机器学习实战(二)LR算法:实现简单的分类模型

说明:主要参考 机器学习实战之Logistic,里面有更详尽的Logistic Regression原理分析和案例实现流程详解,是一个关于机器学习实战的不错的学习资料,推荐一波。出于编程实践和机器学习算法梳理的目的,按照自己的代码风格重写该应用案例,在实现的过程中也很有助于自己的思考。为方便下次看时能快速理解便通过截图的方式截取了个人认为比较关键的内容,推荐看原链接,自己在代码实现过程中会留下一些思考,也欢迎交流学习。

不过关于LR的由来和推导,我建议看 logistic回归(一)logistic回归(二)和 Logistic回归原理

LR原理

这里只截取代码实现过程中关键的部分,即梯度上升公式,该截图为最后一个参考链接里面的,也是为了方便在代码中进行注释,能够更好地将代码实现和原理公式结合在一起看,加强理解。

LR算法实现及分析

数据请到第一个参考链接里面下载,这里就不贴出来了。

#  __author__ = 'czx'
# coding=utf-8
from numpy import *
import matplotlib.pyplot as plt
# 数据加载
def loadData(filename):
    f = open(filename)
    dataMat = []
    labels = []
    for line in f.readlines():
        tempSample = line.strip().split('\t')
        dataMat.append([1.0,float(tempSample[0]),float(tempSample[1])])
        labels.append(int(tempSample[2]))
    return dataMat,labels
# Sigmoid激活函数,这里也给了tanh激活函数
def sigmoid(X):
    return 1.0/(1+exp(-X))
    #return 2*1.0/(1+exp(-2*X))-1  # tanh(x):mean value is 0
# 打印数据验证数据加载是否正常
def dataCheck():
    data,labels = loadData('datingTest.txt')
    print len(data),len(labels)
    for i in range(len(data)):
        print data[i],labels[i]
# 用于显示后面梯度上升训练过程中的weights
def trainingProcessDisplay(weights):
    fig = plt.figure()
    n = len(weights)
    x = range(n)
    ax1 = fig.add_subplot(311)
    ax1.plot(x,weights[:,0])
    plt.ylabel('w0')
    ax = fig.add_subplot(312)
    ax.plot(x,weights[:,1])
    plt.ylabel('w1')
    ax = fig.add_subplot(313)
    ax.plot(x,weights[:,2])
    plt.ylabel('w2')
    plt.xlabel('Iterations')
    plt.show()
# 梯度上升,每次更新都是计算出所有样本之间的误差(数据量很大时计算很耗时)
def gradAscent(data,labels, alpha = 0.001, numIter=500):
    dataMatrix = mat(data)
    labelMat = mat(labels).transpose()
    m,n = shape(dataMatrix)
    weights = ones((n,1))
    for k in range(numIter):
        h = sigmoid(dataMatrix*weights)       # 激活输出
        error = labelMat - h                  # 误差计算,上图中的蓝色框公式
        weights = weights + alpha*dataMatrix.transpose()*error    # 权值更新,上图中的红色框公式
    return array(weights)
# 梯度上升,每次使用单个样本进行更新,error为标量
def stocGradAscent0(data,labels, alpha = 0.001, numIter=500):
    m,n = shape(data)
    weights = ones(n)
    for j in range(numIter):
        for i in range(m):
            h = sigmoid(sum(data[i]*weights))
            error = labels[i]-h
            weights = weights + alpha*error*data[i]
    return weights
# 随机梯度上升,每次迭代过程中顺序不一样,同样也是单样本更新
def stocGradAscent1(data,labels, numIter=500):
    m,n = shape(data)
    weights = ones(n)
    allWeights = ones((numIter,n))
    for j in range(numIter):
        allWeights[j] = weights
        dataIndex =  range(m)
        random.shuffle(dataIndex)
        for i in range(m):
            alpha = 4/(1.0+i+j) + 0.0001
            index = dataIndex[i]
            h = sigmoid(sum(data[index]*weights))
            error = labels[index] - h
            weights = weights + alpha *error*data[index]
    trainingProcessDisplay(allWeights)
    return weights
# 结果可视化:在这里回归出来的是直线
def resultVisualization(data,labels,weights):
    n = shape(data)[0]
    x1 = [];y1=[];x2=[];y2=[]
    for i in range(n):
        if int(labels[i])==1:
            x1.append(data[i][1]);y1.append(data[i][2])
        else:
            x2.append(data[i][1]);y2.append(data[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(x1,y1,s=30,c='red',marker='s')
    ax.scatter(x2,y2,s=30,c='green')
    x = arange(-5.0,5.0,0.1)
    # div = weights[2]
    # if weights[2]==0: div = 0.00001
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('X1');plt.ylabel('X2')
    plt.show()
# 测试:其实也就只是将回归直线绘制出来,真正测试的话应该要拿出一个测试集,然后计算测试误差,以及后续对新样本预测并作出相应的决策,这里只做简单分类就不介绍决策
def testLR():
    data,labels = loadData("data.txt")
    dataArr = array(data)
    #weights = gradAscent(dataArr,labels)
    #weights = stocGradAscent0(dataArr,labels)
    weights = stocGradAscent1(dataArr,labels)
    #print weights
    resultVisualization(dataArr,labels,weights)
# 主函数
if __name__ == "__main__":
    print 'hello LR !'
    # dataCheck()
    testLR()
中间迭代训练过程中[w1,w2,w3]的变化过程,200个迭代之后均趋于稳定。


最后的模型可视化。


小结

多写代码

多写代码

多写代码






猜你喜欢

转载自blog.csdn.net/stayfoolish_fan/article/details/80314941
今日推荐