机器学习——Logistic回归

 

1.基于Logistic回归和Sigmoid函数的分类

 

2.基于最优化方法的最佳回归系数确定

 

2.1 梯度上升法

参考:机器学习——梯度下降算法

 

2.2 训练算法:使用梯度上升找到最佳参数

 

Logistic回归梯度上升优化算法

def loadDataSet():
    dataMat = []; labelMat = []
    fr = open('testSet.txt')
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])	#加上第0维特征值
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat	#返回数据矩阵和标签向量

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

def gradAscent(dataMatIn, classLabels):		#Logistic回归梯度上升优化算法
    dataMatrix = mat(dataMatIn)             	#由列表转换成NumPy矩阵数据类型,dataMatrix是一个100×3的矩阵
    labelMat = mat(classLabels).transpose() 	#由列表转换成NumPy矩阵数据类型,labelMat是一个100×1的矩阵
    m,n = shape(dataMatrix)		    	#shape函数取得矩阵的行数和列数,m=100,n=3
    alpha = 0.001				#向目标移动的步长
    maxCycles = 500				#迭代次数
    weights = ones((n,1))			#3行1列的矩阵,这个矩阵为最佳的回归系数,和原来的100×3相乘,可以得到100×1的结果
    for k in range(maxCycles):              
        h = sigmoid(dataMatrix*weights)     	#矩阵相乘,得到100×1的矩阵,即把dataMat的每一行的所有元素相加
        error = (labelMat - h)              	#求出和目标向量之间的误差
	#梯度下降算法
        weights = weights + alpha * dataMatrix.transpose()* error #3×100的矩阵乘以100×1的矩阵,weights是梯度算子,总是指向函数值增长最快的方向
    return weights				#返回一组回归系数,确定了不同类别数据之间的分割线

 

    dataMat,labelMat = loadDataSet()
    print gradAscent(dataMat,labelMat)	#输出回归系数

 

[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

 

2.3 分析数据:画出决策边界

 画出数据集和Logistic回归最佳拟合直线的函数

def plotBestFit(wei):			#画出数据集和Logistic回归最佳拟合直线的函数
    import matplotlib.pyplot as plt
    weights = wei.getA()
    dataMat,labelMat=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()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    #最佳拟合曲线,这里设w0x0+w1x1+w2x2=0,因为0是两个分类(0和1)的分界处(Sigmoid函数),且此时x0=1
    #图中y表示x2,x表示x1
    y = (-weights[0]-weights[1]*x)/weights[2]	
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()

 

    dataMat,labelMat = loadDataSet()
    #print dataMat
    #print labelMat
    #print gradAscent(dataMat,labelMat)	#输出回归系数
    plotBestFit(gradAscent(dataMat,labelMat))

 

 

2.4 训练算法:随梯度上升

def stocGradAscent0(dataMatrix, classLabels):	#随机梯度上升算法
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)   			#3行1列的矩阵,初始最佳回归系数都为1,
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))	#计算出是数值,而不是向量,dataMatrix[100×3]中取得[1×3],乘以[3×1],得到数值
        error = classLabels[i] - h
        weights = weights + alpha * error * dataMatrix[i]
    return weights

def plotBestFit(weights):			#画出数据集和Logistic回归最佳拟合直线的函数
    import matplotlib.pyplot as plt
    #weights = wei.getA()
    dataMat,labelMat=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()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    #最佳拟合曲线,这里设w0x0+w1x1+w2x2=0,因为0是两个分类(0和1)的分界处(Sigmoid函数),且此时x0=1
    #图中y表示x2,x表示x1
    y = (-weights[0]-weights[1]*x)/weights[2]	
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()

 

    dataMat,labelMat = loadDataSet()
    #print dataMat
    #print labelMat
    #print gradAscent(dataMat,labelMat)	#输出回归系数
    #plotBestFit(gradAscent(dataMat,labelMat))
    plotBestFit(stocGradAscent0(array(dataMat),labelMat))

 

 

改进的随机梯度上升算法

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m,n = shape(dataMatrix)
    weights = ones(n)   		#初始化回归系数
    for j in range(numIter):		#从0到149开始循环
        dataIndex = range(m)
        for i in range(m):		#从0到99开始循环
            alpha = 4/(1.0+j+i)+0.0001    			#步进alpha的值逐渐减小,j=0-150,i=1-100,使得收敛的速度加快
            randIndex = int(random.uniform(0,len(dataIndex)))	#样本随机选择0-99中的一个数计算回归系数,减小周期性波动的现象
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error * dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weights

 

 

示例:从疝气病症预测病马的死亡率

 

 1.准备数据:处理数据中的缺失值

 

2.测试算法:使用Logistic回归进行分类

def classifyVector(inX, weights):	#输入回归系数和特征向量,计算出Sigmoid值,如果大于0.5则返回1,否则返回0
    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0

def colicTest():
    frTrain = open('horseColicTraining.txt'); frTest = open('horseColicTest.txt')
    trainingSet = []; trainingLabels = []
    for line in frTrain.readlines():		#导入训练数据
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):			#把0-20个病症加到列表中
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)			#把得到的每个列表加到训练集合中
        trainingLabels.append(float(currLine[21]))	#把标签加到训练标签中
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 1000)	#使用改进的随机梯度上升算法,递归1000次,计算回归系数
    errorCount = 0; numTestVec = 0.0
    for line in frTest.readlines():		#导入测试数据
        numTestVec += 1.0			#测试数据的总数
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):			#把0-20个病症加到列表中,作为分类器的输入
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr), trainWeights))!= int(currLine[21]):	#计算分类错误的次数,currLine[21]表示真正死亡与否
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)						#计算错误率
    print "the error rate of this test is: %f" % errorRate
    return errorRate

def multiTest():	#调用colicTest()十次并求结果的平均值
    numTests = 10; errorSum=0.0
    for k in range(numTests):
        errorSum += colicTest()
    print "after %d iterations the average error rate is: %f" % (numTests, errorSum/float(numTests))

 

posted @ 2016-11-15 10:36  tonglin0325  阅读(1357)  评论(0编辑  收藏  举报