机器学习之逻辑回归梯度下降实现代码技术问询
逻辑回归(带L2正则化)梯度下降代码解析
嘿,咱们一步步拆解这段带L2正则化的逻辑回归梯度下降实现代码,每一部分都给你讲明白:
1. 依赖导入与Sigmoid激活函数
首先代码开头导入了numpy——这是Python做数值计算和矩阵操作的核心库:
import numpy as np
然后定义了Sigmoid函数:
def sigmoid(x): return 1.0/(1+np.asmatrix(np.exp(-x)))
Sigmoid的核心作用是把线性回归的输出(可以是任意实数)映射到0到1之间,用来表示样本属于正类的概率。这里用np.asmatrix把np.exp(-x)的结果转成矩阵格式,是为了保证后续和特征矩阵、参数矩阵的运算维度匹配,避免广播错误。
2. 梯度下降主函数graD解析
这个函数是实现梯度下降的核心,先看看它的参数:
X: 特征矩阵,每行是一个样本,每列是一个特征(注意第一列应该是全1的截距项)y: 标签向量,对应每个样本的真实类别(0或1)alpha: 学习率,控制每次参数更新的步长s0: 收敛阈值,当参数的整体变化量小于这个值时,认为模型已经收敛,停止迭代numda: L2正则化的系数,用来防止模型过拟合
函数内部先做初始化:
m=np.size(X,0) # 样本总数,X的行数 n=np.size(X,1) # 特征总数,X的列数 X0=X[:,0] # 提取X的第一列,也就是截距项对应的特征(全1列) X1=X[:,1:] # 提取剩下的所有特征列 theta=np.asmatrix(np.zeros(np.size(X,1))).T # 初始化参数向量为全0,转成列矩阵 s=100 # 参数变化量的初始值,用来判断收敛 lit=0 # 迭代次数计数器
3. 迭代更新逻辑
接下来是核心的迭代循环:
while abs(s)>s0 and lit<=10000: theta0=theta[0] # 单独取出截距项参数 theta1=theta[1:] # 取出其他特征对应的参数 # 更新截距项参数:L2正则化通常不作用于截距项 theta0-=(float(alpha)/m)*X0.T*(sigmoid(X*theta)-y) # 更新其他特征参数:加入L2正则化项 theta1-=float(alpha)*((1.0/m)*X1.T*(sigmoid(X*theta)- y)+float(numda)/m*theta1) # 重新组合更新后的参数向量 theta=np.vstack((np.asmatrix(theta0),np.asmatrix(theta1))) lit+=1 # 迭代次数加1 s=sum((float(1.0)/m)*...) # 计算参数的整体变化量(代码未写完,逻辑是对比当前theta与上一轮的差异)
这里有两个关键的参数更新逻辑:
- 截距项theta0的更新:没有加正则化项,因为截距是全局偏移,正则化它会影响模型的整体预测基准,通常不需要对截距做正则化。更新公式是用残差(预测概率-真实标签)和截距特征的内积,乘以学习率除以样本数,这是无正则化的梯度下降步长。
- 其他参数theta1的更新:加入了L2正则化项
(numda/m)*theta1,这部分的作用是惩罚过大的参数值,让模型更简单,避免过拟合。整体是梯度项(残差与特征的内积除以样本数)加上正则化项,再乘以学习率后从原参数中减去。
循环停止的条件有两个:一是参数变化量的绝对值小于设定的阈值s0(模型收敛),二是迭代次数超过10000(防止因为学习率过小或数据问题导致无限迭代)。
4. 值得注意的细节
- 矩阵格式处理:全程用
np.asmatrix把数组转成矩阵,确保所有运算都是矩阵乘法,避免维度不匹配的问题。 - 正则化的作用:
numda越大,正则化强度越高,参数会越趋近于0,模型复杂度越低,过拟合风险越小,但也可能导致欠拟合。 - 收敛判断:用参数变化量
s来判断收敛,这是梯度下降中常用的方法,比单纯看损失值变化更直接。
内容的提问来源于stack exchange,提问作者Zhihao ZHAO
相关产品推荐
相关产品推荐

