逻辑回归----Python实现

逻辑回归是个二分类问题,具体原理网上有很多,这里只列出Python实现过程。
原理参考:逻辑回归

参考《机器学习实战》,对于逻辑回归参数寻优时,采用梯度下降法和随机梯度下降两种方法实现。

Python定义梯度下降函数:

# 梯度下降法
def gardDescent(dataMatIn,classLabels):
    dataMatrix = mat(dataMatIn) 
    labelMatrix = mat(classLabels).T
    m,n = shape(dataMatrix)     # 得到数据规模
    # 迭代步长
    alpha = 0.01
    # 迭代次数
    maxCycles = 5000
    weights = ones((n,1))       # help(numpy.ones)
                                # 设定初始参数,全为1
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)  # sigmoid函数已定义
        E = (h - labelMatrix)
        weights = weights - alpha * dataMatrix.T * E
    return weights

Python定义随机梯度下降函数:

梯度上升算法在每次更新回归系数时都需要遍历整个数据集,一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为随机梯度上升算法。由于可以在新样本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个在线学习算法。与“在线学习 ”相对应 ,一次处理所有数据被称作是“批处理” 。

随机梯度上升算法可以写成如下的伪代码

所有回归系数初始化为 1
对数据集中每个样本:
    计算该样本的梯度
    使用 alpha x gradient ^ ,得到新回归系数值
返回回归系数值
# 随机梯度上升算法
# 每次对参数的更新都只用一个样本值,属于在线算法
def stocGradAscent0(dataMatrix,classLabels):
    dataMatrix = array(dataMatrix)
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i] * weights))
        E = classLabels[i] - h
        weights = weights + alpha * E * dataMatrix[i]
    return weights

可以 看到 ,随机梯度下降算法与梯度下降算法在代码上很相似,但也有一些区别:

  • 第一 ,后者的变量 & 和误差 都是向量,而前者则全是数值;
  • 第二 ,前者没有矩阵的转换过程,所有变量的数据类型都是 numpy 数组。

Python实现逻辑回归

from numpy import *
import matplotlib.pyplot as plt

print('\n###############logistic regression#####################')

# 载入数据
def loadDataSet():

    dataMat = [];   labelMat = []
    fr = open('testSet.txt')
    # 逐行读入数据,然后strip去头去尾,用split分组
    for line in fr.readlines():
        lineArr = line.strip().split('   ')
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

# 定义sigmoid函数
def sigmoid(inX):
    return 1.0/(1+exp(-inX))

########## 梯度下降法,见上面 #################

########## 随机梯度下降法,见上面 ##############



# 画图函数,传入参数为两种不同算法得到的参数矩阵
def plotBestFit(weights_1,weights_2):
    weights_1 = weights_1.getA()      # numpy.matrix.getA():
                                      # Return `self` as an `ndarray` object.
    # weights_2 = weights_2.getA()
    dataMat,labelMatrix = loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[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(figsize=(14,6))


    ####################### 图1 ####################
    ax = fig.add_subplot(121)
    # 画散点图,不同的样本点用不同颜色表示
    ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
    ax.scatter(xcord2,ycord2,s=30,c='blue',)

    x = arange(-3.0,3.0,0.1)
    y_1 = (-weights_1[0]-weights_1[1]*x)/(weights_1[2])
    ax.plot(x,y_1,'k--',color = 'yellow',linewidth=2)
    plt.xlabel('Logistics Regression GradDescent')

    # 去掉坐标系右边和上边的边界,美观
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    ####################### 图2 ####################
    ax = fig.add_subplot(122)
    ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
    ax.scatter(xcord2,ycord2,s=30,c='blue',)
    x = arange(-3.0,3.0,0.1)
    y_2 = (-weights_2[0]-weights_2[1]*x)/(weights_2[2])
    ax.plot(x,y_2,'k--',color = 'yellow',linewidth=2)
    plt.xlabel('Logistics Regression StocGradDescent')
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')

    plt.show()



# 定义准确度计算函数
def calAccuracyRate(dataMat,labelMat,weights):
    count = 0
    dataMat = mat(dataMat)
    labelMat = mat(labelMat).T
    m,n = shape(dataMat)

    for i in range(m):
        h = sigmoid(dataMat[i,:] * weights)
        if ( h>0.5 and int(labelMat[i,0]) == 1) or ( h<0.5 and int(labelMat[i,0]) == 0 ):
            count += 1 
    return count/m

dataMat,labelMat = loadDataSet() 
weights_GD = gardDescent(dataMat,labelMat)              # 使用梯度下降计算参数矩阵 θ
weights_SGD = stocGradAscent0(dataMat,labelMat)         # 使用随机梯度下降计算参数矩阵 θ

print('weights_GD:\n',weights_GD)
print('weights_SGD:\n',weights_SGD)
plotBestFit(weights_GD,weights_SGD)

# 计算两种算法结果的准确度
acc_gd = calAccuracyRate(dataMat,labelMat,weights_GD)
weights_SGD = mat(weights_SGD).transpose() 
acc_sgd = calAccuracyRate(dataMat,labelMat,weights_SGD)

print('\n\nacc_gd:',acc_gd)
print('acc_sgd:',acc_sgd)

运行结果

运行结果:

逻辑回归----Python实现_第1张图片

准确度:

逻辑回归----Python实现_第2张图片

其中使用梯度下降法等到的准确度为:95%,使用随机梯度下降法准确度:72%。虽然后者准确度差好多,但是后者是在所有样本点上迭代1次的结果,而使用梯度下降法这是迭代了5000次的结果。我们来改进一下随机梯度下降法,将迭代次数增加到500次。

改进随机梯度下降法

# 改进的随机梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
    dataMatrix = array(dataMatrix)
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)
    # 在所有样本点上迭代500次
    for j in range(500):
        for i in range(m):
            h = sigmoid(sum(dataMatrix[i] * weights))
            E = classLabels[i] - h
            weights = weights + alpha * E * dataMatrix[i]

    return weights

