"> "> 机器学习-逻辑回归 | Yufei Luo's Blog

机器学习-逻辑回归

定义

逻辑回归虽然在名字里面带有“回归”二字,但是它实质上是一种分类模型。从广义上来讲,因为逻辑回归的表达式中使用到了线性方程,因此它也属于广义线性模型的一种。

逻辑分布

\(X\)为连续随机变量,如果\(X\)服从逻辑分布那么它具有下列的分布函数\(F(x)\)和密度函数\(f(x)\)\[ F(x)=P(x\le x)=\frac{1}{1+\exp(-(x-\mu)/\gamma)} \\ f(x)=F'(x)=\frac{\exp(-(x-\mu)/\gamma)}{\gamma(1+\exp(-(x-\mu)/\gamma))^2} \] 式中,\(\mu\)为位置参数,\(\gamma>0\)为形状参数。

逻辑分布函数的图形是一条S形曲线,曲线以点\((\mu,\frac{1}{2})\)中心对称。曲线在中心附近增长速度最快,而在两端增长速度较慢。

逻辑回归模型

在分类问题中,如果要使用线性方程\(y=\boldsymbol{x}\boldsymbol{w}^T\)(其中\(\boldsymbol{w}=(w_1,w_2,\dots,w_n,b)\)\(\boldsymbol{x}=(x_1,x_2,\dots,x_n,1)\))去预测\(\boldsymbol{x}\)属于\(K\)个类别的概率,并且保证\(K\)个类别的总概率加起来等于1,使用对数几率(或者logit函数)构造出如下的\(K-1\)个表达式组成的逻辑回归模型,便可以满足上述这些条件(其实这些线性方程也相当于是分类边界): \[ \log \frac{\Pr(G=1|X=\boldsymbol{x})}{\Pr(G=K|X=\boldsymbol{x})}=\boldsymbol{x}\boldsymbol{w}_1^T \\ \log \frac{\Pr(G=2|X=\boldsymbol{x})}{\Pr(G=K|X=\boldsymbol{x})}=\boldsymbol{x}\boldsymbol{w}_2^T \\ \vdots \\ \log \frac{\Pr(G=K-1|X=\boldsymbol{x})}{\Pr(G=K|X=\boldsymbol{x})}=\boldsymbol{x}\boldsymbol{w}_{K-1}^T \] 通过对上述的表达式做一些数学变换,我们可以得到每个类别的条件概率: \[ \begin{aligned} &\Pr(G=k|X=\boldsymbol{x})=\frac{\exp(\boldsymbol{x}\boldsymbol{w}_k^T)}{1+\sum_{i=1}^{K-1}\exp(\boldsymbol{x}\boldsymbol{w}_i^T)},~k=1,\dots,K-1 \\ &\Pr(G=K|X=\boldsymbol{x})=\frac{1}{1+\sum_{i=1}^{K-1}\exp(\boldsymbol{x}\boldsymbol{w}_i^T)} \end{aligned} \] 从中可以看出,这些概率表达式与逻辑分布的函数表达式相同,这也是这一模型被称为逻辑回归模型的原因。

模型求解

为了求解逻辑回归模型中的参数,我们需要构造如下的对数似然函数: \[ L(\boldsymbol{w})=\sum_{i=1}^{N}\log p_{g_i}(\boldsymbol{x}_i;\boldsymbol{w}) \] 其中\(p_{g_i}(\boldsymbol{x}_i;\boldsymbol{w})=\Pr(G=k|X=\boldsymbol{x};\boldsymbol{w})\),代表模型预测出的\(\boldsymbol{x}\)属于第\(k\)个类别的条件概率。

为了简化推导过程,接下来我们以二分类为例进行说明。我们将两个类别分别记作0和1,并将\(y=1\)对应于预测结果为类别1,\(y=0\)对应预测结果为类别0。记\(p_1(\boldsymbol{x};\boldsymbol{w})=p(\boldsymbol{x};\boldsymbol{w})\),那么\(p_0(\boldsymbol{x};\boldsymbol{w})=1-p(\boldsymbol{x};\boldsymbol{w})\)。此时,对数似然函数可以写成下面的形式: \[ \begin{aligned} L(\boldsymbol{w})=&\sum_{i=1}^{N}[y_i\log p(\boldsymbol{x};\boldsymbol{w})+(1-y_i)\log(1-p(\boldsymbol{x};\boldsymbol{w}))] \\ =&\sum_{i=1}^{N}[y_i\boldsymbol{x}\boldsymbol{w}^T-\log(1+\exp(\boldsymbol{x}\boldsymbol{w}^T))] \end{aligned} \] 由于对数似然函数在对\(\boldsymbol{w}\)求一阶偏导之后,仍然是非线性函数,因此无法像线性回归一样直接求出解析表达式。要求解逻辑回归的参数,则需要使用梯度下降法或是牛顿法求近似解。

正则化

逻辑回归的对数似然函数其实相当于是对模型的预测结果使用对数损失函数(符号取反),也就是说,逻辑回归的损失函数\(\ell(\boldsymbol{w})\)也具有相同的表达式: \[ \begin{aligned} \ell(\boldsymbol{w})=&-\sum_{i=1}^{N}[y_i\log p(\boldsymbol{x};\boldsymbol{w})+(1-y_i)\log(1-p(\boldsymbol{x};\boldsymbol{w}))] \\ =&-\sum_{i=1}^{N}[y_i\boldsymbol{x}\boldsymbol{w}^T-\log(1+\exp(\boldsymbol{x}\boldsymbol{w}^T))] \end{aligned} \] 因此,我们可以像线性回归一样,在逻辑回归的损失函数中加上正则项,从而对模型参数进行约束。

例如L1正则化的损失函数表达式: \[ \ell_{L1}(\boldsymbol{w})=-\sum_{i=1}^{N}[y_i\log p(\boldsymbol{x};\boldsymbol{w})+(1-y_i)\log(1-p(\boldsymbol{x};\boldsymbol{w}))]+\lambda\sum_{j=1}^{p}|w_j| \] L2正则化的损失函数表达式: \[ \ell_{L2}(\boldsymbol{w})=-\sum_{i=1}^{N}[y_i\log p(\boldsymbol{x};\boldsymbol{w})+(1-y_i)\log(1-p(\boldsymbol{x};\boldsymbol{w}))]+\lambda\sum_{j=1}^{p}w_j^2 \] 通过对损失函数求最小值,我们便可得到加入正则化项之后的模型参数。

优缺点

优点:

  1. 训练速度较快,内存资源占用小,分类的时候,计算量仅仅只和特征的数目相关;
  2. 简单易理解,模型的可解释性非常好,从特征的权重可以看到不同的特征对最后结果的影响;

缺点:

  1. 如果要用Logistic回归去解决非线性问题,则需要对数据做特征工程;
  2. 对多重共线性数据较为敏感;
  3. 很难处理数据不平衡的问题;
  4. 无法直接处理多分类的问题,对于多分类问题可能需要构建多个模型。

代码示例

接下来我们使用Sklearn来演示逻辑回归的用法,我们使用Sklearn自带的iris数据集进行演示。

1
2
3
4
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix

Iris数据集的四个特征分别为:sepal length (cm)、sepal width (cm)、petal length (cm)、petal width (cm),三种不同的类别0、1、2分别对应于Iris-Setosa、Iris-Versicolour和Iris-Virginica这三类。

为了方便做可视化,我们对数据进行精简,只选取2、3两列来训练与预测模型。我们取petal length (cm)和petal width (cm)这两个特征来训练和预测。需要注意的是,Sklearn的逻辑回归可以自动对多分类问题进行处理,默认使用OneVsRest的方式做多分类,因此N个类别就对应于N个不同的分类器。

1
2
X,y=load_iris(return_X_y=True)
X=X[:,2:4]
1
train_x,test_x,train_y,test_y=train_test_split(X,y,test_size=0.3)

LogisticRegression分类器的主要参数包括:

  • penalty:正则项的类型,默认为l2,可以改为l1、elasticnet或者none
  • C:代表正则项的惩罚因子,数值越大则对于正则项的惩罚越小
1
2
3
lr_clf=LogisticRegression(C=2.0) 
lr_clf.fit(train_x,train_y)
pred_y=lr_clf.predict(test_x)
1
confusion_matrix(test_y,pred_y)
array([[17,  0,  0],
       [ 0, 14,  0],
       [ 0,  0, 14]], dtype=int64)

接下来我们对结果进行可视化展示。首先我们先构造一个二维空间的网格点,将其输入到模型,便得到这些网格点上所对应的概率输出值。使用这些概率值我们可以做出概率轮廓图,方便我们观察模型的决策边界:

1
2
X_mesh,Y_mesh=np.meshgrid(np.linspace(0,8,200),np.linspace(0,5,100))
XY_mesh=np.concatenate([X_mesh.reshape(-1,1),Y_mesh.reshape(-1,1)],axis=1)
1
mesh_proba=lr_clf.predict_proba(XY_mesh)
1
mesh_proba
array([[0.9998164 , 0.0001836 , 0.        ],
       [0.9997917 , 0.0002083 , 0.        ],
       [0.99976368, 0.00023632, 0.        ],
       ...,
       [0.        , 0.        , 1.        ],
       [0.        , 0.        , 1.        ],
       [0.        , 0.        , 1.        ]])

由于原始数据中一共有三种类型,因此我们共需要做出三个图,对应于三个分类模型,以及它们各自的概率轮廓图:

1
2
3
4
5
6
7
8
9
10
11
fig=plt.figure(figsize=(15,3))
axes=fig.subplots(1,3)
for i in range(3):
axes[i].set_xlabel('sepal length (cm)')
axes[i].set_ylabel('sepal width (cm)')
contour=axes[i].contourf(X_mesh,Y_mesh,mesh_proba[:,i].reshape(X_mesh.shape),cmap='Greys')
fig.colorbar(contour,ax=axes[i])
axes[i].scatter(test_x[test_y==0][:,0],test_x[test_y==0][:,1],label='Iris-Setosa')
axes[i].scatter(test_x[test_y==1][:,0],test_x[test_y==1][:,1],label='Iris-Versicolour')
axes[i].scatter(test_x[test_y==2][:,0],test_x[test_y==2][:,1],label='Iris-Virginica')
axes[i].legend()

逻辑回归

参考

  1. The Elements of Statistical Learning
  2. 机器学习,周志华
  3. https://blog.csdn.net/keep_giong/article/details/96109592
  4. Hands-on Machine Learning with Scikit-learn and TensorFlow