回归分析——逻辑回归
逻辑回归算法原理了解和简单案例引入,方便理解算法原理。同时简单的python代码复现
1. 逻辑回归是干什么的?
逻辑回归是一种用来解决分类问题的算法。比如:
-
判断一封邮件是垃圾邮件还是正常邮件。
-
判断一张图片是猫还是狗。
-
判断一个学生是否能通过考试(通过 or 不通过)。
它的目标是找到一个“分界线”,把不同的类别分开。比如下图:
复制
🐱 🐱 🐱 🐱 🐈 | 🐶 🐶 🐶 🐶
这条竖线就是逻辑回归找到的“分界线”,左边是猫,右边是狗。
2. 逻辑回归是怎么工作的?
逻辑回归的核心思想是:根据输入的数据,计算出一个概率值,然后根据概率值判断属于哪一类。
举个例子:
假设我们要判断一个学生是否能通过考试,输入数据是学生的学习时间,输出是通过(1)或不通过(0)。
-
如果学习时间越长,通过的概率越大。
-
如果学习时间越短,通过的概率越小。
逻辑回归的任务就是找到一个公式,把学习时间映射到通过的概率上。
3.原理
(1) 逻辑回归的“魔法公式”
逻辑回归的核心是一个叫Sigmoid函数的魔法公式,它可以把任意数值变成一个0到1之间的概率值。公式长这样:
其中:

举个例子:
假设我们有一个简单的逻辑回归模型:
-
输入特征:学习时间 x 。
-
权重:ω = 2。
-
偏置:b = −10。
那么公式就是:
-
如果学习时间 x=6小时:
-
-
也就是说,通过考试的概率是88%!
(2)逻辑回归的预测规则
根据概率值 P(y=1),我们可以进行分类预测:

