其他分享
首页 > 其他分享> > 机器学习笔记8-Logistic回归基础

机器学习笔记8-Logistic回归基础

作者:互联网

一、基础知识

1 回归的含义

回归即为最佳拟合,用一条直线对这些点进行拟合的过程,逻辑回归过程即为寻找最佳拟合参数的过程,使用的是最优化理论。

2 最优化理论中常用的优化算法

3 逻辑回归思想和优缺点

Logistic主要用于二分类算法,它利用的是Sigmoid函数阈值在[0,1]这个特性。逻辑回归本质就是最大似然参数估计法。

4 Sigmoid函数

hθ(x)=g(θTx)h_\theta(x)=g(\theta^Tx)hθ​(x)=g(θTx)
z=[θ0θ1θ2...θn][θ0θ1θ2...θn]T=θnTXz=[\theta_0 \theta_1 \theta_2... \theta_n ][\theta_0 \theta_1 \theta_2... \theta_n ]^T=\theta_n ^TXz=[θ0​θ1​θ2​...θn​][θ0​θ1​θ2​...θn​]T=θnT​X
g(Z)=11+ezg(Z)={1\over{1+e^{-z}}}g(Z)=1+e−z1​
可得:hθ(x)=g(θTx)=11+eθTx\bf h_\theta(x)=g(\theta^Tx)={1\over{1+e^{-\theta^Tx}}}hθ​(x)=g(θTx)=1+e−θTx1​
Sigmoid函数:
在这里插入图片描述θ\thetaθ是参数列向量(待求解未知量),xxx是样本列向量(给定的数据集)。g(z)g(z)g(z)函数实现了任意实数到[0,1]的映射,这样我们的数据集x0,x1,x2...xnx_0,x_1,x_2...x_nx0​,x1​,x2​...xn​,不管是大于1还是小于0,都可以映射到[0,1]区间分类。hθ(x)h_\theta(x)hθ​(x)给出了输出为1的概率,比如hθ(x)=0.7h_\theta(x)=0.7hθ​(x)=0.7,说明有70%的概率输出为1,输出0的概率是输出1的补集,也就是30%。
如果我们有合适的参数列向量θ\thetaθ和样本列向量X,那么我们对样本X分类就可以通过上述公式计算出一个概率,如果概率大于0.5,可以说样本是正样本,否则样本是负样本。
根据Sigmoid函数特性,做出以下假设:
P(y=1x;θ)=hθ(x)P(y=1|x;\theta)=h_\theta(x)P(y=1∣x;θ)=hθ​(x) P(y=0x;θ)=1hθ(x)P(y=0|x;\theta)=1-h_\theta(x)P(y=0∣x;θ)=1−hθ​(x)
上式即为在已知样本xxx和参数θ\thetaθ情况下,样本xxx属于正样本(y=1)和负样本(y=0)的条件概率。理想状态下,根据上述公式,求出各点的概率均为1,也就是分类完全正确。但是考虑实际情况,样本点概率越接近1分类效果越好。比如,一个样本属于正样本的概率为0.99,那么说明这个样本属于正样本。我们可以把上述两个概率公式合二为一:
Cost(hθ(x),y)=hθ(x)y(1hθ(x))1yCost(h_\theta(x),y)=h_\theta(x)^y(1-h_\theta(x))^{1-y}Cost(hθ​(x),y)=hθ​(x)y(1−hθ​(x))1−y我们对整个表达式求对数:
Cost(hθ(x),y)=yloghθ(x)+(1y)log(1hθ(x))Cost(h_\theta(x),y)=y\log_{}{h_\theta(x)}+(1-y)\log_{}{(1-h_\theta(x))}Cost(hθ​(x),y)=ylog​hθ​(x)+(1−y)log​(1−hθ​(x))给定一个样本,我们可以通过这个函数求出,样本所属类别的概率,而且这个概率越大越好,所以也就是求解这个函数的最大值。既然概率出来了,那么最大似然估计也该出场了。假定样本与样本之间互相独立,那么整个样本集生成的概率即为所有样本生成概率的乘积,再将公式对数化,可得:
在这里插入图片描述其中,m为样本的总数,y(i)表示第i个样本的类别,x(i)表示第i个样本。
综上所述,满足J(θ)J(\theta)J(θ)的最大值的θ\thetaθ即是我们需要求解的模型。

5 梯度上升法

