机器学习之logistic回归

机器学习之logistic回归

  • Logistic回归分析的基本原理
  • 数据准备
  • 代码实现
    • 导入必要库
    • 加载数据集
    • 定义sigmoid函数
    • 定义反向传播
    • 可视化展示
    • 定义logistic类
    • 训练并可视化结果
  • 总结

Logistic回归分析的基本原理

logistic是一种广义的线性回归分析模型,用于建立自变量与因变量之间的关系模型。不同于线性回归、线性模型,logistic回归在线性模型的基础上嵌套一层非线性函数,使得模型可以拟合曲线(面)函数,同时将输出结果范围控制在[0, 1]中使得输出结果直接对应输出类别的概率。本此实验采用sigmoid函数实现logistic回归。
s i g m o i d ( z ) = 1 1 + e − z sigmoid(z)=\frac{1}{1+e^{-z}} sigmoid(z)=1+ez1

数据准备

本次实验解决二维空间的二分类问题,先准备若干个二维点与对应类别。存放于testSet.txt中。
机器学习之logistic回归_第1张图片

代码实现

导入必要库

此次实验需要numpy数学库和可视化展示所需的matplotlib库。

from numpy import *
import matplotlib.pyplot as plt

加载数据集

从testSet.txt中读取所有二维点

def loadDataSet():
        dataMat = []
        labelMat = []
        fr = open('testSet.txt')
        for line in fr.readlines():
            # 矩阵的格式【标签,X1,X2】
            lineArr = line.strip().split()

            #插入X1,X2,以及初始化的回归系数(权重),全部设为1.0
            dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])

            #插入标签,
            #必须转换成int类型,因为只有两类
            labelMat.append(int(lineArr[2]))


        return dataMat,labelMat

定义sigmoid函数

# 使用sigmoid函数进行分类
    def sigmoid(inX):
        return 1.0/(1+exp(-inX))

定义反向传播

本次实验采用梯度上升算法进行反向传播更新权重。

#使用梯度上升算法进行优化,找到最佳优化系数
    #dataMatIn是训练集,三维矩阵,(-0.017612	14.053064	0)
    #classLabels是类别标签,数值型行向量,需要转置为列向量,取值是0,1
    def gradAscent(dataMatIn,classLabels):
        dataMatrix = mat(dataMatIn) #转换为Numpy矩阵数据类型
        labelMat = mat(classLabels).transpose() #转置矩阵,便于加权相乘
        m,n = shape(dataMatrix) #得到矩阵的行列数,便于设定权重向量的维度

        alpha = 0.001
        maxCycles = 500
        weights = ones((n,1))  #返回一个被1填满的 n * 1 矩阵,作为初始化权重
        for k in range(maxCycles):
            h = sigmoid(dataMatrix*weights)
            erro = (labelMat - h)   #labelMat是使用当前回归系数得到的的标签,labelMat是训练集的标签,取值是0,1
            weights = weights + alpha * dataMatrix.transpose( ) * erro  #根据使用当前权重计算的值与初始值的误差,更改weight,
                                                                        #按照误差的方向调整回归系数
        return weights

可视化展示

根据训练好的权重和已有数据点绘制图线。

def plotBestFit(wei):
        weights = wei.getA()
        dataMat,labelMat = loadDataSet()
        dataArr = array(dataMat)
        n = shape(dataMat)[0]
        xcord1 = []
        ycord1 = []
        xcord2 = []
        ycord2 = []

        #根据标签不同分为两种颜色画图,易于分辨
        for i in range(n):
            if int(labelMat[i]) == 1:
                xcord1.append(dataArr[i,1])
                ycord1.append(dataArr[i,2])
            else :
                xcord2.append(dataArr[i, 1])
                ycord2.append(dataArr[i, 2])

        fig = plt.figure()
        ax = fig.add_subplot(111) #将画布分为一行一列的画布,并从第一块开始画
        ax.scatter(xcord1,ycord1,s=30,c='red',marker = 's') #scatter散开
        ax.scatter(xcord2,ycord2,s=30,c='green')
        x = arange(-3.0,3.0,1)
        y = (-weights[0]-weights[1]*x)/weights[2]
        ax.plot(x,y)
        plt.xlabel('x1')
        plt.ylabel('x2')
        plt.show()