(3)损失函数
逻辑回归的训练目标是找到最优的权重 ω 和偏置 b,使得预测结果尽量接近真实值。这里使用的损失函数是 交叉熵损失函数:
m 样本数量;是第 i 个样本的真实标签;
是模型预测的概率。
(5)梯度下降更新公式
通过梯度下降法,我们可以更新权重 ω 和偏置 b:
α是学习率;和
分别是损失函数对
和 b 的偏导数。
4. 逻辑回归的训练
逻辑回归的模型需要通过学习数据来找到最好的权重 ω 和偏置 b。这个过程叫做训练。
-
训练的目标是让模型的预测结果和真实结果尽量接近。
-
通过不断调整 ω 和 b,模型会变得越来越准。
5. python代码
import numpy as np
from sklearn.model_selection import train_test_split
# 定义Sigmoid函数,用于将线性输出转换为概率输出
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 预测函数,根据输入特征X和模型参数w, b,输出预测结果
def predict(X, w, b):
z = np.dot(X, w) + b # 计算线性输出
y_pred = sigmoid(z) # 将线性输出转换为概率输出
# 将概率转换为类别(0或1),通常设定一个阈值如0.5
y_pred = np.where(y_pred >= 0.5, 1, 0)
return y_pred
# 损失函数(交叉熵损失),用于评估模型性能
def compute_loss(y_true, y_pred):
m = y_true.shape[0] # 样本数量
# 为了避免log(0)的情况,我们在y_pred和1-y_pred中添加了一个很小的数1e-9
loss = -1/m * np.sum(y_true * np.log(y_pred + 1e-9) + (1 - y_true) * np.log(1 - y_pred + 1e-9))
return loss
# 梯度下降更新规则,用于优化模型参数
def gradient_descent(X, y_true, w, b, learning_rate, num_iterations):
m = X.shape[0] # 样本数量
for i in range(num_iterations): # 迭代优化
z = np.dot(X, w) + b # 计算线性输出
y_pred = sigmoid(z) # 计算预测概率
# 计算梯度
dw = np.dot(X.T, (y_pred - y_true)) / m
db = np.sum(y_pred - y_true) / m
# 更新模型参数
w -= learning_rate * dw
b -= learning_rate * db
# 每100次迭代打印一次损失值,用于监控训练过程
if i % 100 == 0:
loss = compute_loss(y_true, predict(X, w, b))
print(f"Iteration {i}: Loss = {loss}")
return w, b
# 示例数据:学生的数学和英语成绩,以及是否通过了考试(1表示通过,0表示未通过)
# 数据格式:[数学成绩, 英语成绩, 是否通过考试]
data = [
[90, 85, 1], # 学生1:数学90,英语85,通过考试
[78, 74, 0], # 学生2:数学78,英语74,未通过考试
[88, 92, 1], # 学生3:数学88,英语92,通过考试
[65, 70, 0], # 学生4:数学65,英语70,未通过考试
[85, 80, 1], # 学生5:数学85,英语80,通过考试
[50, 60, 0], # 学生6:数学50,英语60,未通过考试
[78, 72, 1], # 学生7:数学78,英语72,通过考试
[90, 65, 1], # 学生8:数学90,英语65,通过考试
[62, 58, 0], # 学生9:数学62,英语58,未通过考试
[88, 92, 1], # 学生10:数学88,英语92,通过考试
[55, 45, 0], # 学生11:数学55,英语45,未通过考试
[70, 85, 1], # 学生12:数学70,英语85,通过考试
[48, 52, 0], # 学生13:数学48,英语52,未通过考试
[95, 80, 1], # 学生14:数学95,英语80,通过考试
[68, 76, 1], # 学生15:数学68,英语76,通过考试
[52, 64, 0], # 学生16:数学52,英语64,未通过考试
[82, 79, 1], # 学生17:数学82,英语79,通过考试
[40, 50, 0], # 学生18:数学40,英语50,未通过考试
[75, 65, 1], # 学生19:数学75,英语65,通过考试
[60, 80, 1], # 学生20:数学60,英语80,通过考试
[50, 50, 0] # 学生21:数学50,英语50,未通过考试
]
# 分离特征和标签
X = np.array([d[:2] for d in data]) # 特征:数学和英语成绩
y_true = np.array([d[2] for d in data]).reshape(-1, 1) # 标签:是否通过考试
# 将数据集划分为训练集和测试集(80%训练,20%测试)
X_train, X_test, y_train, y_test = train_test_split(X, y_true, test_size=0.2, random_state=42)
# 添加偏置项(将X的第一列设置为1),这样我们就可以在矩阵乘法中同时考虑权重和偏置
X_train_b = np.c_[np.ones((X_train.shape[0], 1)), X_train]
X_test_b = np.c_[np.ones((X_test.shape[0], 1)), X_test]
# 初始化权重和偏置,使用小的随机数进行初始化
np.random.seed(42) # 为了结果可复现
w = np.random.randn(X_train_b.shape[1], 1) * 0.01
b = 0
# 超参数设置
learning_rate = 0.1 # 学习率,控制参数更新的步长
num_iterations = 1000 # 迭代次数,控制训练过程的轮数
# 训练模型,通过梯度下降优化模型参数
w, b = gradient_descent(X_train_b, y_train, w, b, learning_rate, num_iterations)
# 使用训练好的模型进行预测
y_train_pred = predict(X_train_b, w, b)
y_test_pred = predict(X_test_b, w, b)
# 输出训练集和测试集的预测结果
print("训练集预测:", y_train_pred.flatten())
print("测试集预测:", y_test_pred.flatten())
# 输出结果解释,将预测结果和真实标签进行对比
print("\n训练集结果:")
for i, (pred, true) in enumerate(zip(y_train_pred.flatten(), y_train.flatten())):
print(f"学生 {i+1}: 预测 {'Pass' if pred == 1 else 'Fail'}, 实际 {'Pass' if true == 1 else 'Fail'}")
print("\n测试集结果:")
for i, (pred, true) in enumerate(zip(y_test_pred.flatten(), y_test.flatten())):
print(f"学生 {i+1}: 预测 {'Pass' if pred == 1 else 'Fail'}, 实际 {'Pass' if true == 1 else 'Fail'}")
#运行结果展示;我们这里的数据集比较少,只是为了说明这个例子。实际中数据集体量很大。
Iteration 0: Loss = 6.476020573358253
Iteration 100: Loss = 6.476020573358253
Iteration 200: Loss = 11.656837032844855
Iteration 300: Loss = 6.476020573358253
Iteration 400: Loss = 6.476020573358253
Iteration 500: Loss = 14.247245262588155
Iteration 600: Loss = 6.476020573358253
Iteration 700: Loss = 6.476020573358253
Iteration 800: Loss = 14.247245262588157
Iteration 900: Loss = 7.771224688229903
训练集预测: [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]
测试集预测: [0 0 0 0 0]
训练集结果:
学生 1: 预测 Fail, 实际 Fail
学生 2: 预测 Fail, 实际 Pass
学生 3: 预测 Fail, 实际 Fail
学生 4: 预测 Fail, 实际 Pass
学生 5: 预测 Fail, 实际 Pass
学生 6: 预测 Fail, 实际 Pass
学生 7: 预测 Fail, 实际 Pass
学生 8: 预测 Fail, 实际 Pass
学生 9: 预测 Fail, 实际 Fail
学生 10: 预测 Fail, 实际 Pass
学生 11: 预测 Fail, 实际 Fail
学生 12: 预测 Pass, 实际 Pass
学生 13: 预测 Fail, 实际 Fail
学生 14: 预测 Fail, 实际 Pass
学生 15: 预测 Fail, 实际 Pass
学生 16: 预测 Fail, 实际 Pass
测试集结果:
学生 1: 预测 Fail, 实际 Pass
学生 2: 预测 Fail, 实际 Fail
学生 3: 预测 Fail, 实际 Fail
学生 4: 预测 Fail, 实际 Fail
学生 5: 预测 Fail, 实际 Fail
6. 总结
-
逻辑回归是一种分类算法,用来预测概率。
-
它通过Sigmoid函数把输入映射到0到1之间的概率值。
-
训练过程是调整权重和偏置,让模型更准。
更多推荐


所有评论(0)