机器学习日记(一):从零认识逻辑回归

引言

分类技术是机器学习和数据挖掘应用中的重要组成部分。在数据科学中,大约70%的问题属于分类问题。解决分类问题的算法也有很多种,比如:KNN算法,使用距离计算来实现分类;决策树,通过构建直观易懂的树来实现分类;朴素贝叶斯,使用概率论构建分类器。本篇谈到的是Logistic回归,它是一种很常见的用来解决二元分类问题的方法。

逻辑回归(Logistic Regression,简称LR),虽然它的名字中带有“回归”两个字,但是它最擅长处理的却是分类问题。 LR分类器适用于各项广义上的分类任务,例如:评论信息的正负情感分析(二分类)、用户点击率(二分类)、用户违约信息预测(二分类)、垃圾邮件检测(二分类)、疾病预测(二分类)、用户等级分类(多分类)等场景。我们这里主要讨论的是二分类问题,解决了二分类自然就解决了多分类,因为N分类问题可以转化成N个二分类问题。


一、线性回归(Linear Regression)

线性回归的表达式:

\[ f(\bf{x})=\pmb{\omega^{T}x}+b\]

线性回归对于给定的输入 \(x\),输出的是一个数值 \(y\),因此它是一个解决回归问题的模型。

为了消除掉后面的常数项b,我们可以令 \(x^{'}=[1\ \ x]^{T}\),同时 \(\omega^{'}=[b\ \ w]^T\) ,直线方程可以化简成为:

