逻辑回归的原理、求解及python实现
逻辑回归的由来:从线性回归到逻辑回归
不知道你们是否有同感,在刚接触逻辑回归算法时候,大家多多少少都听过逻辑回归和线性回归的不同,虽然叫逻辑回归,但是完全不是回归的数值预测,而是进行分类,总是强调分类和数值预测这点的不同,很容易忽略两个算法本质上的关联。所以,本文不准备把这两个算法拆解开,算法既然叫逻辑回归,自然和“回归”脱不了关系。本文就从线性回归和逻辑回归的关联讲起,看看逻辑回归的“回归”体现在哪一步骤中,并通过公式推导探索逻辑回归的原理。
线性回归回顾
我们不再使用吴恩达教授的房价预测的例子,来看“小白鼠”的例子~
若研究老鼠死亡率和毒物用量的关联,可知,随着毒物用量的增加,老鼠死亡率上升,若使用线性回归,如下:
从值域上看,线性回归是发散式方程,其因变量取值范围为(
−
∞
-\infty
−∞,
+
∞
+\infty
+∞),很明显死亡率>1是不合理的。这个时候对于这种输出概率的问题,我们希望把值控制在0-1之间。我们可以想到把线性回归的值带入到某一函数中进行转换,使输出值的范围压制在0-1之间
。
我们可以使用哪种变换函数呢?可以想到的有“单位阶跃函数”:
f
(
z
)
=
{
0
,
z<0
0.5
,
z=0
1
,
z>0
f(z)=\begin{cases}0,& \text{z<0}\\0.5,&\text{z=0}\\1,&\text{z>0}\end{cases}
f(z)=⎩⎪⎨⎪⎧0,0.5,1,z<0z=0z>0但是,问题在于单位阶跃函数是分段函数,不连续、不可导的性质不方便使用。
所以,我们常用logit函数,也称sigmoid函数:
f
(
z
)
=
1
1
+
e
−
z
f(z)=\frac{1}{1+e^{-z}}
f(z)=1+e−z1
sigmoid函数的优良性质
首先,来看看sigmoig函数图形:
可以看到sigmoid函数的特点:连续、单调、可导。
ps.sigmoid函数一个优良的性质在于:
f
′
(
z
)
=
f
(
z
)
(
1
−
f
(
z
)
)
f'(z)=f(z)(1-f(z))
f′(z)=f(z)(1−f(z))
1
(
1
+
e
−
z
)
′
=
[
(
1
+
e
−
z
)
−
1
]
′
=
−
(
1
+
e
−
z
)
−
2
(
−
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
)
)
\frac{1}{(1+e^{-z})}'=[(1+e^{-z})^{-1}]'=-(1+e^{-z})^{-2}(-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})})
(1+e−z)1′=[(1+e−z)−1]′=−(1+e−z)−2(−e−z)=(1+e−z)2e−z=(1+e−z)21+e−z−1=(1+e−z)1−(1+e−z)21=(1+e−z)1(1−(1+e−z)1)
过渡到逻辑回归
由上述可知,我们将线性回归的结果
z
=
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
.
.
.
+
θ
n
x
n
z=\theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n
z=θ0+θ1x1+θ2x2+...+θnxn带入sigmoid函数,有:
y
=
1
(
1
+
e
−
z
)
=
1
(
1
+
e
−
(
θ
0
+
t
h
e
t
a
1
x
1
+
.
.
.
θ
n
x
n
)
)
[
1
]
y=\frac{1}{(1+e^{-z})}=\frac{1}{(1+e^{-(\theta_0+theta_1x_1+...\theta_nx_n)})}^{[1]}
y=(1+e−z)1=(1+e−(θ0+theta1x1+...θnxn))1[1]
由式[1]可得
z
=
θ
0
+
t
h
e
t
a
1
x
1
+
.
.
.
θ
n
x
n
=
l
n
y
1
−
y
z=\theta_0+theta_1x_1+...\theta_nx_n=ln\frac{y}{1-y}
z=θ0+theta1x1+...θnxn=ln1−yy
由于此时
y
y
y的取值是0-1之间的概率,可将其看做样本
x
x
x作为正例“1”的可能性,
1
−
y
1-y
1−y即为反例"0"的可能性,
y
1
−
y
\frac{y}{1-y}
1−yy称为odds(优势),反映
x
x
x作为正例的相对可能性。上述,对odds取对数,称为odds ratio优势比,也称“对数几率”:
o
d
d
s
r
a
t
i
o
=
l
n
y
1
−
y
odds ratio=ln\frac{y}{1-y}
oddsratio=ln1−yy这就是逻辑回归的由来,实际上就是用线性回归的结果,带入转换函数,逼近真实标记的对数几率。
逻辑回归可以解决的问题
由上可知,逻辑回归的值域为[0,1],此时,我们常用逻辑回归解决二分类问题。如何进行分类?我们需要设定一个阈值(threshold),输出概率
y
y
y大于这个阈值时归为类1,小于这个阈值,归于类0.
例如,电信客户流失预警,我们判断客户流失与否,流失即为类1,保留客户即为类0.如何根据输出判断客户是否流失呢?我们可以把阈值设定为最普遍的0.5,逻辑回归输出值>0.5时,认为客户流失,否则不流失。
其他的二分类问题,都可以使用逻辑回归解决。
逻辑回归的决策边界
在具有两个类的统计分类问题中,决策边界或决策表面是超曲面,其将基础向量空间划分为两个集合,一个集合。 分类器将决策边界一侧的所有点分类为属于一个类,而将另一侧的所有点分类为属于另一个类。——百度百科
我们假设阈值为0.5,
y
<
0.5
y<0.5
y<0.5时即为类“0”;
y
>
0.5
y>0.5
y>0.5时即为类“1”,此时有:
Y
=
{
0
,
y
<
0.5
1
,
y
>
0.5
Y=\begin{cases} 0 ,&y<0.5\\1, &y>0.5\end{cases}
Y={0,1,y<0.5y>0.5
→
\rightarrow
→
Y
=
{
0
,
z
<
0
1
,
z
>
0
Y=\begin{cases} 0 ,&z<0\\1, &z>0\end{cases}
Y={0,1,z<0z>0
→
\rightarrow
→
Y
=
{
0
,
X
θ
<
0
1
,
X
θ
>
0
Y=\begin{cases} 0 ,&X\theta<0\\1, &X\theta>0\end{cases}
Y={0,1,Xθ<0Xθ>0
假设,我们的输入变量有
x
1
,
x
2
x_1,x_2
x1,x2,逻辑回归:
y
=
1
1
+
e
−
(
θ
0
+
θ
1
x
1
+
θ
2
x
2
)
=
1
1
+
e
−
(
X
θ
)
y=\frac{1}{1+e^{-(\theta_0+\theta_1x_1+\theta_2x_2)}}=\frac{1}{1+e^{-(X\theta)}}
y=1+e−(θ0+θ1x1+θ2x2)1=1+e−(Xθ)1
此时,我们取
y
=
0.5
y=0.5
y=0.5,对应横坐标(线性回归的输出值):
z
=
X
θ
z=X\theta
z=Xθ的取值为0。有决策边界:
θ
0
+
θ
1
x
1
+
θ
2
x
2
=
0
\theta_0+\theta_1x_1+\theta_2x_2=0
θ0+θ1x1+θ2x2=0
图中紫色直线即为决策边界。
逻辑回归的求解
损失函数
由线性回归,可以得到同样的逻辑回归损失函数:
J
(
θ
)
=
1
m
∑
i
=
1
m
1
2
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}(h_\theta(x^{(i)})-y^{(i)})^2
J(θ)=m1∑i=1m21(hθ(x(i))−y(i))2
令
c
o
s
t
=
1
2
(
h
θ
(
x
)
−
y
)
2
cost=\frac{1}{2}(h_\theta(x)-y)^2
cost=21(hθ(x)−y)2,我们最小化
J
(
θ
)
J(\theta)
J(θ)相当于最小化cost。但是我们不能直接对cost使用梯度下降法求解,因为cost中
h
θ
(
x
)
=
1
1
+
e
−
X
θ
h_\theta(x)=\frac{1}{1+e^{-X\theta}}
hθ(x)=1+e−Xθ1导致
J
(
θ
)
J(\theta)
J(θ)是非凸函数,无法收敛到全局最小。因此,我们需要对cost进行转换。
此时逻辑回归使用的损失函数
[
2
]
^{[2]}
[2]为:
c
o
s
t
(
h
θ
(
x
)
,
y
)
=
{
−
l
o
g
(
h
θ
(
x
)
)
,
if
y
=
1
−
l
o
g
(
1
−
h
θ
(
x
)
)
,
if
y
=
0
cost(h_\theta(x),y)=\begin{cases}-log(h_\theta(x)),&\text{if $y=1$}\\-log(1-h_\theta(x)),&\text{if $y=0$}\end{cases}
cost(hθ(x),y)={−log(hθ(x)),−log(1−hθ(x)),if y=1if y=0
代价函数的图像为:
当
y
=
1
y=1
y=1,
h
θ
(
x
)
=
1
ℎ_\theta(x)=1
hθ(x)=1时,
c
o
s
t
=
0
cost=0
cost=0;
当
y
=
0
y=0
y=0,
h
θ
(
x
)
=
1
ℎ_\theta(x)=1
hθ(x)=1时,
c
o
s
t
=
∞
cost=\infty
cost=∞;
当
y
=
1
y=1
y=1,
h
θ
(
x
)
=
0
ℎ_\theta(x)=0
hθ(x)=0时,
c
o
s
t
=
∞
cost=\infty
cost=∞;
当
y
=
0
y=0
y=0,
h
θ
(
x
)
=
0
ℎ_\theta(x)=0
hθ(x)=0时,
c
o
s
t
=
0
cost=0
cost=0.
综上,
c
o
s
t
(
h
θ
(
x
)
−
y
)
=
−
y
l
o
g
(
h
θ
(
x
)
)
−
(
1
−
y
)
l
o
g
(
h
θ
(
x
)
)
cost(h_\theta(x)-y)=-ylog(h_\theta(x))-(1-y)log(h_\theta(x))
cost(hθ(x)−y)=−ylog(hθ(x))−(1−y)log(hθ(x))即可得到上述[2]式逻辑回归常用的cost function。
将cost function带入逻辑回归的损失函数,得:
J
(
θ
)
=
1
m
∑
i
=
1
m
c
o
s
t
(
h
θ
(
x
(
i
)
)
,
y
(
i
)
)
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
l
o
g
h
θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
l
o
g
(
1
−
h
θ
(
x
(
i
)
)
)
]
J(\theta)=\frac{1}{m}\sum_{i=1}^{m}cost(h_\theta(x^{(i)}),y^{(i)})=-\frac{1}{m}\sum_{i=1}^{m}[y^{(i)}logh_\theta(x^{(i)})+(1-y^{(i)})log(1-h_\theta(x^{(i)}))]
J(θ)=m1i=1∑mcost(hθ(x(i)),y(i))=−m1i=1∑m[y(i)loghθ(x(i))+(1−y(i))log(1−hθ(x(i)))]
最后,附上cost函数推导的笔记:
梯度下降法求解逻辑回归
ps.为了书写方便
y
(
i
)
y^{(i)}
y(i)写为
y
i
y_i
yi
python实现——sklearn
1.导入库
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report,confusion_matrix
from sklearn import preprocessing
from sklearn import linear_model
# 数据是否需要标准化
scale = False
2.数据导入和转换
# 载入数据
data = np.genfromtxt("data/LR-testSet.csv", delimiter=",")
x_data = data[:,:-1]
y_data = data[:,-1] #最后一列为标签
def plot():
x1_0 = []
x1_1 = []
x2_0 = []
x2_1 = []
for i in range(len(x_data)):
if y_data[i]==0:
x1_0.append(x_data[i,0])
x2_0.append(x_data[i,1])
else:
x1_1.append(x_data[i,0])
x2_1.append(x_data[i,1])
# 画图
scatter0 = plt.scatter(x1_0, x2_0, c='b', marker='o')
scatter1 = plt.scatter(x1_1, x2_1, c='r', marker='x')
#画图例
plt.legend(handles=[scatter0,scatter1],labels=['label0','label1'],loc='best')
plot()
plt.show()
- 模型建立
model = linear_model.LogisticRegression()
model.fit(x_data, y_data)
4.画决策边界
if scale == False:
# 画图
plot()
x_test = np.array([[-4],[3]])
y_test = (-model.intercept_ - x_test*model.coef_[0][0])/model.coef_[0][1]
plt.plot(x_test, y_test, 'k')
plt.show()
5.模型预测
predictions = model.predict(x_data)
print(classification_report(y_data, predictions))
#混淆矩阵
print(confusion_matrix(y_data, predictions))
参考资料
《机器学习》·周志华
吴恩达机器学习课程