先举一个简单求极大值的例子:f(x)=x2+4xf(x)=-x^2+4xf(x)=−x2+4x
求极值,先求函数导数:f(x)=2x+4f'(x)=-2x+4f′(x)=−2x+4令导数为0,可求出x=2x=2x=2即取得函数f(x)的极大值。
但是真实环境中函数不会像上面这么简单,就算求出函数导数,也很难精确计算出函数的极值。此时我们就可以用迭代的方法来做,就像爬坡一样,一点一点逼近极值。这种寻找最佳拟合参数的方法,就是最优化算法。爬坡这个动作用数学公式表达即为:xi+1=xi+αf(xi)xi\bf x_{i+1}=x_i+α\frac{\partial f(x_i)}{x_i}xi+1​=xi​+αxi​∂f(xi​)​其中,α为步长,也就是学习速率,控制更新的幅度,效果如下图:在这里插入图片描述比如从(0,0)开始,迭代路径就是1⟶2⟶3⟶4⟶…⟶n,直到求出的x为函数极大值的近似值,停止迭代。

def Gradient_Ascent_test():
    # f(x)的导数
    def f_prime(x_old):
        return -2 * x_old +4
    # 初始值,给一个小于x_new的值
    x_old = -1
    # 梯度上升算法初始值,即从(0,0)开始
    x_new = 0
    # 步长,也就是学习效率,控制更新的幅度
    alpha = 0.01
    # 精度,也就是更新阈值
    presision = 0.00000001
    while abs(x_new - x_old) > presision:
        x_old = x_new
        # 上面提到的公式
        x_new = x_old + alpha * f_prime(x_old)
    #     打印最终求解的极值近似值
    print(x_new)

if __name__ == '__main__':
    Gradient_Ascent_test()

这一过程就是梯度上升算法。同理,J(θ)J(\theta)J(θ)函数极值,也可以这样求解,公式可以写为:θj:=θj+αJ(θ)θj\bf\theta_j:=\theta_j+α\frac{\partial J(\theta)}{\theta_j}θj​:=θj​+αθj​∂J(θ)​由上小节可知:
在这里插入图片描述Sigmoid函数为:hθ(x)=g(θTx)=11+eθTxh_\theta(x)=g(\theta^Tx)={1\over{1+e^{-\theta^Tx}}}hθ​(x)=g(θTx)=1+e−θTx1​现在,只要求出J(θ)J(\theta)J(θ),就可以利用梯度上升算法,求解极大值啦。
J(θ)θj=J(θ)g(θTx)g(θTx)θTxθTxθj\frac{\partial J(\theta)}{\theta_j}=\frac{\partial J(\theta)}{\partial g(\theta^Tx)}*\frac{\partial g(\theta^Tx)}{\partial \theta^Tx}*\frac{\partial \theta^Tx}{\partial \theta_j}θj​∂J(θ)​=∂g(θTx)∂J(θ)​∗∂θTx∂g(θTx)​∗∂θj​∂θTx​
其中:
J(θ)g(θTx)=y1g(θTx)+(y1)11g(θTx)\frac{\partial J(\theta)}{\partial g(\theta^Tx)}=y*\frac{1}{g(\theta^Tx)}+(y-1)*\frac{1}{1-g(\theta^Tx)}∂g(θTx)∂J(θ)​=y∗g(θTx)1​+(y−1)∗1−g(θTx)1​
再由:
g(z)=ddz11+ez=1(1+ez)2(ez)=11+ez(111+ez)=g(z)(1g(z))g'(z)=\frac{d}{dz}\frac{1}{1+e^{-z}}=\frac{1}{(1+e^{-z})^2}(e^{-z})=\frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})=g(z)(1-g(z))g′(z)=dzd​1+e−z1​=(1+e−z)21​(e−z)=1+e−z1​(1−1+e−z1​)=g(z)(1−g(z))
可得:
g(θTx)θTx=g(θTx)(1g(θTx))\frac{\partial g(\theta^Tx)}{\partial \theta^Tx}=g(\theta^Tx)(1-g(\theta^Tx))∂θTx∂g(θTx)​=g(θTx)(1−g(θTx))
第三部分:
θTxθj=J(θ1x1+θ2x2...+θnxn)θj=xj\frac{\partial \theta^Tx}{\partial \theta_j}=\frac{\partial J(\theta_1x_1+\theta_2x_2...+\theta_nx_n)}{\partial \theta_j}=x_j∂θj​∂θTx​=∂θj​∂J(θ1​x1​+θ2​x2​...+θn​xn​)​=xj​
综上所述:
J(θ)θj=(yhθ(x))xj\frac{\partial J(\theta)}{\theta_j}=(y-h_\theta(x))x_jθj​∂J(θ)​=(y−hθ​(x))xj​
因此,梯度上升迭代公式为:θj:=θj+αi=1m(y(i)hθ(x(i)))xj(i)\bf\theta_j:=\theta_j+α\sum_{i=1}^m{(y^{(i)}-h_\theta(x^{(i)}))}x_j^{(i)}θj​:=θj​+αi=1∑m​(y(i)−hθ​(x(i)))xj(i)​

