逻辑回归原理简述及代码实现

1 逻辑回归原理

逻辑回归与线性回归本质上来说是类似,相较线性回归来说只是多了一个Logistic函数(或称为Sigmoid函数)。

1.1 线性回归

机器学习最通俗的解释就是让机器学会决策。对于我们人来说,比如去菜市场里挑选芒果,从一堆芒果中拿出一个,根据果皮颜色、大小、软硬等属性或叫做特征,我们就会知道它甜还是不甜。类似的,机器学习就是把这些属性信息量化后输入计算机模型,从而让机器自动判断一个芒果是甜是酸,这实际上就是一个分类问题。

分类和回归是机器学习可以解决两大主要问题,从预测值的类型上看,连续变量预测的定量输出称为回归;离散变量预测的定性输出称为分类。例如:预测明天多少度,是一个回归任务;预测明天阴、晴、雨,就是一个分类任务。

1.2 逻辑回归

Logistic Regression原理与Linear Regression回归类似,其主要流程分为:
(1)构建预测函数。一般来说在构建之前,需要根据数据来确定函数模型,是线性还是非线性。
(2)构建Cost函数(损失函数)。该函数表示预测的输出(h)与训练数据类别(y)之间的偏差,可以是二者之间的差(h-y)或者是其他的形式。综合考虑所有训练数据的“损失”,将Cost求和或者求平均,记为J(θ)函数,表示所有训练数据预测值与实际类别的偏差。
(3)采用梯度下降算法,minJ(θ)。在数据量很大时,梯度下降算法执行起来会较慢。因此出现了随机梯度下降等算法进行优化。

2 具体过程

2.1 构造预测函数

在线性回归中模型中预测函数为:
单变量线性回归预测函数
逻辑回归作为分类问题,结果h = {1 or 0}即可。若逻辑回归采用线性回归预测函数则会产生远大于1或远小于0得值,不便于预测。因此线性回归预测函数需要做一定改进。设想如果有一个函数h(x)能够把预测结果值压缩到0-1这个区间,那么我们就可以设定一个阈值s,若h(x) >= s,则认定为预测结果为1,否之为0。
实际中也存在这样函数:Logistic函数(或称为Sigmoid函数),函数表达式为:
Sigmoid函数
Sigmoid函数
从上图可以看到,g(z)随着z不断增大越来越靠近1但不会超过1,相反随着z不断减少越来越靠近0但不会小于0。此类函数完美满足前面线性函数作为逻辑回归函数模型中得不足。因此集合Sigmoid函数就可以构造预测函数。
接下来需要确定数据划分的边界类型,对于图1和图2中的两种数据分布,显然图1需要一个线性的边界,而图2需要一个非线性的边界。接下来我们只讨论线性边界的情况。
图1图2在构建预测函数时,首先通过数据得到大概得决策边界。例图1中的边界为线性边界。本文也只分析线性边界。
在这里插入图片描述
经过公式1与公式2整合,得到公式3,即逻辑回归预测函数。hθ(x)函数的值有特殊的含义,它表示结果取1的概率,因此对于输入x分类结果为类别1和类别0的概率分别为:
在这里插入图片描述

2.2 构造损失函数J(θ)

损失函数J(θ)是由极大似然法推导而来,本文暂时不给出公式推导,直接借用吴恩达老师课中给出的损失函数J(θ)。
在这里插入图片描述
对上述公式进行整合可以得到如下公式:
在这里插入图片描述上述公式则为逻辑回归的损失函数J(θ),接下则需要通过训练减少J(θ)。

2.3 采用梯度下降算法minJ(θ)

求J(θ)可以通过最小值可以通过梯度下降算法,根据梯度下降算法可以得到θ不断更新的过程。
在这里插入图片描述
定义一个f(x),f(x)原型和求导如下。
在这里插入图片描述
对θ更新会用到上式公式,读者可以自己推导一下。
求偏导如下:
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.4 采用向量化进行优化

对θ更新时,需要多层循环嵌套取得一些值,对此用向量化来进行优化。
假设有m个样本,每个样本有n+1个特征,θ0 = 1,则就可以构建一个mx(n+1)的样例矩阵。
在这里插入图片描述
特征值向量
在这里插入图片描述
在这里插入图片描述对A矩阵经过sigmod函数处理,得到预测函数h和误差矩阵。
在这里插入图片描述
通过构建此类矩阵,并按照一定的运算规则,会加快梯度下降速度。α为学习步长。
在这里插入图片描述

