逻辑回归

1、逻辑回归简介
       逻辑回归也叫对数几率回归,理解了线性回归,逻辑回归理解起来就容易多了。逻辑回归虽然名字叫做回归,但实际上却是一种分类学习方法。线性回归完成的是回归拟合任务,而对于分类任务,我们同样需要一条线,但不是去拟合每个数据点,而是把不同类别的样本区分开来。
                                                        
2、假设函数
       线性回归中预测函数为:
                                                   
它的值域为R。
而我们需要的是个分类模型,对于二分类问题来说结果不是1(正例)就是0(负例),。怎么样实现在线性回归的基础上实现分类功能呢?我们知道线性回归的输出值为:
我们可以寻找一个假设函数将线性回归输出的值映射到0,1之间,如果>=0.5,则y=1,否则y=0。
我们发现有一个函数,叫做对数几率函数(logistic function):
                                                                             
它的图像如下:
                                                              
对数几率函数是Sigmoid函数(形状为S型的函数)的重要代表,它的定义域为R,值域为(0,1)。把线性回归的输出值当做对数几率函数的输入值z,则输出值在0~1之间,刚好符合我们的要求。
则逻辑回归的假设函数为:
                                                                      
对于更直观的解释是:对于给定的输入x,表示该样本属于正例y=1的概率。

1.为什么逻辑回归又叫对数几率回归?
逻辑回归假设函数可以变形为:
                                                                                   

是x属于正例的概率,则是x属于负例的概率,两者比值叫做几率(odds),表示x作为正例相对负例的可能性,取对数就叫对数几率。
2.也有其它值域为(0,1)的函数,为什么选择对数几率函数?
参考:https://blog.csdn.net/a1628864705/article/details/62233395

3、损失函数/代价函数
线性回归中我们采用的是平方误差:
                                                                       
但是当我们把
                                                                                 
带入上式时,得到的是一个非凸函数(下面左图)
                                                       
这意味着代价函数有许多局部最小值,这无疑影响了我们寻找全局最优解。
     于是我们转换思路,既然是分类问题,那么我们可以对每个类别分别计算它们各自的损失。对于正例,预测值越接近1,损失越小;对于负例越接近0,损失越小。-log(x)函数正好满足以上情况,图像如下:

                                                   

这样每个样本的损失计算公式为:
                                                     
合并后(方便后面计算和书写):
                                                
则逻辑回归的代价函数计算公式为:
                                                           

即为:
                                             

4、求最优解
求解使代价函数最小的参数θ,这里使用梯度下降法。
其梯度更新公式为:
                                         
                                               \theta_{j}:=\theta_{j}-\alpha \frac{\alpha }{\alpha _{\theta _{j}}}J(\theta )=\theta_{j}-\alpha \frac{1}{m}\sum_{m}^{1}[(h_{\theta }(x^{(i)})-y^{(i)})x_{j}^{(i)}]

其中:
                                         
                                        
除了梯度下降算法外,还有其它算法被用来求最优解,这些算法更加复杂和优越,而且不需要人工选择学习率,通常还更快。有共轭梯度,局部优化法,有限内存局部优化法。

5、多类别分类
前面讲的是二分类情况,当遇到多分类时怎么实现分类呢?
                                                        
上面二图分别展示二分类和多分类,不同符号代表不同类别。
对于多分类,我们可以把它变为多个二分类问题
                                                 
首先我们把class1当作正例,然后将其它所有类记为负例,训练得到。然后把class2当作正例,其它所有类当作负例,训练得到模型,依次类推。
                    
做预测时,我们选择一个让最大的,即

6、正则化
正则化用来解决过拟合问题。


1.什么是过拟合?
先看看下面这些图(回归问题):
                          
第一个图,模型不能很好的拟合我们的原始数据,欠拟合;
第三个图,是个四次方的模型,过于强调拟合原始数据,过拟合。若给出一个新的值使之预测,它将表现很差。即泛化能力差;
中间的模型是比较合适的。
分类问题也存在这样的问题:
                             
x的次数越高,或者说模型越复杂,拟合的越好,但预测能力可能变差,这就是过拟合。

2.如何解决过拟合?
a.正则化;
b.增加数据样本;
c.PCA、特征那选择等技术降维、去掉冗余特征;
d.提前结束训练;
这里我们讲使用正则化方法来解决过拟合问题。

3.什么是正则化?
回归问题中如果我们的模型是:
                                                     
对我们结果影响最大的往往是高次项,那么我们所要做的就是减小高次项的系数,从而减小高次项的影响。正则化就是保留所有特征,但是减小参数大小。

