Logistic应用于二分类

回归方程

z=w0x0+w1x1+w2x2+w3x3+...wnxn
=wTx
表示两个向量对应元素的相乘
x 是分类器的输入特征
w 是我们需要求的最佳参数

算法过程

每个回归系数初始化为1
重复R次:
。。。计算整个数据的梯度
。。。使alpha*grandient更新回归系数向量
。。。返回回归系数

Sigmoid

在由于是二分类问题,需要对上面求得 z 进行判断,判断其所在的类别,我们用到的是 Sigmoid ,公式如下:
σ(z)=11+ez
Logistic应用于二分类_第1张图片
该函数具有很好的性质:
z 很大时候,函数值趋向于1
z 很小时候,函数值趋向于0
根据这个特性可用于二分类分体
z=w0x0+w1x1+w2x2+w3x3+...wnxn
=wTx
对上面的回归方程:
σ(z)=σ(wTx)=11+ewTx
对给定的 x ,上式的值越趋向于1,认为是1类的可能性越大,越趋近0,则认为是0类的可能性越大, Sigmoid 函数给了分类的一个很好的界限。

梯度上升法

参见梯度下降法
梯度上升法和梯度下降法只是在迭代公式中的正负号的差别。
上面的梯度下降法中很详细的讲了梯度下降法,随机梯度下降法和增量梯度下降法,但是写的有点乱。
我们发现对 σ(z) 求导后的结果是 σ(z)(1σ(z)
根据梯度上升法至于要求出 w 既可以对给定的样本,判断其所在的类别
hw(x)=σ(z)=σ(wTx)

P(y=1|x;w)=hw(x)

P(y=0|x;w)=1hw(x)

P(y|x;w)=(hw(x))y(1hw(x))1y

若假设有m个训练样本,根据极大似然估计
L(W)=P(Y|X;W)=i=mi=1P(y(i)|x(i);w)

=i=mi=1(hw(x(i)))y(i)(1hw(x(i)))1y(i)
取对数

logL(W)=i=mi=1y(i)loghw(x(i))+i=mi=1(1y(i))log(1hw(x(i)))

为了求出 W=(w0,w1,w2,...,wm)

logL(W) 中的某个 wj 求导得到; mi=1(y(i)hw(x(i)))x(i)j

wj

wj=wj+α(mi=1(y(i)hw(x(i))))x(i)j
这个是增量梯度上升法
注意:
1.这里的迭代只是求出了 wj ,只是一个而已,求出所有的要分别迭代 n+1
2. x(i) 是第 i 个样本数据,是个向量,有 n 个元素, n+1 W 中元素的个数
3. (y(i)hw(x(i))) ,第 i 个样本的误差
4. mi=1(y(i)hw(x(i)))x(i)j ,可以理解为:所有每个样本的误差与样本特征乘积的和。
5. α 是学习率
6.这个与上次讲的梯度下降法的求导后的结果有点不一样,这里是对的,这个我求导好多次的,要求所有的误差与特征乘积的和。为了与梯度下降法的迭代公式一样,每次可知求一个样本的误差。

wj=wj+α((y(i)hw(x(i))))x(i)j
这个是普通的梯度上升法
为了提高速度可以,随机的抽取样本 x(i) ,这个就是随机梯度上升法

Python程序

程序中有两个数据集,第一个只是用来简单的测试,第二个数据集是疝气病预测马死亡的预测
程序中注释很详细,不对程序再过多说明

# -*- coding: utf-8 -*-
from numpy import *
import operator
from os import listdir

def loadDataSet():
    dataMat=[]
    labelMat=[]
    # 打开txt文件
    fr = open('testSet.txt')
    # readData中保存了所有的数据行
    readData = fr.readlines()
    # 利用正则,每行数据以 \t 划分开的
    # 返回的结果是list
    for line in readData:
        lineArr = line.strip().split("\t")
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

def sigmoid(intX):
    # sigmoid 函数
    return 1.0/(1+exp(-intX))

def gradAscent(dataMatIn,classLabels):
    # 梯度上升法
    DataMatrix = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    m,n = shape(DataMatrix)
    # alpha 学习率
    alpha = 0.001 
    maxCycles = 500
    weight = ones((n,1))
    # 下面计算都是按照矩阵方式
    # 1.计算sigmoid函数,也就是根据当前的weight,判断类别
    # 2.计算误差
    # 3.更新权值 对w_i,只是计算了自己的误差,误差大,更新权值w_i相对越大
    # 4.迭代到达最大次数结束 
    for k in range(maxCycles):
        h= sigmoid(DataMatrix*weight)
        error = (labelMat - h)
        weight = weight  + alpha * DataMatrix.transpose()*error
    return weight

def plotBestFit(weights):
    import matplotlib.pyplot as plt
    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)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('X1');plt.ylabel('X2')
    plt.show()

def runTest():
    dataArr,labelMat = loadDataSet()
    weights = gradAscent(dataArr,labelMat)
    plotBestFit(weights.getA())

def stocGradAscent0(dataMatrix,classLabels):
    # 随机梯度上升法
    m,n=shape(dataMatrix)
    alpha = 0.01
    weights = ones(n)
    # 选取前m个样本更新权值
    # 每次对所有的weights 更新的权值一样 
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))
        error = classLabels[i] - h
        weights = weights + alpha*error * dataMatrix[i]
    return weights

def runTest1():
    dataArr,labelMat = loadDataSet()
    weights = stocGradAscent0(array(dataArr),labelMat)
    plotBestFit(weights)

def stocGradAscent1(dataMatrix,classLabels,numIter=150):
    # 改进的随机梯度上升法
    m,n=shape(dataMatrix)
    weights = ones(n)
    # 随机的选取样本,计算误差,更新权值
    # 这里的alpha 也根据迭代次数更新大小,
    for j in range(numIter):
        dataIndex = range(m)
        for i in range(m):
            alpha = 4/(1.0+i+j)+0.01
            randIndex = int(random.uniform(0,len(dataIndex)))
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h 
            weights = weights + alpha* error* dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weights

def runTest2():
    dataArr,labelMat = loadDataSet()
    weights = stocGradAscent1(array(dataArr),labelMat)
    plotBestFit(weights)

def classifyVector(intX,weights):
    prob = sigmoid(sum(intX*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]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[i]))
    trainWeights = stocGradAscent1(array(trainingSet),trainingLabels,500)
    errorCount = 0 
    numTestVec = 0.0 
    for line in frTest.readlines():
        numTestVec += 1.0 
        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

def mulitTest():
    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))

你可能感兴趣的:(Logistic回归,二分类,梯度上升发)