同理对其它θ参数更新时规则如下:
在这里插入图片描述与其像上面逐步分开求θ参数变化,可以将θ整合到一块处理更快速。
在这里插入图片描述以上是向量化全部介绍。通过向量化不仅可以减少出错,还可以提高效率,建议多使用向量化来进行编程,解决实际问题。

3 python实现逻辑回归

import numpy as np
import matplotlib.pyplot as plt

class LogisticReg():

    def __init__(self):
        pass

    def sigmod(self,x):
        return 1.0/(1+np.exp(-x))
    
    def get_data(self,path):

        self.x = []
        self.y = []
        dat = open(path)

        for line in dat:
            temp = line.split()
            self.x.append(temp[:2])
            self.y.append(temp[2])
        self.y = list(map(lambda x:float(x),self.y))
        self.y = np.array(self.y)
        self.y = self.y.reshape((len(self.y, )))
        self.x = np.array(self.x)
        self.x = self.x.reshape((len(self.x), len(self.x[0])))
        self.x = self.stringTofloat(self.x)
        # print(self.x,self.y)

    def init_data(self,path):
        data = np.loadtxt(path)
        # print(data)
        dataMatIn = data[:,0:-1]
        dataLabel = data[:,-1:]
        dataMatIn = np.insert(dataMatIn,0,1,axis = 1)
        return dataMatIn,dataLabel

    def stringTofloat(self,number):

        # number is Two-dimensional array
        (m,n) = number.shape
        x = np.zeros((m,n))
        for i in range(m):
            for j in range(n):
                # print(float(number[i,j]))
                x[i][j] = float(number[i][j])
        return x

    def LogisticRegGradinet(self,theta,learing_rate,dataMatIn,dataLabel):
        m = dataMatIn.shape[0]
        dataMatIn = np.mat(dataMatIn)
        dataLabel = np.mat(dataLabel)
        h = self.sigmod(dataMatIn*theta)
        err = h-dataLabel
        weights = theta.copy()
        weights = weights - learing_rate*1.0/m*dataMatIn.transpose()*err
        return weights

    def trainLogisticRegression(self,interations,learing_rate,dataMatIn,dataLabel):
        theta = np.ones((dataMatIn.shape[1],1))
        for i in range(interations):
            theta = self.LogisticRegGradinet(theta,learing_rate,dataMatIn,dataLabel)
        return theta

    def plotBestFIt(self,dataMatIn,dataLabel,weights):
        self.x = dataMatIn.reshape((dataMatIn.shape[0],dataMatIn.shape[1]))
        self.y = dataLabel.reshape((dataLabel.shape[0],))
        m = dataMatIn.shape[0]
        print(weights.shape,weights[0][0],weights[1][0],weights[2][0])
        xcord1 = []
        ycord1 = []
        xcord2 = []
        ycord2 = []
        for i in range(m):
            if self.y[i] == 1:
                xcord1.append(self.x[i][1])
                ycord1.append(self.x[i][2])
            else:
                xcord2.append(self.x[i][1])
                ycord2.append(self.x[i][2])
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
        ax.scatter(xcord2, ycord2, s=30, c='green')
        x = np.arange(-3, 3, 0.1)
        y = (-float(weights[0][0]) - (float(weights[1][0]) * x)) / float(weights[2][0])  # matix
        ax.plot(x, y)
        plt.xlabel('X1')
        plt.ylabel('X2')
        plt.show()

    def run(self):

        path = "D:\\Data\\LogisticReg\\data.txt"
        dataMatIn,dataLabel = self.init_data(path)
        interations = 5000 #最大迭代次数
        learing_rate = 0.01 #学习步长
        theta = self.trainLogisticRegression(interations,learing_rate,dataMatIn,dataLabel)
        self.plotBestFIt(dataMatIn,dataLabel,theta)

    def test(self):
        self.init_data("D:\\Data\\LogisticReg\\data.txt")


if __name__ == "__main__":

    f = LogisticReg()
    f.run()
    # f.test()

参考文章
机器学习之逻辑回归(纯python实现)
逻辑回归(Logistic Regression, LR)简介

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值