机器学习(二):逻辑回归

一、原理解释

1.1、从线性回归到逻辑回归

考虑二分类问题y \in \{0,1 \},线性回归模型z=\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b产生的是实值,仍需要转化为0/1值。因此单位阶跃函数(unit-step function)是一个自然的选择,但是阶跃函数不连续,因此考虑采用逻辑函数(logistic function)(Sigmoid函数的一种):y=\frac{1}{1+e^{-z}} 二者图像如下所示:

单位阶跃函数与逻辑函数图像

由此则有:即:

实际上是用线性回归模型的预测结果去逼近真实标记的对数几率。由于是0/1二分类问题上式可改写为:\ln \frac{p(y=1 | \boldsymbol{x})}{p(y=0 | \boldsymbol{x})}=\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b

由此可以得到:\begin{array}{l}{p(y=1 | \boldsymbol{x})=\frac{e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b}}{1+e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b}}} \\ {p(y=0 | \boldsymbol{x})=\frac{1}{1+e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b}}}\end{array}

对于给定的实例x,按照上式可以求得p(y=1 | \boldsymbol{x})p(y=0 | \boldsymbol{x}),通过比较两个条件概率的大小,将实例x分到概率较大的一类。

1.2、模型参数估计

本节采用极大似然估计法(maximum likelihood method)来估计wb
设:p(y=1 | \boldsymbol{x})=p(x), p(y=0 | \boldsymbol{x})=1-p(x)
则似然函数为:\prod_{i=1}^{m}\left[p\left(x_{i}\right)\right]^{y_{i}}\left[1-p\left(x_{i}\right)\right]^{1-y_{i}}
对数似然函数为:\begin{aligned} L(w) &=\sum_{i=1}^{m}\left[y_{i} \log p\left(x_{i}\right)+\left(1-y_{i}\right) \log \left(1-p\left(x_{i}\right)\right)\right] \\ &=\sum_{i=1}^{m}\left[y_{i} \log \frac{p\left(x_{i}\right)}{1-p\left(x_{i}\right)}+\log \left(1-p\left(x_{i}\right) \right)\right] \\ &=\sum_{i=1}^{m}\left[y_{i}\left({\boldsymbol{w}^{\mathrm{T}} x_{i}+b}\right)-\log \left(1+e^{ {\boldsymbol{w}^{\mathrm{T}} x_{i}+b}}\right)\right] \\&=\sum_{i=1}^{m}\left[y_{i}\left(\boldsymbol{\theta}^{\mathrm{T}} \boldsymbol{x}_{i}\right)-\log \left(1+ e^{ {\boldsymbol{\theta}^{\mathrm{T}} \boldsymbol{x}_{i}}} \right)\right] \end{aligned}

L(\theta)求极大值,即得到\theta的估计值。由此问题变为以对数似然函数为目标函数的最优化问题,这是一个高阶可导连续凸函数,可以采用梯度下降法进行求解:
\begin{aligned} \frac{\partial L(\theta)}{\partial \boldsymbol{\theta}_{j}} &=-\sum_{i=1}^{m} \frac{\mathrm{e}^{\boldsymbol{\theta}^{\top} \boldsymbol{x}^{(i)}}}{1+\mathrm{e}^{\boldsymbol{\theta}^{\top} \boldsymbol{x}^{(i)}}} \boldsymbol{x}_{j}^{(i)}+\sum_{i=1}^{m} y^{(i)} \boldsymbol{x}_{j}^{(i)} \\ &=\sum_{i=1}^{m}\left(y^{(i)}-p\left(x_{i}\right)\right) \boldsymbol{x}_{j}^{(i)} \end{aligned}

二、算法实现

2.1 手动实现

以下是通过最大似然估计来求解逻辑回归的过程
1、导入包和文件

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

datafile = 'data2.txt'

2、主函数,实现整个逻辑回归的过程,调用scipy 的优化算法fmin_bfgs(拟牛顿法 Broyden-Fletcher-Goldfarb-Shanno)

def LogisticRegression():
    data = np.loadtxt(datafile,delimiter=',',dtype=np.float64)

    X = data[:,:-1]
    Y = data[:,-1]  

    Xm = MapFeature(X[:,0],X[:,1])  # mapping to polynomial
    init_theta = np.zeros((Xm.shape[1],1))  # initial theta
    init_lambda = 0.1

    J = Cost(init_theta,Xm,Y,init_lambda)   # cost function
    print('J:',J)

    result = optimize.fmin_bfgs(Cost,init_theta,fprime=Gradient,args=(Xm,Y,init_lambda))
    #result = optimize.fmin(Cost,init_theta,args=(Xm,Y,init_lambda))
    p = Predict(Xm,result)
    print('accuracy:{}'.format(np.mean(np.float64(p==Y)*100)))

    plot_boundary(result,X,Y)

