本文用python代码实现了利用梯度下降法训练线性回归模型
该实验的Github链接:dingdingqiuqiu/ML
文中重敲的代码可能有问题,但github上的一定都是可运行的
必备库导入
1 | # 导入必要的库 |
np
库进行矩阵运算,plt
模块进行2D绘图,mpl
库用于更复杂3D图像的绘制。而accuracy_score
函数则是sklearn
包里的metrics
模块中的用于评估机器学习中模型性能指标的函数。
读取数据文件并绘图
我们从代码入手,探讨项目文件的读取逻辑
1 | # 加载数据 |
代码第一行加载数据,将除了最后一列的数据作为X矩阵,即特征矩阵,将最后一列数据作为标签向量,并重塑为二维矩阵,方便运算。
我们来尝试数据图的绘制部分
1 | def plot(X, y): |
先保存正负样本点的索引,然后在以特征矩阵X中的正负样本的第一列特征和第二列特征为x和y将点绘制为’x’和’o’设置对应标签,添加x轴的标签和y轴的标签并显示前面正负标签的图例。
初始状态设置
1 | X, y = loaddata() # 再次加载数据 |
进行了各个参数的初始化,主要包括theta和iterations以及alpha。
梯度下降
1 | theta = gradientDescent(X, y, theta, iterations, alpha) # 执行梯度下降 |
调用了gradientDescent函数,我们来看函数的定义过程。
1 | def gradientDescent(X, y, theta, iterations, alpha): |
首先先给特征矩阵前添加了一列1,这是为了方便偏置项b的计算。然后,进行参数迭代更新,在每次更新时,计算梯度,并更新参数。同时每10000次输出一次损失值。下面我们深度分析梯度更新时的参数计算过程
1 | theta_temp = theta - (alpha / m) * np.dot(X.T, (hypothesis(X, theta) - y)) # 梯度下降更新 |
此处计算时,主要计算思路与线性方程的梯度下降计算过程基本一致,不过在进行假设函数值的计算时,我们引入了sigmoid
函数,主要是将函数的输出映射到[0,1]之间,用来表示某样本是否属于正类的概率,同时可以利用非线性映射拟合更复杂的决策边界。由于引入了sigmoid
函数,在计算损失函数时,计算过程也略有改变,如下:1
2
3
4
5
6
7
8
9def computeCost(X, y, theta):
m = X.shape[0] # 样本数
z = hypothesis(X, theta) # 计算假设值
# 限制 z 的范围以避免取对数时出现问题
epsilon = 1e-15
z = np.clip(z, epsilon, 1 - epsilon)
# 计算代价函数
cost = -np.sum(y * np.log(z) + (1 - y) * np.log(1 - z)) / m # 代价公式
return cost
我们利用交叉熵损失来描述损失,这里主要是交叉熵损失的计算公式。
决策边界的绘制
1 | def plotDescisionBoundary(X, y, theta): |
这段代码通过逻辑回归模型的参数 theta
,在二维特征空间中绘制样本的散点图并显示决策边界。首先,样本点根据不同类别(y
)使用绿色和红色区分,并标注坐标轴。然后,通过决策边界方程
预测函数
1 | def predict(X): |
根据训练得到的theta参数,我们可以通过对输入的数据添加全1列来完成对新样本的预测。
理论支撑
在逻辑回归的梯度下降算法中,参数更新的核心是通过最小化损失函数来调整模型参数
1. 假设函数
在逻辑回归中,模型的假设函数
其中,
对应的代码解释:
1 | def hypothesis(X, theta): |
此函数通过特征矩阵
2. 代价函数(Cost Function)
逻辑回归的目标是最小化代价函数,其形式为:
其中:
是样本数量 是第 个样本的预测值 是第 个样本的实际标签
代价函数用于衡量预测值
对应的代码解释:
1 | def computeCost(X, y, theta): |
在这里,通过 np.clip(z, epsilon, 1 - epsilon)
防止 z
取 0 或 1,从而避免对数函数取值为负无穷大的错误。computeCost
函数根据给定的参数
3. 梯度下降更新规则
为了最小化代价函数
其中,
4. 梯度的计算
代价函数
推导步骤:
- 代价函数
包含 ,其中 是 Sigmoid 函数。对 求导数时,使用链式法则:
- 代价函数关于
的偏导数最终简化为:
这表示模型预测值与真实值之间的误差,用以调整参数。
5. 梯度下降的参数更新公式
最终,梯度下降更新参数的公式为:
向量化表示形式:
6. 完整的梯度下降步骤
- 计算假设函数:
- 计算代价函数
- 计算梯度:
- 更新参数:
通过迭代上述过程,参数
1 | theta_temp = theta - (alpha / m) * np.dot(X.T, (hypothesis(X, theta) - y)) # 梯度下降更新 |
这段代码实现了向量化形式的参数更新公式:
theta_temp
计算预测值。 np.dot(X.T, (hypothesis(X, theta) - y))
计算梯度。alpha / m
表示学习率和样本数 。
通过这一步,更新后的参数
7. 绘制决策边界
在训练逻辑回归模型后,通常需要绘制决策边界,以展示模型如何将特征空间划分为不同类别。假设逻辑回归模型的决策边界是线性分割,公式为:
通过解这个方程,我们可以得到
对应以下代码
1 | x2 = -(theta[0] + theta[1] * x1) / theta[2] # 决策边界方程 |
此代码通过计算