本次修炼方法请往下查看
🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地!
🎇 免费获取相关内容文档关注:微信公众号,发送 pandas 即可获取
🎇 相关内容视频讲解 B站
🎓 博主简介:AI算法驯化师,混迹多个大厂搜索、推荐、广告、数据分析、数据挖掘岗位 个人申请专利40+,熟练掌握机器、深度学习等各类应用算法原理和项目实战经验。
🔧 技术专长: 在机器学习、搜索、广告、推荐、CV、NLP、多模态、数据分析等算法相关领域有丰富的项目实战经验。已累计为求职、科研、学习等需求提供近千次有偿|无偿定制化服务,助力多位小伙伴在学习、求职、工作上少走弯路、提高效率,近一年好评率100% 。
📝 博客风采: 积极分享关于机器学习、深度学习、数据分析、NLP、PyTorch、Python、Linux、工作、项目总结相关的实用内容。
文章目录
- 🎯 1. 基本介绍
- 💡 2. 理论介绍
- 🔍 3. 代码实践
- 3.1 自己实现
- 3.2 Sklearn实现
- 3.3 LR重要参数介绍
- 🔍 4. 注意事项
- 🔍 5. 总结
🎯 1. 基本介绍
逻辑回归是一种广泛应用于分类问题的统计方法,特别是在二分类问题中。尽管名字中有“回归”二字,逻辑回归实际上是一种分类算法。在Python的scikit-learn库中,逻辑回归模型通过LogisticRegression类实现,它使用最大似然估计来训练模型。
逻辑回归比较高效,不需要太大计算,不需要对特征进行缩放,容易实现。但是该算法分类效果一般,且不能处理非线性问题,因为它的决策边界是线性的。因此,当数据分界面是线性平面的时候,可以采用该算法进行分类。
个人觉得逻辑回归设计的巧妙一点的地方在于,将wx通过sigmod函数缩放(0,1)之间
,这样就可以通过设置sigmoid的函数值来归为哪类,从而使输出值满足二项分布的条件。
逻辑回归的损失函数为交叉熵损失。这个我个人有这么一个解释:对于分类问题,他的损失函数其实是0-1损失函数,但是这种函数很难进行求解,优化,一般都采用类似趋势的可求导函数进行替代,而逻辑回归则通过极大似然估计来转换成log损失函数来替代0-1损失函数
💡 2. 理论介绍
在线性回归中,我们假设因变量Y和自变量X之间存在以下线性关系:Y = β₀ + β₁X₁ + β₂X₂ + ... + βₙXₙ,
其中β₀是截距,β₁至βₙ是自变量X的系数。通过最小化损失函数来确定最佳的系数估计值。
在博客中我们会详细推导出最小二乘法的公式,这是一种常见的求解线性回归系数的方法。
逻辑回归假设
p
(
y
∣
x
,
θ
)
p(y|x,\theta)
p(y∣x,θ)服从二项分布,同时对
θ
T
x
\theta^Tx
θTx通过函数sigmoid进行数据映射,该函数公式和图表如下所示:
h θ ( x ) = 1 1 + e − z h_{\theta} (x)=\frac{1}{1 + e^{-z}} hθ(x)=1+e−z1
其中 z = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . . . . + θ n x n = θ T x z=\theta_{0} + \theta_{1}x_{1}+\theta_{2}x_{2}+......+\theta_{n}x_{n}=\theta^{T}x z=θ0+θ1x1+θ2x2+......+θnxn=θTx
- 具体的推导过程如下所示:
p ( y = 1 ∣ x ; θ ) = h θ ( x ) p(y=1|x;\theta)=h_{\theta}(x) p(y=1∣x;θ)=hθ(x)
p ( y = 0 ∣ x ; θ ) = 1 − h θ ( x ) p(y=0|x;\theta)=1-h_{\theta}(x) p(y=0∣x;θ)=1−hθ(x)
- 对上面的二项分布的概率函数的具体表达公式如下所示:
p ( y ∣ x ; θ ) = ( h θ ( x ) ) y ∗ ( 1 − h θ ( x ) ) ( 1 − y ) p(y|x;\theta)=(h_{\theta}(x))^y *(1-h_{\theta}(x))^{(1-y)} p(y∣x;θ)=(hθ(x))y∗(1−hθ(x))(1−y)
- 对上面的概率函数通过MLE进行参数估计:
L ( θ ) = ∏ i = 1 m p ( y i ∣ x i ; θ ) L(\theta)=\prod_{i=1}^{m}p(y^{i}|x^{i};\theta) L(θ)=∏i=1mp(yi∣xi;θ)
L ( θ ) = ∏ i = 1 m ( h θ ( x ( i ) ) ) y ( i ) ∗ ( 1 − h θ ( x ( i ) ) ) ( 1 − y ( i ) ) L(\theta)=\prod_{i=1}^{m}(h_{\theta}(x^{(i)}))^{y^{(i)}}*(1-h_{\theta}(x^{(i)}))^{(1-y^{(i)})} L(θ)=∏i=1m(hθ(x(i)))y(i)∗(1−hθ(x(i)))(1−y(i))
- 对上面的似然函数取对数:
l ( θ ) = l o g ( L ( θ ) ) = ∑ i = 1 m y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) l(\theta)=log(L(\theta))=\sum_{i=1}^{m}y^{(i)}log(h_{\theta}(x^{(i)})) + (1-y^{(i)})log(1-h_{\theta}(x^{(i)})) l(θ)=log(L(θ))=∑i=1my(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i)))
- MLE的目的就是求使得 l ( θ ) l(\theta) l(θ)取最大值的 θ \theta θ,由于函数有很好的凹凸性,故可以通过梯度上升法来求得最大值,为了求解的方便可以在前面添加一个负号,近似的求得函数的最优解:
- 梯度下降法来求取 J ( θ ) J(\theta) J(θ)的最小值,其中参数 θ \theta θ的更新过程如下所示:
θ j : = θ j − α ∂ ∂ θ j J ( θ ) \theta_{j}: = \theta_{j}-\alpha\frac{\partial}{\partial \theta_{j}}J(\theta) θj:=θj−α∂θj∂J(θ)
- 其中学习步长为 α \alpha α,具体的求导过程如下所示:
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) 1 h θ ( x i ) ∂ ∂ θ j h θ ( x ( i ) ) − ( 1 − y i ) 1 1 − h θ ( x ( i ) ) ∂ ∂ θ j h θ ( x ( i ) ) ) \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}\frac{1}{h_{\theta}(x^{i})}\frac{\partial}{\partial \theta_{j}}h_{\theta}(x^{(i)})-(1-y^{i})\frac{1}{1-h_{\theta}(x^{(i)})}\frac{\partial}{\partial \theta_{j}}h_{\theta}(x^{(i)})) ∂θj∂=−m1∑i=1m(y(i)hθ(xi)1∂θj∂hθ(x(i))−(1−yi)1−hθ(x(i))1∂θj∂hθ(x(i)))
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) 1 g ( θ T x ( i ) ) − ( 1 − y ( i ) ) 1 1 − g ( θ T x ( i ) ) ) ∂ ∂ θ j g ( θ T x ( i ) ) \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}\frac{1}{g(\theta^{T}x^{(i)})}-(1-y^(i))\frac{1}{1-g(\theta^{T}x^{(i)})})\frac{\partial}{\partial \theta_{j}}g(\theta^{T}x^{(i)}) ∂θj∂=−m1∑i=1m(y(i)g(θTx(i))1−(1−y(i))1−g(θTx(i))1)∂θj∂g(θTx(i))
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) 1 g ( θ T x ( i ) ) − ( 1 − y ( i ) ) 1 1 − g ( θ T x ( i ) ) ) g ( θ T x ( i ) ) ( 1 − g ( θ T x ( i ) ) ) ∂ ∂ θ j θ T \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m} (y^{(i)}\frac{1}{g(\theta^{T}x^{(i)})} - (1-y^{(i)})\frac{1}{1-g(\theta^{T}x^{(i)})})g(\theta^{T}x^{(i)})(1-g(\theta^{T}x^{(i)}))\frac{\partial}{\partial \theta_{j}}\theta^{T} ∂θj∂=−m1∑i=1m(y(i)g(θTx(i))1−(1−y(i))1−g(θTx(i))1)g(θTx(i))(1−g(θTx(i)))∂θj∂θT
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) ( 1 − g ( θ T x ( i ) ) − ( 1 − y ( i ) ) g ( θ T x ( i ) ) ) x j ( i ) \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}(1-g(\theta^{T}x^{(i)})-(1-y^{(i)})g(\theta^{T}x^{(i)}))x_{j}^{(i)} ∂θj∂=−m1∑i=1m(y(i)(1−g(θTx(i))−(1−y(i))g(θTx(i)))xj(i)
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) − g ( θ T x ( i ) ) ) x j ( i ) \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}-g(\theta^{T}x^{(i)}))x_{j}^{(i)} ∂θj∂=−m1∑i=1m(y(i)−g(θTx(i)))xj(i)
∂ ∂ θ j = − 1 m ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x j ( i ) \frac{\partial}{\partial \theta_{j}}=-\frac{1}{m}\sum_{i=1}^{m}(y^{(i)}-h_{\theta}(x^{(i)}))x_{j}^{(i)} ∂θj∂=−m1∑i=1m(y(i)−hθ(x(i)))xj(i)
∂ ∂ θ j = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \frac{\partial}{\partial \theta_{j}}=\frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})x_{j}^{(i)} ∂θj∂=m1∑i=1m(hθ(x(i))−y(i))xj(i)
- 其中对于sigmod函数的求导如下所示,但是由于逻辑回归的函数设定时是带有负号的,所以带入上式计算时需要注意:
f ( x ) = 1 1 + e g ( x ) f(x)=\frac{1}{1+e^{g(x)}} f(x)=1+eg(x)1
∂ ∂ x f ( x ) = − 1 ( 1 + e g ( x ) ) 2 e g ( x ) ∂ ∂ x g ( x ) \frac{\partial}{\partial x}f(x)=-\frac{1}{(1+e^{g(x)})^2}e^{g(x)}\frac{\partial}{\partial x}g(x) ∂x∂f(x)=−(1+eg(x))21eg(x)∂x∂g(x)
∂ ∂ x f ( x ) = − 1 1 + e g ( x ) e g ( x ) 1 + e g ( x ) ∂ ∂ x g ( x ) \frac{\partial}{\partial x}f(x)=-\frac{1}{1+e^{g(x)}}\frac{e^{g(x)}}{1+e^{g(x)}}\frac{\partial}{\partial x}g(x) ∂x∂f(x)=−1+eg(x)11+eg(x)eg(x)∂x∂g(x)
∂ ∂ x f ( x ) = − f ( x ) ( 1 − f ( x ) ) ∂ ∂ x g ( x ) \frac{\partial}{\partial x}f(x)=-f(x)(1-f(x))\frac{\partial}{\partial x}g(x) ∂x∂f(x)=−f(x)(1−f(x))∂x∂g(x)
🔍 3. 代码实践
3.1 自己实现
自行通过python中的numpy库实现LR的代码,具体如下所示:
import numpy as np
def predict(w, x):
'''
w:为训练好的参数w,其数据格式为向量shape(n,m)
x:为预测数据特征,其数据格式为向量shape(n,m)
'''
# 创建sigmod函数形式
z = np.dot(w, x)
p_sigmod = np.exp(z) / (1 + np.exp(z))
# 对sigmod函数输出概率进行判断,将概率等于0.5做为阈值
if p_sigmod <= 0.5:
return 0
else:
return 1
def train(x, y, iter, step):
'''
x:训练数据特征,数据格式为向量shape(n, m)
y:训练数据label,数据格式为向量(n,1)
step:为梯度下降的步长
iter:为梯度下降迭代的次数
'''
# 初始化参数w, 这里没有将参数b加入了,
# 如果要加参数b需要将训练数据增加一个维度
w = np.zeros(x.shape[1])
# 进行iter次随机梯度下降操作
for i in range(iter):
# 每次迭代遍历所以样本进行随机梯度下降算法,每次随机打乱数据的顺序
index= list(range(x.shape[0]))
random.shuffle(index)
for j, idx in enumerate(data_indices):
tmp_x, tmp_y = x[idx], y[idx]
# 根据上面的公式最后的最小似然函数的求导结果为:
# h(xi)* xi- xi * yi, 所以先构建h(xi)
z = np.dot(w, tmp_x)
# 再看上面的梯度下降的算法公式,将构建好的求导结果带入
w -= step *((np.exp(z) / (1 + np.exp(z)))*tmp_x - tmp_x*tmp_y)
# 也可以直接进行梯度下降操作
for i in range(iter):
z = np.dot(w, x)
w -= step *((np.exp(z) / (1 + np.exp(z)))*x- x*y)
return w
3.2 Sklearn实现
我们构建简单的数据集,通过sklearn来实现lr的过程,具体代码如下所示:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
# 加载iris数据集
iris = load_iris()
X, y = iris.data, iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建逻辑回归模型实例
model = LogisticRegression(max_iter=200)
# 训练模型
model.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = model.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
# 打印分类报告
print(classification_report(y_test, y_pred))
print(f"准确率: {accuracy:.2f}")
precision recall f1-score support
0.0 0.00 0.00 0.00 0
1.0 0.00 0.00 0.00 0
2.0 0.83 1.00 0.91 39
...
3.3 LR重要参数介绍
在实际的工作中,lr经常调试的参数如下所示:
-
penalty:
惩罚方式,默认为"l2",可选择"l1"或"elasticnet"。"l1"使用L1范数作为惩罚项,可以产生稀疏解;"l2"使用L2范数作为惩罚项,可以防止过拟合;"elasticnet"是"l1"和"l2"的组合。 -
C:
正则化强度的倒数。与惩罚项相关联,值越小表示更强的正则化。默认为1.0。 -
fit_intercept:
是否计算截距项,默认为True。如果选择False,则模型将不会计算截距。 -
solver:
优化算法,默认为"lbfgs"。可选择"newton-cg"、“sag"或"liblinear”。"lbfgs"适用于小型数据集;"newton-cg"适用于多分类问题;"sag"适用于大型数据集;"liblinear"适用于二分类问题。 -
max_iter:
迭代次数,默认为100。用于控制优化算法的最大迭代次数。 -
multi_class:
多分类问题的处理方式,默认为"auto",可选择"ovr"或"multinomial"。"ovr"使用一对多的方法进行多类别分类,"multinomial"使用Softmax回归进行多类别分类。 -
class_weight:
类别权重,默认为None。可以使用balanced来自动平衡不均衡的类别。
🔍 4. 注意事项
- 逻辑回归假设特征和目标变量之间存在线性关系,即使是在分类问题中。
- 它对异常值不敏感,但对特征的缩放敏感,因此在训练模型前通常需要进行特征标准化或归一化。
- max_iter参数是最大迭代次数,有时可能需要调整以确保模型能够收敛。
- 离散特征的增加和减少都很容易,易于模型快速迭代;
- 稀疏向量内积乘法速廈快,计算结果方便存储,容易扩展;
- 离散化的特征对异常数据有很强的鲁棒性(比如年龄为300异常值可归为年龄>30这一段);
- 逻辑回归属于广义线性模型,表达能力受限。单变量离散化为N个后,每个变量有单独的权重,相当于对模型引入了非线性,能够提升模型表达能力,加大拟合;
- 离散化进行特征交叉,由 M+N 个变量为M*N个变量(将单个特征分成M个取值),进一步引入非线性,提升表达能力;
- 特征离散化后,模型会更稳定(比如对用户年龄离散化,20-30作为一个区间,不会因为用户年龄,增加一岁变成完全不同的人;
- 总得来说就是工业界的做法就是:“海量离散特征+简单模型” 同 “少量连续特征+复杂模型”的权衡
🔍 5. 总结
逻辑回归是处理分类问题的强大工具,特别是在二分类问题中。scikit-learn的LogisticRegression类提供了一个易于使用的接口来训练和预测逻辑回归模型。通过本博客的代码示例,我们学习了如何创建逻辑回归模型,进行训练、预测和评估。希望这篇博客能够帮助你更好地理解逻辑回归模型,并将其应用于实际的分类任务中。