问题引入
如上图,我们将每个点看成一个样本,$x_1,x_2$为样本的两个特征。可以看到所有点都可划分为class0或class1。(本文只讨论二分类问题)
当我们要对一个新的样本进行分类,可以采用回归预测的方法。也就是拟合一个假设函数$h_\theta(x)$,该函数以样本的所有特征为参数,返回该样本的类别。但是,对于一个分类的问题,常规的回归预测并不适用,因为我们经过假设函数$h_\theta(x)$预测往往返回的是一个连续值,但对于样本而言,其标签非0即1,是一个离散值。所以,就有了一种用于分类的回归算法logistic。
在继续阅读前,希望您已经有了线性回归和梯度下降法的基础。
本篇文章相关代码以及数据集已上传至github
假设函数
我们一般定义$h_\theta(x)$=$\theta_0+\theta_1\times x_1+\theta_2\times x_2+...+\theta_n\times x_n$ (别问为什么这么定义,问就是奥卡姆剃刀)
我们的最终目的,就是去拟合参数$\theta=[\theta_0,\theta_1...\theta_n]^T$来提升分类器的性能。
对于一个分类问题而言,我们需要设定阈值来比较样本与阈值的大小进行分类。但是对于这个朴素的$h_\theta(x)$,返回值本身没有意义且阈值较难设定。所以从某种角度上来说,我们希望$h_\theta(x)$的返回值有意义,比如表示该样本属于class0的概率,那就要求$h_\theta$的值域为$[0,1]$,这样当$h_\theta(x)$>0.5时,我们将其分类为class0,当
$h_\theta(x)$<0.5时,我们将其分类为class1.于是,大佬们就找到了一种函数sigmoid。
sigmoid
sigmoid函数原型为$g(z)=\frac{1}{1+e^{-z}}$
该函数有良好的特性适应我们的需求。
-
其定义域为$(-\infty,+\infty)$,相应的其值域为$(0,1)$,正好满足概率分布的要求。
-
它是单调上升的函数,具有良好的连续性,不存在不连续点。而且由于$g(0)=0.5$因此可以选取0作为分界点。
因此将原来的$h_\theta(x)=\theta^Tx$作为sigmoid函数的输入,得到
$h_\theta(x)=g(\theta^Tx)=\frac{1}{1+e^{-\theta^Tx}}$
好了,确定了假设函数的形式,接下来的任务就是如何通过样本数据来拟合参数$\theta$.
代价函数
在来拟合参数前,我们先来讲讲如何我们对函数拟合好坏的评价标准。我们的方法是设计一个代价函数。
$J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\frac{1}{2}(h_\theta(x^i)-y^i))^2$
这是普通线性回归中会用到的代价函数$Cost(h_\theta(x),y)=\frac{1}{2}(h_\theta(x)-y))^2$
但是由于logistic中的$h_\theta(x)$的是一个很复杂的函数,且非凸,
会有很多局部最小值,我们如果还是采取这个函数为代价函数,在使用梯度下降法时就无法保证收敛至全局最小值。所以,针对logistic回归,我们需要设计一种新的代价函数。
$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}$
如图这两个函数当输入在趋于0或1时都表现的很好,例如当实际$y=1$时,如果$h_\theta(x)=1$,完全预测正确,那么代价值就为0,反之若$h_\theta(x)=0$,完全预测错误,那么代价就会趋向于无穷。
同时代价函数可以简化为$Cost(h_\theta(x),y)=-y\times log(h_\theta(x))-(1-y)\times log(1-h_\theta(x))$
所以$J(\theta)=\frac{1}{m}\sum_{i=1}^{m}Cost(h_\theta(x^i),y^i)$
$=-\frac{1}{m}(y^i\times log(h_\theta(x^i))+(1-y^i)\times log(1-h_\theta(x^i)))$
这就是logistic的代价函数了,由于该函数为凸函数,我们就可以使用梯度下降法来求取最优解了。
梯度下降法
众所周知,梯度下降法的更新公式为$\theta=\theta- \alpha\times\frac{\partial J(\theta)}{\partial\theta}$
其中,$\alpha$为我们设置的学习率。
那么,代入logistic的$J(\theta)$,得到
$\theta_j=\theta_j-\alpha\sum_{i=1}^m(h_\theta(x^i)-y^i)x_j^i$
$=\theta_j+\alpha\sum_{i=1}^m(y^i-h_\theta(x^i))x_j^i$
令m表示样本数,n表示特征数
向量化,得到$\theta_{n\times1}=\theta_{n\times1}-\alpha x^T_{nm}\times(h(x)_{m1}-y_{m*1})$
有了公式,我们就能写出代码了。
|
|
接下来让我们画出分界曲线来直观的感受一下拟合的好坏吧。
由sigmoid函数可知分界点$h_\theta(x)=0.5$
$\theta^Tx=0$
在这个测试集上,得到 $\theta_0+\theta_1x_1+\theta_2x_2=0$
|
|
得到下图
可以看到,拟合的还算不错。
但是这样的梯度下降法存在一个问题:效率过低。因为每进行一次迭代,其都需要对整个样本数据集进行矩阵操作,像我们使用的数据集中只有几百个样本和较少的特征。但是当我们碰到成千上万个样本以及较多的特征时,梯度下降法的效率就不足以支撑我们处理这些数据了。
因此为解决效率问题,下面介绍一种随机梯度下降法。
随机梯度下降法(SGD)
随机梯度下降法本质上和批量梯度下降一样,唯一的区别在于每次更新时随机选取数据集中的一个样本进行更新,而不是遍历整个数据集再进行更新,这样就大大降低了算法的时间复杂度。但是,带来的代价就是准度会降低,由于是随机选取一个进行更新,没有考虑全局,就像在黑暗中盲目摸索,无法保证每次更新都是朝着正确的方向,所以相比批量梯度下降的准确率肯定会下降。
|
|
效果如下:
可以看到,SGD算法和BGD算法内循环的时间复杂度是一样的,但是SGD只需要大迭代10次就能达到BGD迭代500次的效果,原因就在于SGD每次随机选取一个样本计算代价后就对参数进行了更新。
使用logistic回归预测病马的死亡率
我们先来看一下数据集:
该数据集中有很多缺失值,一般对于数据集有缺失的值,有几种做法:
-
使用可用特征的均值来填补缺失值
-
使用特殊值来填补确实值 如-1
-
忽略有缺失值的样本
-
使用相似样本的均值添补缺失值
-
使用另外的机器学习算法预测缺失值
所以在预处理阶段我们可以使用0来代替所有缺失值,因为在logistic回归中,如果某个特征值为0,应用该更新公式:$weights=weights+\alpha\times error \times dataMat[i]$,$weights$将不会得到更新。
然后我们在看一下各个特征属性,显然第3行的医院编号对病马的死亡率是没有影响的,所以我们将这行去掉。同时我们将所有特征属性归一化。
|
|
预处理完成,我们使用logistic回归进行一下预测,这里我直接使用sklearn的logistic回归算法(偷个懒)。
|
|
结果如下:
准确率为0.8382352941176471