3、数据映射,因为数据的feature可能很少,导致偏差大,映射为二次方的形式:1+x_{1}+x_{2}+x_{1}^{2}+x_{1} x_{2}+x_{2}^{2}

def MapFeature(x1,x2):
    max_degree = 2      # 1,x1,x2,xi^2,x1x2,x2^2
    out = np.ones((x1.shape[0],1))   # output after mapping

    for i in range(1,max_degree+1):
        for j in range(i+1):
            temp = np.multiply(x1**(i-j),(x2**j))
            out = np.hstack((out,temp.reshape(-1,1)))
    return out

4、代价函数与梯度函数,考虑了正则化

def Cost(init_theta,X,Y,init_lambda):
    m = len(Y)
    J = 0
    p = 1-Sigmoid(np.dot(X,init_theta))  # calculate p
    theta = init_theta.copy()
    theta[0] = 0

    temp = np.dot(np.transpose(theta),theta)    # considering regularization
    J = (-np.dot(np.transpose(Y),np.log(p)) - np.dot(np.transpose(1-Y),np.log(1-p)))/m + temp*init_lambda/(2*m)
    return J
def Gradient(init_theta,X,Y,init_lambda):
    m = len(Y)
    grad = np.zeros((init_theta.shape[0]))

    p = 1-Sigmoid(np.dot(X,init_theta))  # calculate p
    theta = init_theta.copy()
    theta[0] = 0

    grad = -np.dot(np.transpose(X),p-Y)/m + init_lambda/m*theta
    return grad

5、激活函数与预测函数

def Sigmoid(z):
    return 1.0/(1.0+np.exp(-z))
def Predict(X,theta):
    m = X.shape[0]
    p = np.zeros((m,1))
    p = 1-Sigmoid(np.dot(X,theta))
    for i in range(m):
        if p[i]>0.5:
            p[i]=1
        else:
            p[i]=0
    return p

6、绘图函数,边界以等高线的形式绘制

def plot_boundary(theta,X,Y):
    c0 = np.where(Y==0)
    c1 = np.where(Y==1)
    plt.plot(X[c0,0],X[c0,1],'ro')
    plt.plot(X[c1,0],X[c1,1],'y*')
    #u = np.linspace(30,100,100)
    #v = np.linspace(30,100,100)
    u = np.linspace(-1,1.5,50)
    v = np.linspace(-1,1.5,50)
    z = np.zeros((len(u),len(v)))
    for i in range(len(u)):
        for j in range(len(v)):
            z[i,j] = np.dot(MapFeature(u[i].reshape(1,-1),v[j].reshape(1,-1)),theta)
    z = np.transpose(z)
    plt.contour(u,v,z,[0,0.01])
    plt.show()

7、调用主函数

if __name__=='__main__':
    LogisticRegression()

运算结果如下所示:
散点图及分类边界

2.2、调用sklearn包

调用sklearn的linear_model中的LogisticRegression模型,实现过程如下:

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

datafile = 'data2.txt'

def Logistic_Regression():
    data = np.loadtxt(datafile,delimiter=',',dtype=np.float64)

    X = data[:,:-1]
    Y = data[:,-1]

    x_train,x_test,y_train,y_test = train_test_split(X,Y,test_size=0.2)
    scaler = StandardScaler()   
    scaler.fit(x_train)
    x_train = scaler.transform(x_train)
    scaler.fit(x_test)
    x_test = scaler.transform(x_test)

    model = LogisticRegression()
    model.fit(x_train,y_train)

    predict = model.predict(x_test)
    right = sum(predict==y_test)

    print('accuracy:',right/len(predict)*100)

if __name__=='__main__':
    Logistic_Regression()

模型预测的准确率为 accuracy: 54.166666666666664

获取原始数据请点击这里,感谢lawlite19的贡献。

三、问题讨论

在以上实现的过程中,遇到了以下问题,现加以分析和阐明。

3.1、正则化

在回归和分类参数估计的过程中,当模型过于简单时,会发生欠拟合,而当模型过于复杂时,会发生过拟合,这两种问题都是要避免的。为避免过拟合,在进行参数估计时,正则化是一种常见方式。

回归中的欠、正常、过拟合
分类中的欠、正常、过拟合

正则化(regularization)通过保留所有的特征,但是减少参数大小,以在学习过程中降低模型复杂度和不稳定程度,从而避免过拟合的危险。