\[f(\bf{x^{'}})=\pmb{\omega^{'}x^{'}}\]

在接下来的文章中为了方便,我们所使用的 \(\omega,x\) 其实指代的是 \(\omega^{'},x^{'}\)

二、如何用连续的数值去预测离散的标签值

线性回归的输出是一个数值,而不是一个标签,显然不能直接解决二分类问题。那我如何改进我们的回归模型来预测标签呢?

一个最直观的办法就是设定一个阈值,比如0。如果我们预测的数值 y>0 ,那么属于标签A,反之属于标签B,采用这种方法的模型又叫做感知机(Perceptron)

另一种方法,我们不去直接预测标签,而是去预测标签为A概率,我们知道概率是一个[0,1]区间的连续数值,那我们的输出的数值就是标签为A的概率。一般的如果标签为A的概率大于0.5,我们就认为它是A类,否则就是B类。这就是我们的这次的主角逻辑回归模型 (Logistics Regression)

三、逻辑回归(logistics regression)

通过以上分析,我们明确了预测目标是标签为A的概率。

我们知道,概率是属于[0,1]区间。但是线性模型 \(f(x) = \omega^Tx\) 值域是 \((-\infty,\infty)\)

我们不能直接基于线性模型建模。我们需要找到一个模型的值域刚好在[0,1]区间,同时要足够好用。

于是,选择了我们的sigmoid函数

\[\sigma(x)=\frac{1}{1+e^{-x}}\]

函数图像为:

但是我们不能直接拿sigmoid函数就用,毕竟它连要训练的参数 \(\omega\) 都没有。

因此我们结合sigmoid函数,线性回归函数,把线性回归模型的输出作为sigmoid函数的输入。于是最后就变成了逻辑回归模型:

\[y=\sigma(f(x))=\sigma(\omega^Tx)=\frac{1}{1+e^{-\pmb{\omega^Tx}}}\]

假设我们已经训练好了一组权值 \(\omega^T\)。只要把我们需要预测的 \(x\) 代入到上面的方程,输出的y值就是这个标签为A的概率,我们就能够判断输入数据是属于哪个类别。

接下来就来详细介绍,如何利用一组采集到的真实样本,训练出参数 \(\pmb{\omega}\) 的值。

四、逻辑回归的损失函数(Loss Function)

一个人工训练出来的模型是无法达到100%准确率的。因此我们需要一个东西来衡量模型训练的好坏。损失函数就是用来衡量模型的输出与真实输出的差别。

下面就是逻辑回归的损失函数推导过程。

假设只有两个标签1和0,\(y_n\in\{0,1\}\)。我们把采集到的任何一组样本看做一个事件的话,那么这个事件发生的概率假设为p。我们的模型y的值等于标签为1的概率也就是p,即:

\[P_{y=1}=\frac{1}{1+e^{-\omega^Tx}}=p\]

因为标签不是1就是0,因此标签为0的概率就是:

\[P_{y=0}=1-p\]

我们把单个样本看做一个事件,那么这个事件发生的概率就是:

\[P(y\ |\ x)=\begin{cases}p,&y=1 \cr 1-p,&y=0\end{cases}\]

这个函数不方便计算,它等价于:

\[P(y_i\ |\ x_i)=p^{y_i}(1-p)^{1-y_i}\]

解释下这个函数的含义,我们采集到了一个样本 \((x_i,y_i)\) 。对这个样本,它的标签是 \(y_i\) 的概率是 \(p^{y_i}(1-p)^{1-{y_i}}\) 。(当y=1,结果是p;当y=0,结果是1-p)。

如果我们采集到了一组数据一共N个, \((x_1,y_1),(x_2,y_2),(x_3,y_3) \ldots (x_N,y_N)\) ,这个合成在一起的合事件发生的总概率怎么求呢?其实就是将每一个样本发生的概率相乘就可以了,即采集到这组样本的概率:

\[P_总=P(y_1|x_1)P(y_2|x_2)\cdots P(y_n|x_n)=\prod_{n=1}^{N}p^{y_n}(1-p)^{(1-y_n)}\]

注意 \(P_总\) 是一个函数,并且未知的量只有 \(\omega\)(在p里面)。

由于连乘很复杂,我们通过两边取对数来把连乘变成连加的形式,即:

\[F(\omega)=ln(P_总)=ln(\prod_{n=1}^{N}p^{y_n}(1-p)^{(1-y_n)})\]

\[\quad\quad\quad\quad\quad\quad\quad=\sum_{n=1}^Nln(p^{y_n}(1-p)^{(1-y_n)})\]

\[\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad=\sum_{n=1}^N(y_nln(p)+(1-y_n)ln(1-p))\]

其中,\(p=\frac{1}{1+e^{-\omega^Tx}}\)

这个函数 \(F(\omega)\) 就叫做它的损失函数。损失函数可以理解成衡量我们当前的模型的输出结果,跟实际的输出结果之间的差距的一种函数。这里的损失函数的值等于事件发生的总概率,我们希望它越大越好。但是跟损失的含义有点儿违背,因此也可以在前面取个负号,最终的表达式如下所示(1/m表示均值化):

\[F(\omega)=-\frac{1}{m}\sum_{n=1}^m(y_nln(p)+(1-y_n)ln(1-p))\]

五、极大似然估计MLE(Maximum Likelihood Estimation)

我们在真实世界中并不能直接看到概率是多少,我们只能观测到事件是否发生。也就是说,我们只能知道一个样本它实际的标签是1还是0。那么我们如何估计参数 \(\omega\)\(b\) 的值呢?

极大似然估计MLE(Maximum Likelihood Estimation),就是一种估计参数 \(\omega\) 的方法。在这里如何使用MLE来估计 \(\omega\) 呢?

我们知道损失函数 \(F(\omega)\) 是正比于总概率 \(P_总\) 的,而 \(F(\omega)\) 又只有一个变量 \(\omega\) 。也就是说,通过改变 \(\omega\) 的值,就能得到不同的总概率值 \(P_总\) 。那么当我们选取的某个 \(\omega^{\*}\) 刚好使得总概率 \(P_总\) 取得最大值的时候。我们就认为这个 \(\omega^{\*}\) 就是我们要求得的 \(\omega\) 的值,这就是极大似然估计的思想。

现在我们的问题变成了,找到一个 \(\omega^*\) ,使得我们的总事件发生的概率,即损失函数 \(F(\omega)\) 取得最大值,这句话用数学语言表达就是:

\[\omega^*=arg\mathop{max}\limits_{\omega}F(\omega)=-arg\mathop{min}\limits_{\omega}F(\omega)\]

六、梯度下降法

由于极大似然函数无法直接求解,所以在机器学习算法中,在最小化损失函数时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。 #### 6.1 梯度 在微积分里面,对多元函数的参数求 \(\delta\) 偏导数,把求得的各个参数的偏导数以向量的形式写出来,就是梯度。 比如函数 \(f(x,y)\) , 分别对 \(x,y\) 求偏导数,求得的梯度向量就是 \((\delta f/\delta x,\delta f/\delta y)^T\),简称 \(grad f(x,y)\) 或者 \(\nabla f(x,y)\)。对于在点 \(x_0,y_0\) 的具体梯度向量就是 \((\delta f/\delta x_0,\delta f/\delta y_0)^T\) 或者 \(\nabla f(x_0,y_0)\)

那么这个梯度向量求出来有什么意义呢?从几何意义上讲,就是函数变化增加最快的地方。具体来说,对于函数 \(f(x,y)\) 在点 \(x_0,y_0\) 沿着梯度方向的向量就是 \(f(x,y)\) 增加最快的地方。或者说沿着梯度向量的方向,更加容易找到函数的最大值;反过来说,沿着梯度向量相反的方向,也就是 \(-(\delta f/\delta x_0,\delta f/\delta y_0)^T\) 的方向,梯度减少的最快,也就更容易找到函数的最小值。

6.2 梯度下降的直观解释

首先来看看梯度下降的一个直观的解释。比如我们在一座大山上的某处位置,由于我们不知道怎么下山,于是决定走一步算一步,也就是在每走到一个位置的时候,求解当前位置的梯度,沿着梯度的负方向,也就是当前最陡峭的位置向下走一步,然后继续求解当前位置梯度,向这一步所在位置沿着最陡峭最易下山的位置走一步。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。

从上面的解释可以看出,梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解。当然,如果损失函数是凸函数,梯度下降法得到的解就一定是全局最优解。

6.3 梯度下降法描述

6.3.1 先决条件
确认优化模型的假设函数和损失函数。 ##### 6.3.2 算法相关参数初始化 主要是初始化 \(\omega_0,\omega_1\cdots,\omega_n\),算法终止距离 \(\varepsilon\) 和步长 \(\alpha\)。在没有任何先验知识的时候,我们比较倾向于将所有的 \(\omega_i\) 初始化为0,将步长初始化为1,在调优的时候再进行优化。 ##### 6.3.3 算法过程 (1) 确定当前位置的损失函数的梯度,对于 \(\omega_i\) ,其梯度表达式如下:

\[\frac{\delta}{\delta\omega_i}J(\omega_0,\omega_1,\cdots,\omega_n)\]

  1. 用步长乘以损失函数的梯度,得到当前位置下降的距离,即 \(\alpha\frac{\delta}{\delta\omega_i}J(\omega_0,\omega_1,\cdots,\omega_n)\),对应于前面登山过程中的某一步。
  2. 确定是否所有的 \(\omega_i\) 梯度下降的距离都小于 \(\varepsilon\),如果小于 \(\varepsilon\) 则算法终止,当前所有的 \(\omega_i\) 即为最终结果,否则进入步骤4。
  3. 更新所有的 \(\omega_i\),对于 \(\omega_i\),其更新表达式如下,更新完毕后继续转入步骤1。

\[\omega_i=\omega_i-\alpha\frac{\delta}{\delta\omega_i}J(\omega_0,\omega_1,\cdots,\omega_n)\]

七、求 \(F(\omega)\) 的梯度 \(\nabla F(\omega)\)

先回顾一下p的公式:

\[p=\frac{1}{1+e^{-\omega^Tx}}\]

再回顾一下 \(F(\omega)\) 的公式:

\[F(\omega)=-\frac{1}{m}\sum_{n=1}^m(y_nln(p)+(1-y_n)ln(1-p))\]

\(p\) 是一个关于变量 \(\omega\) 的函数,我们对 \(p\) 求导,通过链式求导法则,慢慢展开可以得:

\[p^{'}=(\frac{1}{1+e^{-\omega^Tx}})^{'}\]

\[\qquad\qquad\quad\quad\qquad =-\frac{1}{(1+e^{-\omega^Tx})^{2}}\cdot(1+e^{-\omega^Tx})^{'}\]

\[\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad=-\frac{1}{(1+e^{-\omega^Tx})^{2}}\cdot e^{-\omega^Tx}\cdot (-\omega^Tx)^{'}\]

\[\quad\quad\quad\quad\quad\quad\quad\quad=-\frac{1}{(1+e^{-\omega^Tx})^{2}}\cdot e^{-\omega^Tx}\cdot (-x)\]

\[\quad\quad\quad\quad\quad\quad=\frac{1}{1+e^{-\omega^Tx}}\cdot \frac{e^{-\omega^Tx}}{1+e^{-\omega^Tx}}\cdot x\]

\[=p(1-p)x\]

上面都是我们做的准备工作,总之我们得记住:

\[p^{'}=p(1-p)x\]

\[(1-p)^{'}=-p(1-p)x\]

下面我们正式开始对 \(F(\omega)\) 求导,求导的时候请始终记住,我们的变量只有 \(\omega\),其他的什么 \(y_n,x_n\) 都是已知的,可以看做常数。

\[\nabla F(\omega)=-\frac{1}{m}\nabla(\sum_{n=1}^m(y_nln(p)+(1-y_n)ln(1-p)))\]

\[\quad\quad=-\frac{1}{m}\sum_{n=1}^m(y_nln^{'}(p)+(1-y_n)ln^{'}(1-p))\]

\[\quad\quad\quad\quad=-\frac{1}{m}\sum_{n=1}^m((y_n\frac{1}{p}p^{'})+(1-y_n)\frac{1}{1-p}(1-p)^{'})\]

\[\quad=-\frac{1}{m}\sum_{n=1}^m(y_n(1-p)x_n-(1-y_n)px_n)\]

\[=-\frac{1}{m}\sum_{n=1}^m(y_n-p)x_n\]

终于,我们求出了梯度 \(\nabla F(\omega)\) 的表达式了,现在我们再来看看它长什么样子:

\[ \nabla F(\omega)=-\frac{1}{m}\sum_{n=1}^N(y_n-p)x_n\]

它是如此简洁优雅,这就是我们选取sigmoid函数的原因之一。当然我们也能够把 \(p\) 再展开,即:

\[ \nabla F(\omega)=-\frac{1}{m}\sum_{n=1}^N(y_n-\frac{1}{1+e^{-\omega^Tx_n}})x_n\]

八、更新系数 \(\omega_i\)

梯度下降法共分为批量梯度下降(Batch Gradient Descent)、随机梯度下降(Stochastic Gradient Descent)和小批量梯度下降(Mini-Batch Gradient Descent)

具体知识请参考我的另一篇博客:

批量梯度下降(BGD)、随机梯度下降(SGD)、小批量梯度下降(MBGD)

这里给出基于BGD梯度下降的公式

\[\omega_{i+1}=\omega_{i}-\alpha\nabla F(\omega)\]

\[\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad=\omega_{i}+\alpha\frac{1}{m}\sum_{n=1}^m(y_n-\frac{1}{1+e^{-\omega^Tx_n}})x_n\]

九、逻辑回归与正则化

有关L1正则化和L2正则化可以参考我的另一篇博客:

浅谈L1正则化与L2正则化

这里给出基于L2正则化的公式

\[F(\omega)=-\frac{1}{m}\sum_{n=1}^m(y_nln(p)+(1-y_n)ln(1-p))+\frac{\lambda}{2m}\sum_{j=1}^{k}\omega_j^2\]

剩下的就是具体的敲代码了!

参考链接:

逻辑回归 logistics regression 公式推导