4.如何实现正则化?
       我们知道,正则化是要减小参数,即对特征进行惩罚,但是我们并不知道惩罚哪些特征,也不知道惩罚的程度。我们可以放入代价函数中,让优化算法来选择。
在线性回归中,加入正则化的代价函数为:
                                                       
为惩罚系数。
在逻辑回归中,加入正则化的代价函数为:
                                   


5.如何选择合适的惩罚系数?
       若太大,那么所有系数都会趋近于0,这样容易造成欠拟合。至于如何选择合适的惩罚系数,这个我在网上找了下暂时没找到,我觉得可以用学习率的选择方法来选择。

7、正则化的逻辑回归
从上面我们可以知道,加入正则项的代价函数为:
                                 
使用梯度下降法,对代价函数求导,得其梯度更新方式为:
                                                       
注意:
1.不参与其中的任何一个正则化。
2.使用梯度下降法一定要做Feature Scaling。

8、代码实现(python)

# -*- coding: utf-8 -*-

import numpy as np
from sklearn.datasets import load_breast_cancer   #导入威斯康辛州乳腺癌数据
from sklearn import linear_model                  #导入sklearn库线性模型

class LogisticRegression:
    penalty_coef = 0.5  #惩罚系数
    learing_rate = 0.05 #学习率
    num_iter = 300      #迭代次数
    theta = []          #参数
    
    #训练函数
    def fit(self, X, y):
       X = np.matrix(X)                       #转成矩阵
       y = y.reshape(len(y),-1)               #转成列的形式
       y = np.matrix(y)                       #转成矩阵
       m = X.shape[0]                         #样本数
       X_0 = np.ones((len(X), 1))             #创建分量x0
       X = np.hstack((X_0, X))                #加入分量x0到x中
       
       #step 1.初始化参数为任意值,这里设为全0
       self.theta = np.zeros((X.shape[1], 1))  #初始化参数
       
       #step 2.求解梯度(注意:theta_0不参与任何一个正则化)
       grad = (X.T * (sigmoid(X * self.theta) - y)) / m +  self.penalty_coef / m * self.theta
       grad[0,0] = grad[0,0] - self.penalty_coef / m * self.theta[0,0]    #theta_0不参与正则化所以要减去一个正则项
       
       #step 3.更新参数(同步更新)
       self.theta = self.theta - self.learing_rate * grad
       
       #step 4. 若达到指定迭代次数或收敛条件,训练结束,否则,继续执行step2、step3
       for i in range(self.num_iter):
           
            #求解梯度
            grad = (X.T * (sigmoid(X * self.theta) - y)) / m + self.penalty_coef / m * self.theta
            grad[0,0] = grad[0,0] - self.penalty_coef / m * self.theta[0,0]
            
            #更新参数(同步更新)
            self.theta = self.theta - self.learing_rate * grad

            #看每次迭代更新参数后的代价函数值
            first = np.sum((-y).T * np.log(sigmoid(X * self.theta)) - (1 - y).T * np.log(1 - sigmoid(X * self.theta))) / m
            second = self.penalty_coef / (2 * m) * (self.theta[1:,:].T * self.theta[1:,:])
            J = first + second
            print(J)
            
    #预测函数        
    def predict(self, test_x):
        M_test_x = np.matrix(test_x)
        x_0      = np.ones((len(M_test_x), 1))                    #创建分量x0
        M_test_x = np.hstack((x_0, M_test_x))                     #加入分量x0到x中    
        result   = (sigmoid(M_test_x * self.theta) >= 0.5) + 0   #预测结果,+0是把false/true转为0/1
        return result    
            
#对数几率函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


if __name__ == '__main__':
    X, y = load_breast_cancer(return_X_y = True)        #取出威斯康辛州乳腺癌数据
    X = (X - np.mean(X, axis=0)) / np.std(X, axis = 0)  #featrue scaling
    
    #自己的模型结果
    my_lr = LogisticRegression()
    my_lr.fit(X,y)
    estimate1 = my_lr.predict(X[-10:,:])
    
    #sklearn库逻辑回归模型结果
    lr = linear_model.LogisticRegression()
    lr.fit(X,y)
    estimate2 = lr.predict(X[-10:,:])
    
    #打印输出,对比结果
    for i in range(10):
        print("实际值:",y[-10+i]," 估计值1:",estimate1[i,0],"估计值2:", estimate2[i])
    
    
    
    

 

参考:
《统计学习方法》李航
《机器学习》吴恩达
https://www.cnblogs.com/lianyingteng/p/7679825.html
https://blog.csdn.net/jk123vip/article/details/80591619
https://blog.csdn.net/a1628864705/article/details/62233395

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值