在上述实现过程中,我们正则化项采取了如下的平方项(因为不知道哪些特征需要惩罚,因此对所有参数进行惩罚),其中\lambda为正则化参数。
J(\theta)=\frac{1}{2 m}\left[\sum_{i=1}^{m}\left(\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}+\lambda \sum_{j=1}^{n} \theta_{j}^{2}\right)\right]

L1、L2正则化
范数的一般化定义:\|x\|_{p} :=\left(\sum_{i=1}^{n}\left|x_{i}\right|^{p}\right)^{\frac{1}{p}}
当p=1时,是L1范数,其表示某个向量中所有元素绝对值的和。
当p=2时,是L2范数, 表示某个向量中所有元素平方和再开根, 也就是欧几里得距离公式。
惩罚项为L1范数的正则化即是L1正则化。因为参数的大小与模型的复杂度成正比,所以模型越复杂,L1范数就越大。使用L1范数也可以实现特征稀疏,导致 W 中许多项变成零。L1正则化是正则化的最优凸近似,相对L2范数的优点是容易求解。
惩罚项为L2范数的正则化即是L2正则化。让L2范数的正则化项\|X\|_{2}最小,可以使W的每个元素都很小,都接近于零。但是与范数L1不同,它不使每个元素都为0,而是接近于零。越小的参数模型越简单,越简单的模型越不容易产生过拟合现象。L2范数不仅可以防止过拟合,而且还使优化求解变得稳定与迅速。

二维情况下L1,L2范数的最优解

左图为L1正则化的约束项,右图为L2正则化的约束项。通过可视化可以发现,使用L1正则化在取得最优解的时候的值为0,相当于去掉了一个特征,这就是为什么L1正则化可以产生稀疏模型,进而可以用于特征选择。而使用L2正则化在取得最优解的时候特征参数都有其值,且值都不同程度变小。这也可以通过公式看出:
在没有L2正则化项时,参数更新形式如下:

考虑L2正则化项时,参数更新形式变为:\theta_{j} =\theta_{j}\left(1-\alpha \frac{\lambda}{m}\right)-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}

从上式可以看到,与未添加L2正则化的迭代公式相比,每一次迭代,\theta_{j}都要先乘以一个小于1的因子,从而使得\theta_{j}不断减小,因此总得来看,\theta_{j}是不断减小的。

3.2、最小二乘与最大似然

最小二乘法是一种数学优化技术,主要是通过未知参数的选择,使模型的拟合值与观测值之差的平方和达到最小。实质上是对模型优劣的衡量做了一个标准,然后设计算法寻找符合这个标准的参数。对于上述拟合问题,即使:
\min _{\theta} J(\theta)=\frac{1}{2} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}=\frac{1}{2}(X \theta-Y)^{T}(X \theta-Y)
采用梯度下降算法,则有:\begin{aligned} \nabla_{\theta} J(\theta) &=\nabla_{\theta}\left(\frac{1}{2}(X \theta-Y)^{T}(X \theta-Y)\right)=\nabla_{\theta}\left(\frac{1}{2}\left(\theta^{T} X^{T}-Y^{T}\right)(X \theta-Y)\right) \\ &=\nabla_{\theta}\left(\frac{1}{2}\left(\theta^{T} X^{T} X \theta-\theta^{T} X^{T} Y-Y^{T} X \theta+Y^{T} Y\right)\right) \\ &=\frac{1}{2}\left(2 X^{T} X \theta-X^{T} Y-\left(Y^{T} X\right)^{T}\right) \\ &=X^{T} X \theta-X^{T} Y \\&=0 \end{aligned}

则:\theta=\left(X^{T} X\right)^{-1} X^{T} Y

本文所采用的最大似然估计(maximum likelihood estimation, MLE)一种重要而普遍的求估计量的方法。最大似然法明确地使用概率模型,其目标是寻找能够以较高概率产生观察数据的系统发生树。对于最大似然估计来说,最合理的参数估计量应该使得从模型中抽取该n组样本的观测值的概率最大,也就是概率分布函数或者似然函数最大。
最大似然估计需要已知这个概率分布函数,一般假设其满足正态分布函数的特性,在这种情况下,最大似然估计与最小二乘估计是等价的,也就是估计的结果是相同的。

参考资料

[1] https://github.com/lawlite19/MachineLearning_Python
[2] 周志华 著. 机器学习. 北京:清华大学出版社,2016
[3] 李航 著. 统计学习方法. 北京:清华大学出版社,2012
[4] 史春奇等 著. 机器学习算法背后的理论与优化. 北京:清华大学出版社,2019
[5] Peter Harrington 著. 李锐等 译. 机器学习实战. 北京:人民邮电出版社,2013

我知言,我善养吾浩然之气。 ——《孟子·公孙丑上》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容