机器学习02:逻辑回归
逻辑回归的概念
逻辑回归的基本形式
在上一篇文章,我们介绍了线性回归,线性回归可以用来做回归任务.如果我们想要做分类任务,那就用得到逻辑回归了.
逻辑回归就是将线性回归的结果
z
=
w
T
+
b
z = \boldsymbol w ^T + b
z=wT+b映射到分离的
{
0
,
1
}
\{ 0, 1\}
{0,1},这就是Sigmoid函数(对数几率函数).
y
=
1
1
+
e
−
z
y = \frac {1} {1 + e^{-z}}
y=1+e−z1
将
z
z
z值转换为一个接近于0或1的
y
y
y值.
再以 z = 0.5 z=0.5 z=0.5为界,令 z > 0.5 z>0.5 z>0.5被判断为类别 p ^ = 1 \hat{p}=1 p^=1, z < 0.5 z<0.5 z<0.5被判断为类别 p ^ = 0 \hat{p}=0 p^=0.
因此,逻辑回归的表达式如下:
z
=
w
1
x
1
+
w
2
x
2
+
.
.
.
+
w
n
x
n
+
b
y
=
1
1
+
e
−
z
\begin{aligned} \\ z & = w_1 x_1 + w_2 x_2 + ... + w_n x_n + b \\ y & = \frac{1}{1 + e^{-z}} \end{aligned}
zy=w1x1+w2x2+...+wnxn+b=1+e−z1
为什么使用Sigmoid函数而非单位阶跃函数
要将线性回归的结果映射到分离的
{
0
,
1
}
\{ 0, 1\}
{0,1},最简单的就是直接使用单位阶跃函数:
p
^
=
{
1
,
z>0
0.5
,
z=0
0
,
z<0
\hat{p} = \begin{cases} 1, &\text{z>0} \\ 0.5, &\text{z=0} \\ 0, &\text{z<0} \end{cases}
p^=⎩⎪⎨⎪⎧1,0.5,0,z>0z=0z<0
但我们不能使用单位阶跃函数,但我们不能使用它,因为单位阶跃函数不是连续可导的.我们选用Sigmoid函数,正是因为它连续可导且其形状近似于单位阶跃函数.
逻辑回归的损失函数
信息熵是信息论中的概念,可以作为机器学习的损失函数.对于单个样本,信息熵的表达式为Sigmoid函数误差的负对数,即:
c
(
w
)
=
{
log
(
p
^
)
,
y
=
1
log
(
1
−
p
^
)
,
y
=
0
=
y
log
(
p
^
)
+
(
1
−
y
)
(
1
−
log
(
p
^
)
)
c(\boldsymbol{w}) = \begin{cases} \log(\hat{p}), &y=1 \\ \log(1-\hat{p}), &y=0 \end{cases} \quad = \quad y \log(\hat{p}) + (1-y) (1-\log(\hat{p}))
c(w)={log(p^),log(1−p^),y=1y=0=ylog(p^)+(1−y)(1−log(p^))
总的损失函数为所有样本的损失函数的均值:
J
(
w
)
=
−
1
m
∑
i
=
1
m
[
y
i
log
(
p
i
^
)
+
(
1
−
y
i
)
(
1
−
log
(
p
i
^
)
)
]
J(\boldsymbol w) = - \frac{1}{m} \sum_{i=1}^{m} \left[ y_i \log(\hat{p_i}) + (1-y_i) (1-\log(\hat{p_i})) \right]
J(w)=−m1i=1∑m[yilog(pi^)+(1−yi)(1−log(pi^))]
逻辑回归的求解
逻辑回归的损失函数过于复杂,因此我们一般使用随机梯度下降法(SGD)来求解.
逻辑回归的应用
使用逻辑回归解决分类问题
使用逻辑回归解决二分类问题
使用逻辑回归解决二分类问题很简单,只需要将Sigmoid函数的输出作为该样本为正例的概率,对其加以阈值判断.超过阈值上限判定为正例,低于阈值下限判断为负例,在阈值内判断为不确定.
使用逻辑回归解决多分类问题
使用逻辑回归做多分类问题,就是把多分类问题转化为多个互不影响的二分类问题.
假设有 k k k个分类,则我们对每个分类分别做 k k k次逻辑回归.
- 当我们对第 i i i个类别训练逻辑回归模型时,我们以第 i i i类别的样本作为正例,以其它类别的样本作为负例,得到该类样本的概率模型.
- 当我们对测试样本进行判断时,我们只需对该样本应用 k k k个模型进行计算,得到该样本属于每个类别的概率 { P 1 , P 2 , P . . . , P k } \{ P_1, P_2, P_{...}, P_k \} {P1,P2,P...,Pk},取其中概率最大的类别作为判断结果.
多个训练模型互不影响,指的是多个模型之间不需要传递参数,也不需要等待收敛.
使用Sklearn的逻辑回归模块进行分类
在这里,我们使用Sklearn中的LogisticRegression
模块对大名鼎鼎的鸢尾花数据集进行分类.
调用sklearn.datasets.load_iris()
可以得到鸢尾花数据集:
iris = sklearn.datasets.load_iris()
iris.DESCR
'''
.. _iris_dataset:
Iris plants dataset
--------------------
**Data Set Characteristics:**
:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, predictive attributes and the class
:Attribute Information:
- sepal length in cm
- sepal width in cm
- petal length in cm
- petal width in cm
- class:
- Iris-Setosa
- Iris-Versicolour
- Iris-Virginica
:Summary Statistics:
============== ==== ==== ======= ===== ====================
Min Max Mean SD Class Correlation
============== ==== ==== ======= ===== ====================
sepal length: 4.3 7.9 5.84 0.83 0.7826
sepal width: 2.0 4.4 3.05 0.43 -0.4194
petal length: 1.0 6.9 3.76 1.76 0.9490 (high!)
petal width: 0.1 2.5 1.20 0.76 0.9565 (high!)
============== ==== ==== ======= ===== ===========...
'''
iris.feature_names
'''
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
'''
iris.target_names
'''
array(['setosa', 'versicolor', 'virginica'], dtype='<U10')
'''
iris.data
'''
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
...
[6.5, 3. , 5.2, 2. ],
[6.2, 3.4, 5.4, 2.3],
[5.9, 3. , 5.1, 1.8]])
'''
iris.target
'''
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''
我们可以使用LogisticRegression
类对数据进行逻辑回归拟合
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
# 获取测试数据集
iris = datasets.load_iris()
X = iris['data']
Y = iris['target']
# 训练模型
log_reg = LogisticRegression(multi_class='ovr', solver='sag')
# multi_class='ovr'指定对每个标签独立进行二分类,即采用逻辑回归进行多分类问题.solver='sag'指定使用梯度下降法
log_reg.fit(X, Y)
print(log_reg.coef_)
'''
分别为三个类别的模型的权重向量W
array([[ 0.31157822, 1.39076692, -2.26399935, -1.01648555],
[ 0.17493233, -1.81517779, 0.62346813, -1.3488976 ],
[-1.39383116, -1.31172951, 2.5082373 , 2.50381856]])
'''
print(log_reg.intercept_)
'''
分别为三个类别的模型的截距b
array([ 1.02736884, 2.93951978, -3.93953059])
'''
# 使用模型进行预测
print(log_reg.predict([[1, 2, 3, 4], [5, 6, 7, 8]]))
'''
array([2, 2])
'''
print(log_reg.predict_proba([[1, 2, 3, 4], [5, 6, 7, 8]]))
'''
array([[1.96672670e-02, 1.02623967e-01, 8.77708766e-01],
[1.00576908e-06, 1.50664492e-06, 9.99997488e-01]])
'''
运行程序后,得到警告ConvergenceWarning: The max_iter was reached which means the coef_ did not converge "the coef_ did not converge", ConvergenceWarning)
,说明我们设置的迭代次数不够,参数未收敛,通过设置合理的max_iter
属性,可以使模型收敛.
log_reg = LogisticRegression(multi_class='ovr', solver='sag', max_iter=10000)
log_reg.fit(X, Y)