逻辑回归(Logistic Regression)是机器学习中的一种分类模型,判别模型,由于算法的简单和高效,在实际中应用非常广泛。本文将详细的梳理Logistic Regression的Logistic函数,代价函数,梯度下降以及应用探讨等方面进行梳理
模型-----sigmoid 函数
在这里我默认大家知道了线性回归模型:
y
=
w
T
x
+
b
y= {w^Tx + b}
y=wTx+b
另外:对数几率函数(Logistic)是一种“Sigmoid”函数
g
(
x
)
=
1
1
+
e
−
t
g(x)=\frac{1}{1+{e^{-t}}}
g(x)=1+e−t1
sigmoid函数的函数曲线为:
y = g ( w T x + b ) = 1 1 + e − w T x + b y=g(w^Tx+b)=\frac{1}{1+{e^{-{w^Tx + b}}}} y=g(wTx+b)=1+e−wTx+b1
通过以上的组合,我们可以将,一个线性回归模型的没有具体值域范围的y值,映射到[0,1]之间,根据y的结果判断分类的类别。
模型-----决策函数
一个机器学习模型,实际上是把决策函数限定在某一组条件下,这组限定条件就决定了模型的假设空间。我们还希望这组限定条件简单而合理。逻辑回归模型所做的假设是:
P ( y = 1 ∣ x ; w ) = g ( w T x + b ) = 1 1 + e − w T x + b P(y=1|x;w)=g(w^Tx+b)=\frac{1}{1+{e^{-{w^Tx + b}}}} P(y=1∣x;w)=g(wTx+b)=1+e−wTx+b1
则决策函数为:
y
∗
=
1
,
i
f
P
(
y
=
1
∣
x
)
>
0.5
y∗=1, if P(y=1|x)>0.5
y∗=1,ifP(y=1∣x)>0.5
选择0.5作为阈值是普遍做法,对正反两类都不偏倚。但是,根据实际模型的需求,这个阈值是可以调整的,例如,模型偏重于精准,那么,我们就可以提升这阈值,如果偏重于召回,我们也可以调小这个阈值。
模型-----代价函数定义
所谓的代价(cost)就是,预测值与真实标签的差值,差值越小,理论上分类效果或者拟合效果越好,如果没有过拟合发生的话。
对于逻辑回归来说,我们定义预测结果为
y
^
\hat{y}
y^,
0
=
<
y
^
<
=
1
0=<\hat{y}<=1
0=<y^<=1,那么,逻辑回归的代价可以定义为一下两种情况:
C
o
s
t
=
{
−
l
o
g
(
y
^
)
i
f
:
y
^
=
1
−
l
o
g
(
1
−
y
^
)
i
f
:
y
^
=
0
Cost=\begin{cases} -log(\hat{y}) & if:\quad\hat{y}=1\\ -log(1-\hat{y}) & if:\quad\hat{y}=0 \end{cases}
Cost={−log(y^)−log(1−y^)if:y^=1if:y^=0
那么为什么选择这两个式子作为代价公式,我们绘制了下
−
l
o
g
(
x
)
-log(x)
−log(x)和
−
l
o
g
(
1
−
x
)
-log(1-x)
−log(1−x)的曲线图,如下图所示:
从曲线我们可以看出:当预测结果
y
^
\hat{y}
y^值正确使(0或1与标签相同),代价(cost)等于0;但是当预测结果
y
^
\hat{y}
y^与标签有偏差时,就会产生一定值得代价,特别是完全预测错误,即标签为0预测为1,或者相反的情况的代价就是无穷大。
我们画曲线的代码为:
import numpy as np
import matplotlib.pyplot as plt
#画对应曲线
x=np.linspace(-1,2, 1000)
y1=[-(np.log10(a)) for a in x]
y2=[-(np.log10(1-a)) for a in x]
plot1=plt.plot(x,y1,'-g',label="-log(x)")
plot2=plt.plot(x,y2,'-r',label="-log(1-x)")
#改写坐标轴
new_ticks1 = np.linspace(-1,2,4)
plt.xticks(new_ticks1)
plt.yticks([-2,0,2,5])
ax = plt.gca()
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
ax.spines['bottom'].set_position(('data',0))
#画蓝色辅助线
x3 = np.linspace(1,1,500)
y3 = np.linspace(-1,4,500)
plot2=plt.plot(x3,y3,'-b',label="x=1")
plt.legend(loc='log(x)')
plt.show()
目前,cost是一个分段函数,但是我们在优化的时候最好是一个函数,才能较好的对其进行迭代优化。
我们写成如下形式:
c
o
s
t
=
−
y
l
o
g
(
y
^
)
−
(
1
−
y
)
l
o
g
(
1
−
y
^
)
cost=-ylog(\hat{y})-(1-y)log(1-\hat{y})
cost=−ylog(y^)−(1−y)log(1−y^)
现在我们和上一个式子进行对比,可以发现,当
y
=
0
y=0
y=0时,上述公式前部分为0,当
y
=
1
y=1
y=1时,上述公式后半部分为0。与前一个公式恰好相同,这里反而在一个公式中可以一起进行迭代。
那么,现在
y
^
\hat{y}
y^是什么呢?我们将其带入上述等式中,就可以完整的写出代价函数。
J
(
w
)
=
−
y
l
o
g
(
1
1
+
e
−
w
T
x
+
b
)
−
(
1
−
y
)
l
o
g
(
1
−
1
1
+
e
−
w
T
x
+
b
)
J(w) = -ylog(\frac{1}{1+{e^{-{w^Tx + b}}}})-(1-y)log(1-\frac{1}{1+{e^{-{w^Tx + b}}}})
J(w)=−ylog(1+e−wTx+b1)−(1−y)log(1−1+e−wTx+b1)
这里是一个都是非向量化形式进行的书写。那么如果我们写成向量形式,就是如下形式:
J
(
W
)
=
−
Y
l
o
g
(
1
1
+
e
−
W
T
X
)
−
(
1
−
Y
)
l
o
g
(
1
−
1
1
+
e
−
W
T
X
)
J(W) = -Ylog(\frac{1}{1+{e^{-{W^TX }}}})-(1-Y)log(1-\frac{1}{1+{e^{-{W^TX }}}})
J(W)=−Ylog(1+e−WTX1)−(1−Y)log(1−1+e−WTX1)
我们把所有的小写字母都变成了大写字母,这样表示为向量,另外,我们把
b
b
b都去掉了,因为常数项我们可以认为是
x
=
1
x=1
x=1,然后也作为
X
X
X的
x
0
x_0
x0项就可以,这样公式推导较为清晰。
知道代价函数之后,一般我们会使用梯度下降法来寻找最优解,常用的方法就是梯度下降法,因此,推导它的梯度,对于程序的理解和撰写十分重要。
今天我们就非常详细的一步一步的推到一下这个函数的梯度公式,推出公式后,写程序时,我们就可以直接使用了。
模型-----参数计算之梯度推导
J
(
W
)
=
−
1
m
∑
i
=
0
N
(
Y
l
o
g
(
1
1
+
e
−
W
T
X
)
−
(
1
−
Y
)
l
o
g
(
1
−
1
1
+
e
−
W
T
X
)
)
J(W) = -\frac{1}{m}\sum_{i=0}^N(Ylog(\frac{1}{1+{e^{-{W^TX }}}})-(1-Y)log(1-\frac{1}{1+{e^{-{W^TX }}}}))
J(W)=−m1i=0∑N(Ylog(1+e−WTX1)−(1−Y)log(1−1+e−WTX1))
这里的N是指N个样本。这里对这个式子进行详细的推到前,建议大家看看,求导的链式法则。
开始我们不直接对这个式子求导,我们先拆解出几个重要的函数,单独进行导数计算,这样我们可以更好的理解这个过程。
仔细观察以上的式子,我们可以拆解出三个函数:
y
=
w
T
x
+
b
y= {w^Tx + b}
y=wTx+b
y
=
1
1
+
e
−
t
y=\frac{1}{1+{e^{-t}}}
y=1+e−t1
y
=
l
o
g
(
t
)
y=log(t)
y=log(t)
1)第一个是很简单的函数,如果我们对这个函数的
w
w
w进行求偏导数会是怎么样的呢?
∂
y
∂
w
=
x
\frac{\partial y}{\partial w}= x
∂w∂y=x
2)第二个的偏导数就有些难了,但是如果大家高数记着的比较多的话,也是很容的哈:
这里我们对
y
y
y做一个简单的变形。
y
=
(
1
+
e
−
t
)
−
1
y=({1+{e^{-t}}})^{-1}
y=(1+e−t)−1
那么,我们开始计算偏导数:
∂
y
∂
t
=
(
−
1
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
(
−
1
)
\frac{\partial y}{\partial t}= (-1)({1+{e^{-t}}})^{-2}({e^{-t}})(-1)
∂t∂y=(−1)(1+e−t)−2(e−t)(−1)
我们先不对式子进行整理,说一下每一项的由来:第一个(-1)是我们式子的幂数,然后第二项是式子求导后幂数减一,然后在对
e
−
t
{e^{-t}}
e−t求导,导数不变,我们再对-t对导数,导数为-1。所以就是上面的式子。化简一下:
∂ y ∂ t = ( 1 + e − t ) − 2 ( e − t ) \frac{\partial y}{\partial t}= ({1+{e^{-t}}})^{-2}({e^{-t}}) ∂t∂y=(1+e−t)−2(e−t)
3)第三个式子的偏导数也是有公式的:
∂
y
∂
t
=
1
t
t
′
\frac{\partial y}{\partial t}=\frac{1}{t}t^{'}
∂t∂y=t1t′
好现在,我们基本铺垫完毕,我们开始计算整个式子的梯度,也就是对W的偏导数:
J ( W ) = − 1 m ( Y l o g ( 1 1 + e − W T X ) − ( 1 − Y ) l o g ( 1 − 1 1 + e − W T X ) ) J(W) = -\frac{1}{m}(Ylog(\frac{1}{1+{e^{-{W^TX }}}})-(1-Y)log(1-\frac{1}{1+{e^{-{W^TX }}}})) J(W)=−m1(Ylog(1+e−WTX1)−(1−Y)log(1−1+e−WTX1))
首先,我们对第一部分进行偏导数求解:
Y
l
o
g
(
1
1
+
e
−
W
T
X
)
Ylog(\frac{1}{1+{e^{-{W^TX }}}})
Ylog(1+e−WTX1)
为了书写简单些,开始的时候,我们先令
t
=
W
T
X
t=W^TX
t=WTX:
∂
Y
∂
W
=
Y
(
1
+
e
−
t
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
=
Y
(
1
+
e
−
t
)
−
1
(
e
−
t
)
\frac{\partial Y}{\partial W}=Y({1+{e^{-t}}})({1+{e^{-t}}})^{-2}({e^{-t}}) =Y({1+{e^{-t}}})^{-1}({e^{-t}})
∂W∂Y=Y(1+e−t)(1+e−t)−2(e−t)=Y(1+e−t)−1(e−t)
整理公式:
∂
Y
∂
W
=
Y
(
e
−
t
1
+
e
−
t
)
=
Y
(
e
−
t
+
1
−
1
1
+
e
−
t
)
=
Y
(
1
−
1
1
+
e
−
t
)
\frac{\partial Y}{\partial W}=Y(\frac{e^{-t}}{1+{e^{-t}}})=Y(\frac{e^{-t}+1-1}{1+{e^{-t}}}) = Y(1-\frac{1}{1+{e^{-t}}})
∂W∂Y=Y(1+e−te−t)=Y(1+e−te−t+1−1)=Y(1−1+e−t1)
这时候,我们看,是不是就清晰了很多?但是,大家别忽略了
t
=
W
T
X
t=W^TX
t=WTX ,所以上式,还有一步导数可以求解就是,
t
=
W
T
X
t=W^TX
t=WTX,最后上式等于?
∂
Y
∂
W
=
Y
(
e
−
t
1
+
e
−
t
)
=
Y
(
e
−
t
+
1
−
1
1
+
e
−
t
)
=
Y
(
1
−
1
1
+
e
−
t
)
X
\frac{\partial Y}{\partial W}=Y(\frac{e^{-t}}{1+{e^{-t}}})=Y(\frac{e^{-t}+1-1}{1+{e^{-t}}}) = Y(1-\frac{1}{1+{e^{-t}}})X
∂W∂Y=Y(1+e−te−t)=Y(1+e−te−t+1−1)=Y(1−1+e−t1)X
这里面的 1 1 + e − t \frac{1}{1+{e^{-t}}} 1+e−t1是不是就是我们的预测结果? Y ^ \hat{Y} Y^。所以上式,又等于 Y ( 1 − Y ^ ) X Y(1-\hat{Y})X Y(1−Y^)X
我们现在计算完了前半部分,再计算一下后半部分:
(
1
−
Y
)
l
o
g
(
1
−
1
1
+
e
−
W
T
X
)
)
(1-Y)log(1-\frac{1}{1+{e^{-{W^TX }}}}))
(1−Y)log(1−1+e−WTX1))
为了书写简单些,也先令
t
=
W
T
X
t=W^TX
t=WTX:
∂
Y
∂
W
=
(
1
−
Y
)
(
1
1
−
1
1
+
e
−
t
)
(
−
1
)
(
1
1
+
e
−
t
)
′
\frac{\partial Y}{\partial W}=(1-Y)(\frac{1}{1-\frac{1}{1+{e^{-t}}}})(-1)(\frac{1}{1+{e^{-t}}})^{'}
∂W∂Y=(1−Y)(1−1+e−t11)(−1)(1+e−t1)′
这里我们用上边的结果,把后边的导数部分替换掉,得到下面的式子:
=
(
1
−
Y
)
(
1
1
−
1
1
+
e
−
t
)
(
−
1
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
=(1-Y)(\frac{1}{1-\frac{1}{1+{e^{-t}}}})(-1)({1+{e^{-t}}})^{-2}({e^{-t}})
=(1−Y)(1−1+e−t11)(−1)(1+e−t)−2(e−t)
现在我们化简一下:
=
(
1
−
Y
)
(
1
1
+
e
−
t
1
+
e
−
t
−
1
1
+
e
−
t
)
(
−
1
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
=(1-Y)(\frac{1}{\frac{1+{e^{-t}}}{1+{e^{-t}}}-\frac{1}{1+{e^{-t}}}})(-1)({1+{e^{-t}}})^{-2}({e^{-t}})
=(1−Y)(1+e−t1+e−t−1+e−t11)(−1)(1+e−t)−2(e−t)
=
(
1
−
Y
)
(
1
e
−
t
1
+
e
−
t
)
(
−
1
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
=(1-Y)(\frac{1}{\frac{e^{-t}}{1+{e^{-t}}}})(-1)({1+{e^{-t}}})^{-2}({e^{-t}})
=(1−Y)(1+e−te−t1)(−1)(1+e−t)−2(e−t)
=
(
1
−
Y
)
(
1
+
e
−
t
e
−
t
)
(
−
1
)
(
1
+
e
−
t
)
−
2
(
e
−
t
)
=(1-Y)({\frac{1+{e^{-t}}}{e^{-t}}})(-1)({1+{e^{-t}}})^{-2}({e^{-t}})
=(1−Y)(e−t1+e−t)(−1)(1+e−t)−2(e−t)
=
(
1
−
Y
)
(
1
+
e
−
t
)
(
−
1
)
(
1
+
e
−
t
)
−
2
=(1-Y)({1+{e^{-t}}})(-1)({1+{e^{-t}}})^{-2}
=(1−Y)(1+e−t)(−1)(1+e−t)−2
=
(
1
−
Y
)
(
−
1
)
(
1
+
e
−
t
)
−
1
=(1-Y)(-1)({1+{e^{-t}}})^{-1}
=(1−Y)(−1)(1+e−t)−1
这里我们再
t
=
W
T
X
t=W^TX
t=WTX,导数也追加上,就可以得到:
=
(
1
−
Y
)
(
−
1
)
(
1
+
e
−
t
)
−
1
X
=(1-Y)(-1)({1+{e^{-t}}})^{-1}X
=(1−Y)(−1)(1+e−t)−1X
=
(
1
−
Y
)
(
−
1
)
1
1
+
e
−
t
X
=(1-Y)(-1)\frac{1}{1+{e^{-t}}}X
=(1−Y)(−1)1+e−t1X
=
(
1
−
Y
)
(
−
1
)
Y
^
X
=(1-Y)(-1)\hat{Y}X
=(1−Y)(−1)Y^X
这样我们把前后两部分相加:
∂
Y
∂
W
=
−
1
m
(
Y
(
1
−
Y
^
)
X
+
(
1
−
Y
)
(
−
1
)
Y
^
X
)
\frac{\partial Y}{\partial W}= -\frac{1}{m}(Y(1-\hat{Y})X+(1-Y)(-1)\hat{Y}X)
∂W∂Y=−m1(Y(1−Y^)X+(1−Y)(−1)Y^X)
整理:
=
−
1
m
(
Y
X
−
Y
Y
^
X
−
Y
^
X
+
Y
Y
^
X
)
= -\frac{1}{m}(YX-Y\hat{Y}X-\hat{Y}X+Y\hat{Y}X)
=−m1(YX−YY^X−Y^X+YY^X)
=
−
1
m
(
Y
X
−
Y
^
X
)
= -\frac{1}{m}(YX-\hat{Y}X)
=−m1(YX−Y^X)
=
−
1
m
(
(
Y
−
Y
^
)
X
)
= -\frac{1}{m}((Y-\hat{Y})X)
=−m1((Y−Y^)X)
=
1
m
(
(
Y
^
−
Y
)
X
)
= \frac{1}{m}((\hat{Y}-Y)X)
=m1((Y^−Y)X)
最后这就是我们推导获得的梯度公式:
1
m
(
(
Y
^
−
Y
)
X
)
\frac{1}{m}((\hat{Y}-Y)X)
m1((Y^−Y)X)
这里说明下:因为是矩阵运算,注意,行列的顺序关系。顺序关系的不同,最后式子的,
X
X
X乘的位置也有差异,这里不做详细说明,大家可以自己思考下。
最后,我们附上,《机器学习实战》书中提供的,梯度下降法的代码,供大家参考:
#对数几率函数或sigmoid函数实现
def sigmoid(inX):
return 1.0/(1 + exp(-inX))
#梯度下降实现:
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn)
labelMat = mat(classLabels).transpose()
m,n = shape(dataMatrix)
#学习率
alpha = 0.001
maxCycles = 500
weights = ones((n,1))
for k in range(maxCycles):
#预测结果
h =sigmoid(dataMatrix*weights)
#预测结果与真实标签的差值。
error = (labelMat - h)
#更新迭代公式,其中后半部分就是我们推导的梯度懂事。大家可以仔细思考一下。
weights = weights + alpha * dataMatrix.transpose() * error
return weights
模型边界问题
1.直线
逻辑回归本质上是一个线性模型;
从模型的公式,我们认为模型的分界线是一个直线,这是正常的。因为我们的特征都是一次幂的形式。那么,方程肯定是一个直线方程。
2.超平面
如果我们通过“特征变换”的方式把低维空间转换到高维空间,而在低维空间不可分的数据,到高维空间中线性可分的几率会高一些。
例如,我们任务,构造高维特征,例如,原本我们有x1和x2两个特征,我们可以构造。x1*x2,x1^2等等,就变成了高维,那么此时的分界线就是一个超平面了。
正则项
L1,L2正则化可以在模型的参数迭代过程中使用,从而降低模型的过拟合。
具体方式以后待续
单分类模型向多分类模型转化
我们用sigmoid函数实现的是二分类。如果我们使用softmax函数就转化为了多分类模型。
应用展望
1.问题抽象
将一个问题合理的抽象为分类问题,那么,我们就可以尝试用logistics regression模型进行分类学习,是我们进行快速原型迭代的非常有效的模型。也可以作为一个基线模型来比较。
2.特征构建
根据二分类的需要,构建必要的特征。