logistics回归

(转)

1. logistic回归的基本思想  

  logistic回归是一种分类方法,用于两分类问题。其基本思想为:

  a. 寻找合适的假设函数,即分类函数,用以预测输入数据的判断结果;

  b. 构造代价函数,即损失函数,用以表示预测的输出结果与训练数据的实际类别之间的偏差;

  c. 最小化代价函数,从而获取最优的模型参数。

  2. 逻辑回归的过程

  逻辑函数(sigmoid函数):

  该函数的图像:

  假设函数(分类函数):

        

判定边界:

   线性边界和非线性边界如下:

       

          图1  线性边界                                               图2  非线性边界

线性边界的边界形式:

非线性边界的边界形式可表示为:

  hθ(x)函数的值表示结果取1的概率,因此对于输入x分类结果为类别1和类别0的概率分别为:

                         (概率公式)

  代价函数为: 

其中:

等价于:

代入得到代价函数:

  这样构建的 Cost(hθ(x),y)函数的特点是:当实际的 y=1 且 hθ 也为 1 时误差为 0,当 y=1 但 hθ 不为 1 时误差随着 hθ 的变小而变大;当实际的 y=0 且 hθ 也为 0 时代价为 0,当 y=0且hθ 不为 0 时误差随着 hθ 的变大而变大。


  实际上,Cost函数和J(θ)函数是基于最大似然估计推导得到的。

  前面的概率公式可简化为:

  

  对应的似然函数为:

  

  对数似然函数为:

  

  最大似然估计就是要求得使l(θ)取最大值时的θ,其实这里可以使用梯度上升法求解,求得的θ就是要求的最佳参数。

   前面提到的代价函数即可表示为: 


梯度下降法求J(θ)的最小值

  使用梯度下降法求J(θ)的最小值,θ的更新过程:

  

其中:α学习步长。

  求偏导:

  

更新过程可改写为:

α为一常量,所以1/m一般将省略,所以最终的θ更新过程为:


  求解过程中用到如下的公式:

  