二、功能函数

1 显示数据

将第一列数据(X1)看作x轴上的值,第二列数据(X2)看作y轴上的值。而最后一列数据即为分类标签。根据标签的不同,对这些点进行分类。

import matplotlib.pyplot as plt
import numpy as np

def loadDataSet():
    # 创建数据集
    dataMat = []
    # 创建标签列表
    labelMat = []
    # 打开文件
    fr = open('Logistic')
    # 逐行读取
    for line in fr.readlines():
        # 去回车,放入列表
        lineArr = line.strip().split()
        # 添加数据
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        # 添加标签
        labelMat.append(int(lineArr[2]))
    # 关闭文件
    fr.close()
    # 返回
    return dataMat,labelMat

def plotDataSet():
    # 加载数据集
    dataMat,labelMat = loadDataSet()
    # 转换成numpy的array数组
    dataArr = np.array(dataMat)
    # 数据个数
    n = np.shape(dataMat)[0]
    # 正样本
    xcord1 = []
    ycord1 = []
    # 负样本
    xcord2 = []
    ycord2 = []
    # 根据数据集标签进行分类
    for i in range(n):
        if int(labelMat[i]) == 1:
            # 1为正样本
            xcord1.append(dataArr[i,1])
            ycord1.append(dataArr[i,2])
        else:
            # 0为负样本
            xcord2.append(dataArr[i,1])
            ycord2.append(dataArr[i,2])
    fig = plt.figure()
    # 添加subplot
    ax = fig.add_subplot(111)
    # 绘制正样本
    ax.scatter(xcord1,ycord1,s = 20,c = 'red',marker = 's',alpha=.5)
    # 绘制负样本
    ax.scatter(xcord2,ycord2,s = 20,c = 'green',alpha=.5)
    # 绘制title
    plt.title('DataSet')
    # 绘制label
    plt.xlabel('x')
    plt.ylabel('y')
    # 显示
    plt.show()

if __name__ == '__main__':
    plotDataSet()
    dataMat,labelMat = loadDataSet()
    print(dataMat,labelMat)

从上图可以看出数据的分布情况。假设Sigmoid函数的输入记为z,那么z=w0x0 + w1x1 + w2x2,即可将数据分割开。其中,x0为全是1的向量,x1为数据集的第一列数据,x2为数据集的第二列数据。另z=0,则0=w0 + w1x1 + w2x2。横坐标为x1,纵坐标为x2。这个方程未知的参数为w0,w1,w2,也就是我们需要求的回归系数(最优参数)。

2 梯度上升训练算法

根据梯度上升迭代公式:
θj:=θj+αi=1m(y(i)hθ(x(i)))xj(i)\bf\theta_j:=\theta_j+α\sum_{i=1}^m{(y^{(i)}-h_\theta(x^{(i)}))}x_j^{(i)}θj​:=θj​+αi=1∑m​(y(i)−hθ​(x(i)))xj(i)​将上述公式矢量化:
θj:=θ+αXT(Yg(Xθ))\bf\theta_j:=\theta+αX^T(Y-g(X\theta))θj​:=θ+αXT(Y−g(Xθ))

#!/user/bin/env python
# -*- coding:utf-8 -*-
#@Time  : 2020/3/16 9:51
#@Author: fangyuan
#@File  : Logistic回归梯度上升.py


import numpy as np

def loadDataSet():
    # 创建数据集
    dataMat = []
    # 创建标签列表
    labelMat = []
    # 打开文件
    fr = open('Logistic')
    # 逐行读取
    for line in fr.readlines():
        # 去回车,放入列表
        lineArr = line.strip().split()
        # 添加数据
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        # 添加标签
        labelMat.append(int(lineArr[2]))
    # 关闭文件
    fr.close()
    # 返回
    return dataMat,labelMat

