逻辑回归 Logistic Regression
1 原理
1.1 分类问题
目标是面对某种事物,估计它的可能性,判断属于哪种已知的样本类,比如买不买某种东西、是不是垃圾邮件等。类别的数量可以有很多,所以按数量可以分为二分类(binary classification)和多元分类(multiclass classification)。但是对于多分类问题也可以通过OvR、OvO等一些策略方法转为二分类问题。
1.1.1 OvR(One vs Rest)
一对剩余的所有,也可能叫OvA。总之思路就是假如有四个类别,选中一个类别One,剩余的三个都看作是其他类别Rest,于是四个类别的问题就变成了One和Rest的问题。因此,每有一个这样的One就会有对应的一个二分类,所以按照假设,我们得到了四个二分类问题。
进一步的,在训练过程中,将数据集分成4份,每一份都转换为对应的二分类数据集。然后将每一份都使用一个单独的分类器进行训练,就会得到相对应的测试样本为对应的One的概率。最后,我们选取概率值最大的类别作为测试样本的最终类别。
1.1.2 OvO(One vs One)
一对一。思路是假如有四个类别,直接挑出两个,然后对这两个进行二分类。于是,就会有 C 4 2 C_4^2 C42 =6个两两分类问题,即6个二分类任务。进而得到6个分类结果,然后对结果进行投票来选择分类结果数量最多的类别作为最终类别。
1.1.3 逻辑回归
OvO和OvR根据任务数量在时间上有差异;OvO分类结果会更加准确,因为其保留了真实的类别信息,而OvR将剩余的类别都保留混淆了类别信息。
#sklearn的逻辑回归模型的multi_class超参数可设置分类方式
LogisticRegression(multi_class='ovr')
LogisticRegression(multi_class='multinomial')
逻辑回归是一种解决二分类问题的机器学习方法,即给定输入的x,判断它的标签是A还是B。
1.2 具体过程
1.2.1 如何二分类
可以设置一个阈值,如果预测的数值大于阈值,那么就属于A;反之属于B。
还可以去预测标签为A的概率,若概率大于0.5,则认为是A;反之是B。
1.2.2 如何得到概率
概率的区间是[0,1],但线性模型 f ( x ) = w T x f(x)=w^Tx f(x)=wTx 的值域是 ( − ∞ , + ∞ ) (-\infty,+\infty) (−∞,+∞) 。所以需要把线性模型的预测进一步处理,找到一个值域在[0,1]区间的模型。于是选择了sigmoid函数。
1.2.3 Sigmoid函数
公式如下:
g
(
z
)
=
1
1
+
e
−
z
g(z) = \frac {1} {1+e^{-z}}
g(z)=1+e−z1
函数图像如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sOGnN6EN-1602667869838)(D:\kaikeba\第十六章 逻辑回归模型\第一节 逻辑回归模型\sigmoid函数图像.png)]
由图像可以看出,sigmoid函数是一个值域为[0,1]的“s”形曲线,且 lim x → − ∞ g ( z ) = 0 \lim\limits_{x\rightarrow-\infty}{g(z)}=0 x→−∞limg(z)=0 , lim x → + ∞ g ( z ) = 1 \lim\limits_{x\rightarrow+\infty}{g(z)}=1 x→+∞limg(z)=1 。在 ( − ∞ , + ∞ ) (-\infty,+\infty) (−∞,+∞) 上单调增。
求导有:
g
′
(
z
)
=
−
(
1
1
+
e
−
z
)
2
∗
(
−
1
)
∗
(
e
−
z
)
=
e
−
z
(
1
+
e
−
z
)
2
=
1
+
e
−
z
−
1
(
1
+
e
−
z
)
2
=
1
1
+
e
−
z
−
1
(
1
+
e
−
z
)
2
=
1
1
+
e
−
z
(
1
−
1
1
+
e
−
z
)
=
g
(
z
)
(
1
−
g
(
z
)
)
g'(z) = -(\frac{1}{1+e^{-z}})^2*(-1)*(e^{-z})\\ = \frac{e^{-z}}{({1+e^{-z}})^2}\\ =\frac{1+e^{-z}-1}{({1+e^{-z}})^2}\\ = \frac{1}{{1+e^{-z}}}-\frac{1}{({1+e^{-z}})^2}\\ = \frac{1}{{1+e^{-z}}}(1-\frac{1}{{1+e^{-z}}})\\ =g(z)(1-g(z))
g′(z)=−(1+e−z1)2∗(−1)∗(e−z)=(1+e−z)2e−z=(1+e−z)21+e−z−1=1+e−z1−(1+e−z)21=1+e−z1(1−1+e−z1)=g(z)(1−g(z))
1.2.4 逻辑回归模型
将
z
=
w
T
x
z=w^Tx
z=wTx 代入sigmoid函数,就得到了逻辑回归模型:
y
=
g
(
w
T
x
)
=
1
1
+
e
−
w
T
x
y = g(w^Tx) = \frac{1}{1+e^{-w^Tx}}
y=g(wTx)=1+e−wTx1
2 损失函数
为了得到训练好的参数w,我们应该最优化模型的损失函数。
2.1 似然(likelihood)
概率是特定环境下某种事件发生的可能性,是在结果产生之前的预测。
似然与其相反,是在确定的结果下推测产生这个结果的可能环境即参数。
比如抛硬币,根据硬币均匀的性质我们推测任何一面朝上的概率均为50%。当随机抛掷一枚硬币1000次,结果500次朝上,500次朝下,那么就容易判断这枚硬币性质均匀,两面朝上概率50%。
因此,设
θ
\theta
θ 为参数,x表示结果,那么概率为:
P
(
x
∣
θ
)
P(x|\theta)
P(x∣θ)
相对应的似然为:
L
(
θ
∣
x
)
L(\theta |x)
L(θ∣x)
则两者在数值上有:
L
(
θ
∣
x
)
=
P
(
x
∣
θ
)
L(\theta |x)=P(x|\theta)
L(θ∣x)=P(x∣θ)
机器学习中更关注似然函数最大值,因为我们的目的是预测某种事件发生的概率,因此我们希望得到导致这个概率的最有可能的条件,即根据已知的事件来找出产生这种结果的最有可能的参数,即似然函数最大值。
2.2 损失函数
损失函数衡量当前的模型输出结果跟实际的输出结果之间的差距,那么根据似然和概率的关系,这里的损失函数的值等于事件发生的总概率,损失函数就是似然函数,因为我们更关注似然函数的最大值,但损失的含义和最大有点不搭,所以给似然函数前加个负号,这样似然函数取最大即损失函数最小。
由于标签只有0和1,因此对于输入的一个样本,看成一个事件的话,设标签为1的概率是p,则
P
y
=
1
=
1
1
+
e
−
w
T
x
=
p
P
y
=
0
=
1
−
p
P_{y=1} = \frac{1}{1+e^{-w^Tx}} = p\\ P_{y=0} = 1-p
Py=1=1+e−wTx1=pPy=0=1−p
那么事件发生的概率就是:
P
(
y
∣
x
)
=
f
(
x
)
=
{
p
y
=
1
1
−
p
y
=
0
P(y|x) = f(x) = \begin{cases} \quad p \qquad \ \ \ y=1 \\ 1-p\qquad y=0 \end{cases}
P(y∣x)=f(x)={p y=11−py=0
即
P
(
y
i
∣
x
i
)
=
p
y
i
(
1
−
p
)
1
−
y
i
P(y_i|x_i) = p^{y_i}(1-p)^{1-y_i}
P(yi∣xi)=pyi(1−p)1−yi
因此,当有一组采集得到的N个数据 { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . ( x n , y n ) } \{(x_1,y_1),(x_2,y_2),...(x_n,y_n) \} {(x1,y1),(x2,y2),...(xn,yn)} ,他们的总概率,即采集到这组样本的概率:
P
总
=
P
(
y
1
∣
x
1
)
P
(
y
2
∣
x
2
)
.
.
.
P
(
y
n
∣
x
n
)
=
∏
i
=
1
n
p
y
i
(
1
−
p
)
1
−
y
i
P_总 = P(y_1|x_1)P(y_2|x_2)...P(y_n|x_n)\\ = \prod_{i=1}^np^{y_i}(1-p)^{1-y_i}
P总=P(y1∣x1)P(y2∣x2)...P(yn∣xn)=i=1∏npyi(1−p)1−yi
两边取对数有:
F
(
w
)
=
ln
(
P
总
)
=
ln
(
∏
i
=
1
n
p
y
i
(
1
−
p
)
1
−
y
i
)
=
∑
i
=
1
n
ln
[
p
y
i
(
1
−
p
)
1
−
y
i
]
=
∑
i
=
1
n
[
y
i
ln
p
+
(
1
−
y
i
)
ln
(
1
−
p
)
]
F(w) = \ln(P_总) = \ln(\prod_{i=1}^np^{y_i}(1-p)^{1-y_i})\\ =\sum_{i=1}^n\ln[{p^{y_i}(1-p)^{1-y_i}]}\\ =\sum_{i=1}^n[y_i\ln{p}+(1-y_i)\ln(1-p)]
F(w)=ln(P总)=ln(i=1∏npyi(1−p)1−yi)=i=1∑nln[pyi(1−p)1−yi]=i=1∑n[yilnp+(1−yi)ln(1−p)]
F ( w ) F(w) F(w) 就是逻辑回归模型的损失函数,因此现在的问题就变为了找到 w ∗ w^* w∗ 使得 F ( w ) F(w) F(w) 取最大,即 − F ( w ) -F(w) −F(w) 取最小。
3 梯度下降法求解
为求出 w ∗ w^* w∗ ,使用梯度下降法。
3.1 梯度下降法
多元函数
f
(
x
)
=
f
(
x
1
,
x
2
,
.
.
.
,
x
n
)
f(x) = f(x_1,x_2,...,x_n)
f(x)=f(x1,x2,...,xn) ,其梯度为:
∇
f
(
x
)
=
(
∂
f
(
x
)
∂
x
1
,
∂
f
(
x
)
∂
x
2
,
.
.
.
,
∂
f
(
x
)
∂
x
n
)
\nabla f(x) = \left(\frac {\partial f(x)}{\partial x_1},\frac {\partial f(x)}{\partial x_2},...,\frac {\partial f(x)}{\partial x_n}\right)
∇f(x)=(∂x1∂f(x),∂x2∂f(x),...,∂xn∂f(x))
不难看出梯度方向是函数增长速度最快的方向,反之是函数减少速度最快的方向,因为它是由函数对各个x求偏导(在对应x上的切线方向)得到的。
因此如果要计算一个函数的最小值,可以从一个初始点
x
(
0
)
=
(
x
1
(
0
)
,
.
.
.
,
x
n
(
0
)
)
x^{(0)}=(x_1^{(0)},...,x_n^{(0)})
x(0)=(x1(0),...,xn(0)) 开始,基于学习率
η
\eta
η > 0(可以理解为前进的幅度),当
i
≥
0
i\geq 0
i≥0 时,沿梯度反方向即下降方向不断迭代:
x
1
(
i
+
1
)
=
x
1
(
i
)
−
η
⋅
∂
f
(
x
(
i
)
)
∂
x
1
,
.
.
.
x
n
(
i
+
1
)
=
x
n
(
i
)
−
η
⋅
∂
f
(
x
(
i
)
)
∂
x
n
.
x_1^{(i+1)} = x_1^{(i)}-\eta \ \cdot \ \frac {\partial f(x^{(i)})}{\partial x_1} ,\\ ...\\ x_n^{(i+1)} = x_n^{(i)}-\eta \ \cdot \ \frac {\partial f(x^{(i)})}{\partial x_n}.
x1(i+1)=x1(i)−η ⋅ ∂x1∂f(x(i)),...xn(i+1)=xn(i)−η ⋅ ∂xn∂f(x(i)).
因此,
x
i
+
1
=
g
(
x
(
i
)
)
x^{i+1} = g(x^{(i)})
xi+1=g(x(i))
迭代关系为:
g
(
x
)
=
x
−
η
∇
f
(
x
)
g(x) = x - \eta \nabla f(x)
g(x)=x−η∇f(x)
3.2 求解
为消除样本个数的影响,损失函数的形式稍微改变为损失函数除以样本个数:
F
(
w
)
=
−
1
N
∑
i
=
1
n
[
y
i
ln
p
+
(
1
−
y
i
)
ln
(
1
−
p
)
]
F(w) = -\frac{1}{N}\sum_{i=1}^n[y_i\ln{p}+(1-y_i)\ln(1-p)]
F(w)=−N1i=1∑n[yilnp+(1−yi)ln(1−p)]
根据复合函数的链式求导法则:
∇
F
(
w
)
=
F
′
(
p
)
∗
p
′
(
w
)
\nabla F(w) = F'(p)\ * \ p'(w)
∇F(w)=F′(p) ∗ p′(w)
F
′
(
p
)
F'(p)
F′(p) :
F
’
(
p
)
=
−
1
N
∑
i
=
1
n
(
y
i
p
−
1
−
y
i
1
−
p
)
F’(p) = -\frac{1}{N}\sum_{i=1}^n\left(\frac{y_i}{p}-\frac{1-y_i}{1-p}\right)
F’(p)=−N1i=1∑n(pyi−1−p1−yi)
p
′
(
w
)
p'(w)
p′(w) :
p
=
1
1
+
e
−
w
T
x
p
′
(
w
)
=
p
(
1
−
p
)
x
p = \frac{1}{1+e^{-w^Tx}}\\ p'(w) = p(1-p)x
p=1+e−wTx1p′(w)=p(1−p)x
∇
F
(
w
)
\nabla F(w)
∇F(w) :
∇
F
(
w
)
=
−
1
N
∑
i
=
1
n
[
y
i
(
1
−
p
)
−
p
(
1
−
y
i
)
]
x
i
=
−
1
N
∑
i
=
1
n
(
p
−
y
i
)
x
i
\nabla F(w) =-\frac{1}{N}\sum_{i=1}^n[y_i(1-p)-p(1-y_i)]x_i\\ =-\frac{1}{N}\sum_{i=1}^n(p-y_i)x_i
∇F(w)=−N1i=1∑n[yi(1−p)−p(1−yi)]xi=−N1i=1∑n(p−yi)xi
初始化一个
w
0
w_0
w0 ,然后给定一个步长
α
\alpha
α ,通过不断修改
w
t
w_t
wt ,利用梯度下降的方法,不断迭代,直到达到指定的次数或梯度为0。
迭代过程:
w
t
+
1
=
w
t
−
α
∇
F
(
w
t
)
=
w
t
−
α
1
N
∑
i
=
1
n
(
p
−
y
i
)
x
i
w_{t+1} = w_t - \alpha \nabla F(w_t) \\ = w_t -\alpha\frac{1}{N}\sum_{i=1}^n(p-y_i)x_i
wt+1=wt−α∇F(wt)=wt−αN1i=1∑n(p−yi)xi
4 代码实现
以scikit-learn上的乳腺癌数据集为例:
from sklearn import datasets # 导入数据集
from sklearn.model_selection import train_test_split,GridSearchCV # 导入用于切分数据集的api和用于寻找最优模型和参数的网格搜索
from sklearn.linear_model import LogisticRegression # 导入逻辑回归模型
from sklearn.pipeline import Pipeline # 导入管道
from sklearn.preprocessing import PolynomialFeatures,StandardScaler # 导入用于构造多项式特征的api和将数据归一化处理的api
import numpy as np
cancer = datasets.load_breast_cancer() # 导入指定的数据集
X = cancer.data # 获得数据
y = cancer.target # 获得标签
print(X.shape) # (569, 30) 569个样本,每个样本有30个特征
print(y[y==1].shape[0],y[y==0].shape[0]) # (357, 212)
X_train,X_test,y_train,y_test = train_test_split(
X,y,test_size=0.2,random_state=666
) # 按照8:2分割数据集,得到训练集和测试集
def pipeRegression(degree=1,penalty='l2',C=0.1,solver='lbfgs'):
return Pipeline([
('poly',PolynomialFeatures(degree=degree)),
('scaler',StandardScaler()),
('logist_regression',LogisticRegression(penalty=penalty,C=C,solver=solver))
]) # 利用管道机制,把构造多项式特征、归一化、逻辑回归模型封装到一起
print(pipeRegression().get_params()) # 可以查看所有参数
param_grid = [
{
'poly__degree':[ i for i in range(1,3)], # 构造的多项式特征数量
'logist_regression__penalty':['l1','l2'], # 逻辑回归中为了防止过拟合选择的正则化方法
'logist_regression__C':[i for i in np.linspace(0.1,1,10)], # 正则化中的参数
'logist_regression__solver':['liblinear','lbfgs','newton-cg','sag'] # 正则化对应的逻辑回归损失函数的优化算法
}
] # 网格搜索要寻找的超参数范围设置
gs_pipe = GridSearchCV(pipeRegression(),param_grid) # 实例化一个网格搜索对象
gs_pipe.fit(X_train,y_train) #调用fit方法进行训练
print(gs_pipe.best_estimator_) # 获取训练得到的最优模型
print(gs_pipe.best_params_) # 获取最优的超参数
print(gs_pipe.best_score_) # 获取最优的预测准确度
print(gs_pipe.best_estimator_.score(X_test,y_test)) # 输出最优模型在测试集上的得分