逻辑回归的数学公式我大家可以自行研究。这里直接使用sklearn写一个demo
首先我们要了解逻辑回归是预测是与否概率问题的。也就是我们的结果必须是0或1。比如小松鼠今天出门是否找到食物,这个问题和今天的季节天气,外面的其他小动物的行为等因素有关。但是我们已经知道前100次每天的这种数据。我们对这些数据进行逻辑回归分析。
1.创建数据,这里用循环生成px数组,每个数组两个因素,(这里我做演示,随机取的,方便理解,就表示天气指数和外面动物的攻击行为吧),py表示是否找到食物。
random.seed(os.urandom(4))
px = [] # 环境数据
py = [] # 结果
for i in range(100):
px.append([random.random() * 10 - 2, random.random() * 10 - 2])
py.append(random.randint(0, 1))
2.收集数据,用numpy模块统一收集数据
# 自己定义的特征值
X = np.array(px)
# 结果
y = np.array(py)
3.分割训练集和测试集。为什么要这么做呢,因为我们现在还在第一大步骤,就是训练模型。你训练的模型得知道模型的准确率如何。test_size=0.2表示将20%的数据留着不做训练,等训练完了测试用的,看一下这0.2的测试数据和实际的结果是否一致。(因为这20%的数据也是从已知数据中来的)。如果大多一致表示这个模型很准确。random_state表示一个随机数随便填,表示切割的数据两边都一样重复运行不会变。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
4.标准化,将数据按照正态分布归一化,为啥这么做可以自行了解,涉及到数学原理。
# 标准化特征
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
5.创建模型并训练,对train训练集数据训练
# 创建逻辑回归模型并训练
model = LogisticRegression(random_state=1)
model.fit(X_train, y_train)
6.预测测试集数据。将20%的数据代入训练好的模型看看准确率
# 进行预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
7.打印评估模型分数。通过观察发现两点
1:ROC曲线面积越大模型越精确
2:正确的比例越大模型越好
3:精确率和召回率的调和平均数 [0-1] 越大模型越好
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, y_pred_proba)
conf_matrix = confusion_matrix(y_test, y_pred)
print(f"正确的比例: {accuracy}")
print(f"精确度: {precision}")
print(f"召唤率(正确样本比例): {recall}")
print(f"精确率和召回率的调和平均数: {f1}")
print(f"ROC曲线面积: {roc_auc}")
8.将ROC曲线可视化
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
plt.figure()
plt.plot(fpr, tpr, color='blue',)
plt.rcParams['font.sans-serif'] = ['SimSun'] # 指定默认字体为宋体
plt.plot([0, 1], [0, 1], color='red')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.xlabel('环境变量')
plt.ylabel('结果')
plt.title('逻辑回归图形结果分析')
plt.show()
9.运行看一下
正确的比例: 0.65
精确度: 0.65
召唤率(正确样本比例): 1.0
精确率和召回率的调和平均数: 0.7878787878787878
ROC曲线面积: 0.6703296703296703
如下如,真确率0.65,还凑合。
============================分割线================================
再次运行看看
正确的比例: 0.4
精确度: 0.3888888888888889
召唤率(正确样本比例): 0.875
精确率和召回率的调和平均数: 0.5384615384615384
ROC曲线面积: 0.5625
这时候正确率就低了。因为是随机数所以没办法还原之前的数据。
10.分析和应用。当发现正确率比较高的时候,就表示你的原始数据px的线性程度较高。可预测性强。你就可以用这个数据模型进行预测了。如下假设随便输入当前的环境来预测
# 真正开始预测
new_pred = model.predict(np.array([[2.32144, 1.2314]]))
new_pred_proba = model.predict_proba([[2.32144, 1.2314]])[:, 1]
print(f"预测下次兔子出门能否找到食物:{new_pred}")
print(f"预测下次兔子出门能否找到食物预测精确度:{new_pred_proba}")
返回:
预测下次兔子出门能否找到食物:[1]
预测下次兔子出门能否找到食物预测精确度:[0.50552854]
1表示可以找到,但是精确率是0.5.。
完整代码如下:
import os
import random
import numpy as np
from matplotlib import pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, confusion_matrix, roc_curve
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
random.seed(os.urandom(4))
px = [] # 环境数据
py = [] # 结果
for i in range(100):
px.append([random.random() * 10 - 2, random.random() * 10 - 2])
py.append(random.randint(0, 1))
# 自己定义的特征值
X = np.array(px)
# 结果
y = np.array(py)
# test_size是测试集合大小的比例
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
# 标准化特征
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 创建逻辑回归模型并训练
model = LogisticRegression(random_state=1)
model.fit(X_train, y_train)
# 进行预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, y_pred_proba)
conf_matrix = confusion_matrix(y_test, y_pred)
print(f"正确的比例: {accuracy}")
print(f"精确度: {precision}")
print(f"召唤率(正确样本比例): {recall}")
print(f"精确率和召回率的调和平均数: {f1}")
print(f"ROC曲线面积: {roc_auc}")
print(f"Confusion Matrix: {conf_matrix}")
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()
# 真正开始预测
new_pred = model.predict(np.array([[2.32144, 1.2314]]))
new_pred_proba = model.predict_proba([[2.32144, 1.2314]])[:, 1]
print(f"预测下次兔子出门能否找到食物:{new_pred}")
print(f"预测下次兔子出门能否找到食物预测精确度:{new_pred_proba}")