第5章Logistic回归

Logistic回归的优缺点:

优点:计算代价不高,易于理解和实现

缺点:容易欠拟合,分类精度可能不高

适用数据类型:数值型和标称型数据

Sigmoid函数:f(z) = \frac{1}{1 +e^{-z }}

sigmoid函数性质:当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的Sigmoid值将逼近于1;随着x的减小,sigmoid值将逼近于0。

上述的z,由下面的公式得出:

z = w_{0}x_{0}+w_{1}x_{1}+w_{2}x_{2}+....+w_{n}x_{n}

其中的向量x是分类器的输入数据,向量w也就是我们要找到的最佳系数

# encoding: utf-8
import numpy as np
from  numpy import *
import matplotlib
import matplotlib.pyplot as plt
#5-1 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])])
        #除了将lineArr第一列和第二列加进来,还加入一列的1.0
        labelMat.append(int(lineArr[2]))
    return  dataMat,labelMat
def sigmoid(inX):
    return 1.0/(1+exp(-inX))
def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()#转置
    m,n = shape(dataMatrix)#读取这个数组的长宽
    alpha = 0.001#每次移动的步长
    maxCycles = 500
    weights = ones((n,1))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)
        error = (labelMat - h)#预测值和真实值的偏差
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights
#5-2画出数据集和Logistic回归最佳拟合直线的函数
def plotBestFit(weights):
    dataMat,labelMat = loadDataSet()
    dataArr = array(dataMat)#转为Numpy中的数组
    n = shape(dataArr)[0]
    #shape函数是返回一个数组,只有shape[0]或者shape[1]才表示长度或者宽度

    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)
    #arange([start,stop,step)根据start与stop指定的范围以及step设定的步长,生成一个 ndarray。
    y = ((-weights[0]-weights[1]*x)/weights[2]).transpose()
    #找分割线就是令w0x0+w1x1+w2x2=0,其中x0=1,x1和x2就是x,y坐标,这就是y的由来
    ax.plot(x,y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()
#5-3随机梯度上升法
def stocGradAscent0(dataMatrix, classLabels):
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))
        #和梯度上升算法不同的是,这里h是向量而不是数值
        error = classLabels[i] - h
        #error也是向量
        weights = weights + alpha * error * dataMatrix[i]
    return weights
#5-4改进的随机梯度上升算法
#为何改进?在每次迭代时会引发系数的剧烈改变,5-3的随机梯度上升算法并没有避免来回波动
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m,n = shape(dataMatrix)
    weights = ones(n)
    for j in range(numIter):
        dataIndex = range(m)
        for i in range(m):
            alpha = 4/(1.0+j+i)+0.01
            #这样使得alpha在每次迭代时都改变,缓解5-3代码出现的数据波动或者高频波动
            randIndex = int(random.uniform(0,len(dataIndex)))
            #这里第二个改动就是通过随机选取样本来更新h
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error *dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weights
#总结一下,此方法的准确率已经与梯度下降法类似,但计算率却大大降低了。

python中numpy模块下函数array()和mat()的区别:

功能基本类似,有一些小差别

https://blog.csdn.net/Build_Tiger/article/details/79848808

#应用:预测兵马的死亡率
#5-5Logistic回归分类函数
def classifyVector(inX, weights):#第一个参数是特征向量,第二个参数是回归系数
    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):
            lineArr.append(float(currLine[i]))#将每行数据加入到lineArr列表中
        trainingSet.append(lineArr)#再讲所有数据加入到trainingSet列表中
        trainingLabels.append(float(currLine[21]))
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 200)
    #使用随机梯度上升算法来计算回归系数向量
    errorCount = 0;numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0 #numTestVec代表的是总样本数
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr),trainWeights)) != int(currLine[21]):
            #已经通过上面找到了最佳的系数,这是在测试集里测试
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)
    print "the error rate of this test is :%f" % errorRate
    return  errorRate
#colicTest()具有完全独立的功能,多次运行得到的结果可能稍有不同,因为是采用的是随机梯度上升算法
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))
multiTest()
发布了30 篇原创文章 · 获赞 29 · 访问量 2227

猜你喜欢

转载自blog.csdn.net/weixin_41938314/article/details/89186308
今日推荐