梯度下降算法的向量化解法:

   训练数据的矩阵形式表示如下,其中x的每一行为一条训练样本。

  

  参数θ的矩阵形式为:

  

  计算x.θ(点乘)并记为A:

   

  求hθ(x)-y并记为E

  

  g(A)的参数A为一列向量,所以实现g函数时要支持列向量作为参数,并返回列向量。由上式可知hθ(x)-y可以由g(A)-y一次计算求得。

  θ更新过程,当j=0时:

  

  θj同理:

  

  综合起来:

  

  

  

  综上所述,vectorization后θ更新的步骤如下:

  (1)求A=x.θ

  (2)求E=g(A)-y

  (3)求θ:=θ-α.x'.E,x'表示矩阵x的转置。

  也可以综合起来写成:

   

   

  1 import numpy
  2 from numpy import  *
  3 import matplotlib.pyplot as plt
  4 import random
  5 def loadDataSet(filename):
  6     fr = open(filename)
  7     dataMat = []
  8     labelMat = []
  9     for line in fr.readlines():
 10         lineArr = line.strip().split()
 11         dataMat.append( [1.0,float(lineArr[0]),float(lineArr[1])] )
 12         labelMat.append(int(lineArr[2]))
 13     return dataMat,labelMat
 14 
 15 #阶跃函数
 16 def sigmoid(inX):
 17     return 1.0/(1 + numpy.exp(-inX))
 18 
 19 #基于梯度上升法的logistic回归分类器
 20 def gradAscent(dataMatIn,classLabels):
 21     dataMatrix = mat(dataMatIn)
 22     labelMatrix = mat(classLabels).transpose()
 23     m , n = shape(dataMatrix)
 24     alpha = 0.001#步长
 25     maxCycles = 500
 26     weights = ones((n,1))
 27     #对回归系数进行maxCycles次梯度上升
 28     for i in range(maxCycles):
 29         h = sigmoid(dataMatrix * weights)
 30         error = labelMatrix - h
 31         weights = weights + alpha * dataMatrix.transpose() * error
 32     return weights
 33 
 34 #分析数据:画出决策边界
 35 def plotBestFit(weights):
 36     dataMat,labelMat = loadDataSet('test.txt')
 37     dataArr = array(dataMat)
 38     n = list(shape(dataArr))[0]
 39     xcord1 = [] ; ycord1 = []
 40     xcord2 = [] ; ycord2 = []
 41     for i in range(n):
 42         if int(labelMat[i]) == 1:
 43             xcord1.append(dataArr[i,1])
 44             ycord1.append(dataArr[i,2])
 45         else:
 46             xcord2.append(dataArr[i,1])
 47             ycord2.append(dataArr[i,2])
 48     fig = plt.figure()
 49     ax = fig.add_subplot(111)
 50     ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
 51     ax.scatter(xcord2,ycord2,s=30,c='green')
 52 
 53     #最佳拟合直线
 54     x = arange(-3.0, 3.0, 0.1)
 55     print('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',shape(x))
 56 
 57     y = (-weights[0] - weights[1] * x) / weights[2]
 58     print('-----------------------------------------',shape(y))
 59     ax.plot(x,y)
 60     plt.xlabel('X1')
 61     plt.ylabel('X2')
 62     plt.show()
 63 
 64 #随机梯度上升
 65 def stocGradAscent0(dataMatrix,classLabels):
 66     m , n = numpy.shape(dataMatrix)
 67     alpha = 0.01#步长
 68     weights = numpy.ones((n))
 69     for i in range(m):
 70         h = sigmoid(sum(dataMatrix[i] * weights))
 71         error = classLabels[i] - h
 72         weights = weights + alpha * error * dataMatrix[i]
 73     return weights
 74 
 75 #改进的随机梯度上升
 76 def stocGradAscent1(dataMatrix,classLabels,numIter=150):
 77     m , n = shape(dataMatrix)
 78     weights = ones(n)
 79     dataIndex = list(range(m))
 80     print (dataIndex)
 81     for j in range(numIter):
 82         for i in range(m):
 83             alpha = 4/(1.0+j+i) + 0.1   #alpha每次迭代都要调整
 84             randIndex = int(random.uniform(0,len(dataIndex)))
 85             h = sigmoid (sum(dataMatrix[randIndex] * weights))
 86             error = classLabels[randIndex] - h
 87             weights = weights + alpha * error * dataMatrix[randIndex]
 88             del dataIndex[randIndex]
 89             print("randIndex",randIndex)
 90             print("dataIndex",dataIndex)
 91             if randIndex==0:
 92                 return weights
 93 
 94 
 95 if __name__ == '__main__':
 96     dataArr,labelMat = loadDataSet('test.txt')
 97     weights = stocGradAscent1(array(dataArr),labelMat)
 98     # weights = gradAscent(dataArr,labelMat)
 99     # print(shape(weights))
100     plotBestFit(weights)

 应用:从疝气病预测病马的死亡率

import numpy
from numpy import  *
import matplotlib.pyplot as plt
import random

#阶跃函数
def sigmoid(inX):
    return 1.0/(1 + numpy.exp(-inX))

#分类回归函数
def classifyVector(inX,weights):
    prob = sigmoid(sum(inX * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0

#改进的随机梯度上升算法
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m, n = shape (dataMatrix)
    weights = ones (n)
    dataIndex = list (range (m))
    for j in range (numIter):
        for i in range (m):
            alpha = 4 / (1.0 + j + i) + 0.1  # alpha每次迭代都要调整
            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]
            if randIndex == 0:
                return weights

#测试,返回错误率
def colicTest():
    frTrain = open('horseColicTraining.txt')
    frTest = open('horseColicTest.txt')
    trainingSet = []
    trainingLabels = []
    for line in frTrain.readlines():
        curLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(curLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(curLine[21]))
    trainWeights =  stocGradAscent1(array(trainingSet),trainingLabels,500)

    errorCount = 0
    numTestVec = 0
    for line in frTest.readlines():
        numTestVec += 1.0
        curLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(curLine[i]))
        if int(classifyVector(array(lineArr),trainWeights)) != int(curLine[21]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)
    print("错误率",errorRate)
    return errorRate


def multiTest():
    numTests = 10
    errorSum = 0.0
    for i in range(numTests):
        errorSum += colicTest()
    print("%d 次迭代之后,平均错误率为%f"%(numTests,errorSum/float(numTests)))

multiTest()

  

猜你喜欢

转载自www.cnblogs.com/nxf-rabbit75/p/8977621.html