美文网首页
一切从逻辑回归开始

一切从逻辑回归开始

作者: JSong1122 | 来源:发表于2016-11-06 14:05 被阅读596次

    JSong @2016.06.13

    本系列文章不适合入门,是作者综合各方资源和个人理解而得. 另外最好有数学基础, 因为数学人一言不合就会上公式.

    简单模型的魅力在于它能从各个角度去欣赏. 逻辑回归是最简单的二分类模型之一,实际应用中二分类最常见,如判定是否是垃圾邮件,是否是人脸,是否值得借贷等, 而概率模型对于这类问题有得天独厚的优势. 本文将从各个角度来理解逻辑回归,并指出它是一个概率模型、对数线性模型、交叉熵模型.

    我们先从线性回归谈起。 考察$m$个变量和$y$之间的线性关系:

    我们的目的就是找到一种模型将这两类样本点分开(当然实际应用中可能没有这么好的情况。 这里只是给一个Demo)。 最直接的想法就是找一个超平面$\theta^T x=0$, 使得红色点和蓝色点分别分布于超平面的两端. 此时对于任意一个样本点$x^{(i)}$, 不失一般性$\theta^T x^{(i)}$可以代表样本点到该超平面的距离。 因为红色样本点在超平面上方,即红点对应距离为正数,同理蓝点对应的距离为负数。 为避免区分红点或者蓝点,我们可以用$(2y-1)\theta^T x$来代替, 此时只要被正确分类, 该距离则为正数,否则为负数。 于是可得相应的损失函数为![](http://latex.codecogs.com/gif.latex?\\max(0,(2y-1)\theta^Tx.) 综合一下可得最简单的线性分类模型为:
    ![](http://latex.codecogs.com/gif.latex?\\arg_\theta \min \sum_{i=1}^{m} \max[0,(2y_i-1)\theta^T x^{(i)}])
    这个损失函数有很多不好的地方,而且也不可导。接下来我们介绍更好的逻辑回归模型,其背后有很多的解释。

    1.1 逻辑回归模型

    令![](http://latex.codecogs.com/gif.latex?\\theta^T x=\theta_0 +\sum_{i=1}^{m} \theta_i x_i,) 且我们假定
    \begin{eqnarray}
    &P(y=1|x; \theta)=h_{\theta}(x)=g(\theta^T x)=\frac{1}{1+e{-\thetaT x}}\
    &P(y=0|x; \theta)=1-h_{\theta}(x)
    \end{eqnarray}
    其中

    这里我们采用极大似然估计. 由于y取值的特殊性, 上面的模型假设等价于

    1.3 线性代数意义

    在上一节,我们给出了表达式
    ![](http://latex.codecogs.com/gif.latex?\theta^T x=\log \frac{p}{1-p}, \quad p=P(y=1|x))
    可以看出它相当于把y映射到了[0,1]区间。而且p/(1-p)是事件发生与事件不发生的概率之比,称为事件的发生比(the odds of experiencing an event),简称为odds。

    1.4 信息论解释(交叉熵模型)

    令随机变量$p\in {y,1-y}$, $q \in{\hat{y},1-\hat{y}}$, 其中$\hat{y}$为模型拟合得到的y, 则它们之间的交叉熵(cross entropy) 为
    ![](http://latex.codecogs.com/gif.latex?\H(p,q)= -\sum_i p_i \log q_i =-[y\log \hat{y}+(1-y)\log(1-\hat{y})].)我们知道熵常用于度量一个随机变量所包含的信息量, 而交叉熵可以用来度量两个随机变量之间的相似性, 从上面式子可以看出逻辑回归的极大似然等价于最小化交叉熵.

    1.5 神经网络模型

    这个就不多说了,逻辑回归是一个最简单的神经网络模型

    1.6 梯度下降法参数求解

    按照极大似然的来求导:
    ![](http://latex.codecogs.com/gif.latex?\\bigtriangledown_{\theta} l(\theta)=\sum_{i=1}^{m} [y{(i)}-h_{\theta}[x{(i)}]]x^{(i)}= X^T[Y-h_{\theta}(X)])
    其中$x^{(i)}$在$X$中作为行向量存储. 于是可得参数$\theta$的迭代式子:
    ![](http://latex.codecogs.com/gif.latex?\\theta:=\theta+\alpha X^T[Y-h_{\theta}(X)])其中$\alpha$为步长, 因为是最大化$l(\theta)$,所以是沿着梯度的正方向寻找。

    1.7 python代码

    import numpy as np
    import matplotlib.pyplot as plt
    import time
    %pylab inline
    
    # calculate the sigmoid function
    def sigmoid(inX):
        return 1.0 / (1 + np.exp(-inX))
    
    
    
    def trainLogRegres(train_x, train_y, opts):
        # train a logistic regression model using some optional optimize algorithm
        # train_x is a mat datatype, each row stands for one sample
        # train_y is mat datatype too, each row is the corresponding label
        # opts is optimize option include step and maximum number of iterations
    
        # calculate training time
        startTime = time.time()
        train_x=np.asmatrix(train_x)
        train_y=np.asmatrix(train_y)
        numSamples, numFeatures =train_x.shape
        alpha = opts['alpha']; maxIter = opts['maxIter']
        weights = np.ones((numFeatures, 1))
        for k in range(maxIter):
            err = train_y - sigmoid(train_x * weights)
            weights = weights + alpha * train_x.T * err
        print 'Congratulations, training complete! Took %fs!' % (time.time() - startTime)
        return weights
    
    
    # show your trained logistic regression model only available with 2-D data
    def showLogRegres(weights, train_x, train_y):
        # notice: train_x and train_y is mat datatype
        numSamples, numFeatures = train_x.shape
        if numFeatures != 3:
            print "Sorry! I can not draw because the dimension of your data is not 2!"
            return 1
    
        # draw all samples   
        idx1=np.asarray(train_y)==1
        idx2=np.asarray(train_y)==0
        plt.plot(x[:,1][idx1].T,x[:,2][idx1].T,'or')
        plt.plot(x[:,1][idx2].T,x[:,2][idx2].T,'ob')
        # draw the classify line
        min_x = min(train_x[:, 1])[0, 0]
        max_x = max(train_x[:, 1])[0, 0]
        weights = weights.getA()  # convert mat to array
        y_min_x = float(-weights[0] - weights[1] * min_x) / weights[2]
        y_max_x = float(-weights[0] - weights[1] * max_x) / weights[2]
        plt.plot([min_x, max_x], [y_min_x, y_max_x], '-g')
        plt.xlabel('X1'); plt.ylabel('X2')
    
    # 测试样例
    len_samples=500
    x=np.random.randn(len_samples,2)
    idx1=x[:,0]+x[:,1]>0.5
    y=np.zeros((len_samples,1))
    y[idx1,0]=1
    opt={'alpha':0.1,'maxIter':1000}
    x=np.hstack((np.ones((len_samples,1)),x))
    x=np.asmatrix(x)
    y=np.asmatrix(y)
    w=trainLogRegres(x,y,opt)
    print w
    showLogRegres(w,x,y)
    
    Populating the interactive namespace from numpy and matplotlib
    Congratulations, training complete! Took 0.047000s!
    [[-17.37216188]
     [ 34.35470115]
     [ 34.98381818]]
    

    这只是最简单的样例,在实际应用中我们还可以添加惩罚项
    ![](http://latex.codecogs.com/gif.latex?\ \min_{w,c} |w|2+ C\sum{i=1}^{m} \log[1+\exp[-y^{(i)}[w\cdot x^{(i)}+c]]])
    或者$L_1$范数
    ![](http://latex.codecogs.com/gif.latex?\\min_{w,c} |w|1+ C\sum{i=1}{m}\log[1+\exp[-y{(i)}[w\cdot x^{(i)}+c]]])
    在样本很稀疏的时候,惩罚项很有用. 另外当样本量很大,我们又极其要求速度的时候,梯度下降法也要改进,换成SGD(stochastic gradient descent )、拟牛顿法、AGD等等

    1.8 变量选择

    作为实际应用,我们还需要考虑一个变量是否值得加入模型。 对于不同的模型采取的方法一般也不一样。变量选择:网址链接

    1. 前向选择(forward selection):一个一个变量慢慢添加。找到一种指标(刻画加入模型使得模型拟合准确度提高的程度),若某个变量对应的指标符合要求,则加入模型;重新计算指标;重复以上几步。

    2. 后向选择(backward selection):在模型包括所有候选变量的基础上,将不符合保留要求显著水平的自变量一次一个地删除。

    3. 逐步回归(stepwise selection): 逐个引入自变量。每次引入对Y影响最显著的自变量,并对方程中的老变量逐个进行检验,把变为不显著的变量逐个从方程中剔除掉,最终得到的方程中既不漏掉对Y影响显著的变量,又不包含对Y影响不显著的变量。

    经常被问到的一个问题就是共线性,这个注意下。共线性就是指Y与$x_1$和$x_2$都没有显著的线性关系,但是Y与$x_1$和$x_2$的某个线性组合线性相关。

    2.0 附录

    1. 常见的几种最优化方法网址链接 最优化方法按 损失函数的凹凸与可导来分类。应该熟悉梯度下降、牛顿法。随机梯度和启发式的方法思想要掌握。机器学习常用的随机梯度下降法还有:SGD

    2. 模型评价网址链接 这个也是比较重要的,常用的如召回率和ROC曲线。

    3. 模型参数选择网址链接: 比如若有1000个样本,其中800个样本点用来训练,200个样本用来交叉验证。

    4. 模型提升,模型强化: 关键词Boosting、GBDT等

    参数设置

    相关文章

      网友评论

          本文标题:一切从逻辑回归开始

          本文链接:https://www.haomeiwen.com/subject/cwxnuttx.html