def sigmoid(inX):
    return 1.0/(1+np.exp(-inX))

def gradAscent(dataMatIn,classLabels):
    # 转换成numpy的mat
    dataMatrix = np.mat(dataMatIn)
    # 转换成numpy的mat并进行转置
    labelMat = np.mat(classLabels).transpose()
    # 返回dataMatrix的大小,m为行数,n为列数
    m,n = np.shape(dataMatrix)
    # 移动步长,也就是学习速率,控制更新的幅度
    alpha = 0.001
    # 最大迭代次数
    maxCycles = 500
    weights = np.ones((n,1))
    # 梯度上升矢量化公式
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)
        error = (labelMat - h)
        weights = weights + alpha * dataMatrix.transpose() * error
    # 将矩阵转化为数组,返回权重数组(最优参数)
    return weights.getA()

if __name__ == '__main__':
    dataMat,labelMat = loadDataSet()
    print(gradAscent(dataMat,labelMat))

在这里插入图片描述已经求解出回归系数[w0,w1,w2]。通过求解出的参数,我们就可以确定不同类别数据之间的分隔线,画出决策边界。

3 绘制决策边界

#!/user/bin/env python
# -*- coding:utf-8 -*-
#@Time  : 2020/3/16 10:06
#@Author: fangyuan
#@File  : Logistic回归绘制决策边界.py

import numpy as np
import matplotlib.pyplot as plt

def loadDataSet():
    # 创建数据集
    dataMat = []
    # 创建标签列表
    labelMat = []
    # 打开文件
    fr = open('Logistic')
    # 逐行读取
    for line in fr.readlines():
        # 去回车,放入列表
        lineArr = line.strip().split()
        # 添加数据
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        # 添加标签
        labelMat.append(int(lineArr[2]))
    # 关闭文件
    fr.close()
    # 返回
    return dataMat,labelMat

def sigmoid(inX):
    return 1.0/(1+np.exp(-inX))

def gradAscent(dataMatIn,classLabels):
    # 转换成numpy的mat
    dataMatrix = np.mat(dataMatIn)
    # 转换成numpy的mat并进行转置
    labelMat = np.mat(classLabels).transpose()
    # 返回dataMatrix的大小,m为行数,n为列数
    m,n = np.shape(dataMatrix)
    # 移动步长,也就是学习速率,控制更新的幅度
    alpha = 0.001
    # 最大迭代次数
    maxCycles = 500
    weights = np.ones((n,1))
    # 梯度上升矢量化公式
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)
        error = (labelMat - h)
        weights = weights + alpha * dataMatrix.transpose() * error
    # 将矩阵转化为数组,返回权重数组(最优参数)
    return weights.getA()

def plotBestFit(weights):
    # 加载数据集
    dataMat,labelMat = loadDataSet()
    # 转换成numpy的array数组
    dataArr = np.array(dataMat)
    # 数据个数
    n = np.shape(dataMat)[0]
    # 正样本
    xcord1 = []
    ycord1 = []
    # 负样本
    xcord2 = []
    ycord2 = []
    # 根据数据集标签进行分类
    for i in range(n):
        # 1为正样本
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i,1])
            ycord1.append(dataArr[i,2])
        # 0为负样本
        else:
            xcord2.append(dataArr[i,1])
            ycord2.append(dataArr[i,2])
    fig = plt.figure()
    # 添加subplot
    ax = fig.add_subplot(111)
    # 绘制正样本
    ax.scatter(xcord1,ycord1,s = 20,c = 'red',marker = 's',alpha =.5)
    # 绘制负样本
    ax.scatter(xcord2,ycord2,s = 20,c = 'green',alpha=.5)
    x = np.arange(-3.0,3.0,0.1)
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x,y)
    # 绘制title
    plt.title('BestFit')
    # 绘制label
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()

if __name__ == '__main__':
    dataMat,labelMat = loadDataSet()
    weights = gradAscent(dataMat,labelMat)
    print(weights)
    plotBestFit(weights)

在这里插入图片描述Logistic回归的目的是寻找一个非线性函数Sigmoid的最佳拟合参数,求解过程可以由最优化算法完成。

标签:机器,Tx,样本,笔记,labelMat,Logistic,dataMat,theta,partial
来源: https://blog.csdn.net/qq_42722145/article/details/104819313