0

我的帖子

个人中心

设置

  发新话题
逻辑回归是个二分类问题,具体原理网上有很多,这里只列出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 * weights))        E = classLabels - h        weights = weights + alpha * E * dataMatrix    return weights
可以 看到 ,随机梯度下降算法与梯度下降算法在代码上很相似,但也有一些区别:
  • 第一 ,后者的变量 & 和误差 都是向量,而前者则全是数值;
  • 第二 ,前者没有矩阵的转换过程,所有变量的数据类型都是 numpy 数组。
Python实现逻辑回归from numpy import *import matplotlib.pyplot as pltprint('\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) == 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/mdataMat,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)
运行结果运行结果:

准确度:

其中使用梯度下降法等到的准确度为: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 * weights))            E = classLabels - h            weights = weights + alpha * E * dataMatrix    return weights
运行结果:



对比结论在最优化算法中,最常用的就是梯度下降算法, 而梯度上升算法又可以简化为随机梯度下降算法。
随机梯度下降算法与梯度下降算法的效果相当, 但占用更少的计算资源。此外 ,随机梯度下降是一个在线算法, 它可以在新数据到来时就完成参数更新, 而不需要重新读取整个数据集来进行批处理运算。
数据集-0.017612   14.053064   0-1.395634   4.662541    1-0.752157   6.538620    0-1.322371   7.152853    00.423363    11.054677   00.406704    7.067335    10.667394    12.741452   0-2.460150   6.866805    10.569411    9.548755    0-0.026632   10.427743   00.850433    6.920334    11.347183    13.175500   01.176813    3.167020    1-1.781871   9.097953    0-0.566606   5.749003    10.931635    1.589505    1-0.024205   6.151823    1-0.036453   2.690988    1-0.196949   0.444165    11.014459    5.754399    11.985298    3.230619    1-1.693453   -0.557540   1-0.576525   11.778922   0-0.346811   -1.678730   1-2.124484   2.672471    11.217916    9.597015    0-0.733928   9.098687    0-3.642001   -1.618087   10.315985    3.523953    11.416614    9.619232    0-0.386323   3.989286    10.556921    8.294984    11.224863    11.587360   0-1.347803   -2.406051   11.196604    4.951851    10.275221    9.543647    00.470575    9.332488    0-1.889567   9.542662    0-1.527893   12.150579   0-1.185247   11.309318   0-0.445678   3.297303    11.042222    6.105155    1-0.618787   10.320986   01.152083    0.548467    10.828534    2.676045    1-1.237728   10.549033   0-0.683565   -2.166125   10.229456    5.921938    1-0.959885   11.555336   00.492911    10.993324   00.184992    8.721488    0-0.355715   10.325976   0-0.397822   8.058397    00.824839    13.730343   01.507278    5.027866    10.099671    6.835839    1-0.344008   10.717485   01.785928    7.718645    1-0.918801   11.560217   0-0.364009   4.747300    1-0.841722   4.119083    10.490426    1.960539    1-0.007194   9.075792    00.356107    12.447863   00.342578    12.281162   0-0.810823   -1.466018   12.530777    6.476801    11.296683    11.607559   00.475487    12.040035   0-0.783277   11.009725   00.074798    11.023650   0-1.337472   0.468339    1-0.102781   13.763651   0-0.147324   2.874846    10.518389    9.887035    01.015399    7.571882    0-1.658086   -0.027255   11.319944    2.171228    12.056216    5.019981    1-0.851633   4.375691    1-1.510047   6.061992    0-1.076637   -3.181888   11.821096    10.283990   03.010150    8.401766    1-1.099458   1.688274    1-0.834872   -1.733869   1-0.846637   3.849075    11.400102    12.628781   01.752842    5.468166    10.078557    0.059736    10.089392    -0.715300   11.825662    12.693808   00.197445    9.744638    00.126117    0.922311    1-0.679797   1.220530    10.677983    2.556666    10.761349    10.693862   0-2.168791   0.143632    11.388610    9.341997    00.317029 14.739025 0





本帖最后由 redhat9i 于 2018-5-10 15:27 编辑
可读性太差……



宝剑厉不厉害,要看它的主人是谁,不信来PHP版块看看~!
没法看



‹‹ 上一贴:使用Pyinstaller库遇到问题,请大神解答,问题如图 ...   |   下一贴:求助:python解析json文件 ››
  发新话题
快速回复主题
关于我们 | 诚聘英才 | 联系我们 | 网站大事 | 友情链接 |意见反馈 | 网站地图
Copyright©2005-2018 51CTO.COM
本论坛言论纯属发布者个人意见,不代表51CTO网站立场!如有疑义,请与管理员联系:bbs@51cto.com