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

作者: fromeast | 来源:发表于2019-07-02 20:06 被阅读2次

    一、原理解释

    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

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

    相关文章

      网友评论

        本文标题:机器学习(二):逻辑回归

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