Skip to main content

逻辑回归

逻辑回归

假设你的一个朋友让你回答一道题。

可能的结果只有两种:你答对了或没有答对。

为了研究你最擅长的题目领域,你做了各种领域的题目。

那么这个研究的结果可能是这样的:

如果是一道十年级的三角函数题,你有 70%的可能性能解出它。

但如果是一道五年级的历史题,你会的概率可能只有 30%。

逻辑回归就是给你这样的概率结果。

逻辑回归是一种统计模型,它使用数学中的逻辑函数或 logit 函数作为 x 和 y 之间的方程式。Logit 函数将 y 映射为 x 的 sigmoid 函数。

f(x)=11+exf(x) = \frac{1}{1 + e^{-x}}

多个解释变量会影响因变量的值。要对此类输入数据集建模,逻辑回归公式假设不同自变量之间存在线性关系。您可以修改 sigmoid 函数并按如下公式计算最终输出变量

y=f(β0+β1x1+β2x2+βnxn)y = f(β0 + β1x1 + β2x2+… βnxn)

符号 β 表示回归系数。当您给它一个其中包含因变量和自变量的已知值的足够大的实验数据集时,logit 模型可以反向计算这些系数值。

逻辑回归分类器更接近 KNN,要解决多分类问题时,常常需要针对不同类别分别建立多个模型。

import numpy as np
from matplotlib import pyplot as plt

class Sline:
def __init__(self, data):
self.w = 0
self.b = 0
self.learning_rate = 0.1
self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1)
self.loss_list = []


def get_data(self, data):
self.X = np.array(data)[:, 0]
self.y = np.array(data)[:, 1]

def sigmoid(self, x):
return 1 / (1 + np.exp(-(self.w * x + self.b)))

def train(self, epoch_times):
for epoch in range(epoch_times):
total_loss = 0
for x, y in zip(self.X, self.y):
y_pred = self.sigmoid(x)
# w新 = w旧 - 学习率 * 梯度
grad = -2 * (y - y_pred) * (1 - y_pred) * y_pred * x
self.w = self.w - self.learning_rate * grad * x
# b新 = b旧 - 学习率 * 梯度
self.b = self.b - self.learning_rate * grad
loss = (y - y_pred) ** 2
total_loss += loss
epoch_loss = total_loss / len(self.X)
self.loss_list.append(epoch_loss)
if epoch % 10 == 0:
print(f"loss: {epoch_loss}")
self.plot()
plt.ioff()
plt.show()

def plot(self):
plt.ion() # 启用交互模式
self.ax2.clear()
self.ax1.clear()
x = np.linspace(0, 10, 100)
self.ax1.scatter(self.X, self.y, c="g")
self.ax1.plot(x, self.sigmoid(x), c="b")
self.ax2.plot(list(range(len(self.loss_list))), self.loss_list)
plt.show()
plt.pause(0.1)

if __name__ == "__main__":
# 散点输入
data = [(1, 0), (1.8, 0), (2.5, 0), (4.2, 1), (5, 1), (6, 1), (7, 1)]
s = Sline(data)
s.get_data(data)
s.train(1000)

使用sklearn框架

# 绘制逻辑回归的不同回归系数的sigmoid函数

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(x,p=1):
# 直接返回sigmoid函数
return 1. / (1. + np.exp(-p*x))

def plot_sigmoid(p=1):
# param:起点,终点,间距
x = np.arange(-8, 8, 0.2)
y = sigmoid(x,p)
plt.plot(x, y)
plt.show()

if __name__ == '__main__':
plot_sigmoid()
plot_sigmoid(20)
plot_sigmoid(0.5)
import numpy as np
from sklearn.linear_model import LogisticRegression

# 创建一些示例数据
X = np.array([[1], [2], [3], [4], [5]]) # 自变量
y = np.array([0, 0, 1, 1, 2]) # 因变量,0表示负类,1表示正类

# 创建逻辑回归模型
model = LogisticRegression()

# .fit()方法用于拟合模型,即训练模型x
model.fit(X, y)

# 预测新数据点
new_data_point = np.array([[6]]) # 要预测的新数据点
# .predict()方法预测新数据点的类别
predicted_class = model.predict(new_data_point)
# .predict_proba()方法预测新数据点的概率
predicted_probability = model.predict_proba(new_data_point)

print("预测类别:", predicted_class)
print("预测概率 (负类, 正类):", predicted_probability)
print(type(predicted_probability))
predicted_probability

简单示例

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# 加载数据集
digits = datasets.load_digits()
# 获取特征和目标变量
X = digits.data
y = digits.target

# 数据预处理:随机分割训练集和测试集 , 如果不指定 random_state,每次运行结果都不一样。42为约定俗成的随机数种子
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据标准化
scaler = StandardScaler()
# .fit_transform()方法先拟合数据,再标准化。和降维算法的语法一致
X_train = scaler.fit_transform(X_train)
# .transform()方法直接使用在测试集上进行标准化操作
X_test = scaler.transform(X_test)

# 创建Logistic Regression模型 , 如果不指定 random_state,每次运行结果都不一样。42为约定俗成的随机数种子
model = LogisticRegression(random_state=42)

# .fit()方法用于拟合模型,即训练模型
model.fit(X_train, y_train)

# .predict()方法预测新数据点的类别
y_pred = model.predict(X_test)

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# 加载数据集
digits = datasets.load_digits()
# 获取特征和目标变量
X = digits.data
y = digits.target

# 数据预处理:随机分割训练集和测试集 , 如果不指定 random_state,每次运行结果都不一样。42为约定俗成的随机数种子
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据标准化
scaler = StandardScaler()
# .fit_transform()方法先拟合数据,再标准化。和降维算法的语法一致
X_train = scaler.fit_transform(X_train)
# .transform()方法直接使用在测试集上进行标准化操作
X_test = scaler.transform(X_test)

# 创建Logistic Regression模型 , 如果不指定 random_state,每次运行结果都不一样。42为约定俗成的随机数种子
model = LogisticRegression(random_state=42)

# .fit()方法用于拟合模型,即训练模型
model.fit(X_train, y_train)

# .predict()方法预测新数据点的类别
y_pred = model.predict(X_test)

效果评估

from sklearn.metrics import accuracy_score

# accuracy_score()方法计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy}')

可视化数据-数据转图片

from matplotlib import pyplot as plt
# 选出预测错误的样本
index = []
# 遍历所有样本
for i in range(len(y_pred)):
# 判断是否相等
if y_pred[i] != y_test[i]:
# 如果不相等,添加到index中:预测值,真实值,图片(注意要变换形状为8*8)
index.append((
y_pred[i],
y_test[i],
X_test[i].reshape((8, 8))))

# 创建一个正方形画布
# nrows:子图的行数
# ncols:子图的列数
# print(len(index)) // 10
# 因为一共有10张图片,所以行数为2,列数为5,即2*5=10
fig, ax = plt.subplots(
nrows=3,
ncols=5,
)
# 实例化子画布
ax = ax.flatten()
for i in range(len(index)):
p = index[i][0] # 取出预测值
a = index[i][1] # 取出真实值
img = index[i][2] # 取出图片
# 在子画布上画出图片,格式为灰度图
ax[i].imshow(img, cmap='Greys')
ax[i].set_title(f'{p}-{a}')
plt.show()