运行结果:
逻辑回归----Python实现_第3张图片
逻辑回归----Python实现_第4张图片

对比结论

在最优化算法中,最常用的就是梯度下降算法, 而梯度上升算法又可以简化为随机梯度下降算法。

随机梯度下降算法与梯度下降算法的效果相当, 但占用更少的计算资源。此外 ,随机梯度下降是一个在线算法, 它可以在新数据到来时就完成参数更新, 而不需要重新读取整个数据集来进行批处理运算。

数据集

-0.017612   14.053064   0
-1.395634   4.662541    1
-0.752157   6.538620    0
-1.322371   7.152853    0
0.423363    11.054677   0
0.406704    7.067335    1
0.667394    12.741452   0
-2.460150   6.866805    1
0.569411    9.548755    0
-0.026632   10.427743   0
0.850433    6.920334    1
1.347183    13.175500   0
1.176813    3.167020    1
-1.781871   9.097953    0
-0.566606   5.749003    1
0.931635    1.589505    1
-0.024205   6.151823    1
-0.036453   2.690988    1
-0.196949   0.444165    1
1.014459    5.754399    1
1.985298    3.230619    1
-1.693453   -0.557540   1
-0.576525   11.778922   0
-0.346811   -1.678730   1
-2.124484   2.672471    1
1.217916    9.597015    0
-0.733928   9.098687    0
-3.642001   -1.618087   1
0.315985    3.523953    1
1.416614    9.619232    0
-0.386323   3.989286    1
0.556921    8.294984    1
1.224863    11.587360   0
-1.347803   -2.406051   1
1.196604    4.951851    1
0.275221    9.543647    0
0.470575    9.332488    0
-1.889567   9.542662    0
-1.527893   12.150579   0
-1.185247   11.309318   0
-0.445678   3.297303    1
1.042222    6.105155    1
-0.618787   10.320986   0
1.152083    0.548467    1
0.828534    2.676045    1
-1.237728   10.549033   0
-0.683565   -2.166125   1
0.229456    5.921938    1
-0.959885   11.555336   0
0.492911    10.993324   0
0.184992    8.721488    0
-0.355715   10.325976   0
-0.397822   8.058397    0
0.824839    13.730343   0
1.507278    5.027866    1
0.099671    6.835839    1
-0.344008   10.717485   0
1.785928    7.718645    1
-0.918801   11.560217   0
-0.364009   4.747300    1
-0.841722   4.119083    1
0.490426    1.960539    1
-0.007194   9.075792    0
0.356107    12.447863   0
0.342578    12.281162   0
-0.810823   -1.466018   1
2.530777    6.476801    1
1.296683    11.607559   0
0.475487    12.040035   0
-0.783277   11.009725   0
0.074798    11.023650   0
-1.337472   0.468339    1
-0.102781   13.763651   0
-0.147324   2.874846    1
0.518389    9.887035    0
1.015399    7.571882    0
-1.658086   -0.027255   1
1.319944    2.171228    1
2.056216    5.019981    1
-0.851633   4.375691    1
-1.510047   6.061992    0
-1.076637   -3.181888   1
1.821096    10.283990   0
3.010150    8.401766    1
-1.099458   1.688274    1
-0.834872   -1.733869   1
-0.846637   3.849075    1
1.400102    12.628781   0
1.752842    5.468166    1
0.078557    0.059736    1
0.089392    -0.715300   1
1.825662    12.693808   0
0.197445    9.744638    0
0.126117    0.922311    1
-0.679797   1.220530    1
0.677983    2.556666    1
0.761349    10.693862   0
-2.168791   0.143632    1
1.388610    9.341997    0
0.317029 14.739025 0

你可能感兴趣的:(机器学习,Python,数据分析)