定义logistic类

将以上代码整合可得

class func:
    def loadDataSet(self):
        dataMat = []
        labelMat = []
        fr = open('testSet.txt')
        for line in fr.readlines():
            # 矩阵的格式【标签,X1,X2】
            lineArr = line.strip().split()

            #插入X1,X2,以及初始化的回归系数(权重),全部设为1.0
            dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])

            #插入标签,
            #必须转换成int类型,因为只有两类
            labelMat.append(int(lineArr[2]))


        return dataMat,labelMat

    # 使用sigmoid函数进行分类
    def sigmoid(self,inX):
        return 1.0/(1+exp(-inX))

    #使用梯度上升算法进行优化,找到最佳优化系数
    #dataMatIn是训练集,三维矩阵,(-0.017612	14.053064	0)
    #classLabels是类别标签,数值型行向量,需要转置为列向量,取值是0,1
    def gradAscent(self,dataMatIn,classLabels):
        dataMatrix = mat(dataMatIn) #转换为Numpy矩阵数据类型
        labelMat = mat(classLabels).transpose() #转置矩阵,便于加权相乘
        m,n = shape(dataMatrix) #得到矩阵的行列数,便于设定权重向量的维度

        alpha = 0.001
        maxCycles = 500
        weights = ones((n,1))  #返回一个被1填满的 n * 1 矩阵,作为初始化权重
        for k in range(maxCycles):
            h = self.sigmoid(dataMatrix*weights)
            erro = (labelMat - h)   #labelMat是使用当前回归系数得到的的标签,labelMat是训练集的标签,取值是0,1
            weights = weights + alpha * dataMatrix.transpose( ) * erro  #根据使用当前权重计算的值与初始值的误差,更改weight,
                                                                        #按照误差的方向调整回归系数
        return weights

    def plotBestFit(self,wei):
        weights = wei.getA()
        dataMat,labelMat = self.loadDataSet()
        dataArr = array(dataMat)
        n = shape(dataMat)[0]
        xcord1 = []
        ycord1 = []
        xcord2 = []
        ycord2 = []

        #根据标签不同分为两种颜色画图,易于分辨
        for i in range(n):
            if int(labelMat[i]) == 1:
                xcord1.append(dataArr[i,1])
                ycord1.append(dataArr[i,2])
            else :
                xcord2.append(dataArr[i, 1])
                ycord2.append(dataArr[i, 2])

        fig = plt.figure()
        ax = fig.add_subplot(111) #将画布分为一行一列的画布,并从第一块开始画
        ax.scatter(xcord1,ycord1,s=30,c='red',marker = 's') #scatter散开
        ax.scatter(xcord2,ycord2,s=30,c='green')
        x = arange(-3.0,3.0,1)
        y = (-weights[0]-weights[1]*x)/weights[2]
        ax.plot(x,y)
        plt.xlabel('x1')
        plt.ylabel('x2')
        plt.show()

训练并可视化结果

if __name__=="__main__":
    logRegres = func()
    dataArr,labelMat = logRegres.loadDataSet()
    weights = logRegres.gradAscent(dataArr,labelMat)
    logRegres.plotBestFit(weights)

机器学习之logistic回归_第2张图片
可以看出训练结果较好。

总结

使用logistic回归具有无需假定分布的好处。[0,1]范围的输出可以视为概率用于扩展,引入独热编码即可解决多分类问题。同时可直接应用现有数值优化算法(如牛顿法)求取最优解,具有快速、高效的特点。

你可能感兴趣的:(机器学习,回归,python)