PYTHON机器学习实战——逻辑回归

来源:互联网 发布:本地搜索引擎seo 编辑:程序博客网 时间:2024/06/08 19:16

逻辑回归 其实是分类问题。

从这节算是开始进入“正规”的机器学习了吧,之所以“正规”因为它开始要建立价值函数(cost function),

接着优化价值函数求出权重,然后测试验证。这整套的流程是机器学习必经环节。

今天要学习的话题是逻辑回归,逻辑回归也是一种有监督学习方法(supervised machine learning)。

逻辑回归一般用来做预测,也可以用来做分类,预测是某个类别!线性回归想比大家都不陌生了,y=kx+b,给定一堆数据点,

拟合出k和b的值就行了,下次给定X时,就可以计算出y,这就是回归。而逻辑回归跟这个有点区别,

它是一种非线性函数,拟合功能颇为强大,而且它是连续函数,可以对其求导,这点很重要,

如果一个函数不可求导,那它在机器学习用起来很麻烦,早期的海维赛德(Heaviside)

阶梯函数就因此被sigmoid函数取代,因为可导意味着我们可以很快找到其极值点,

这就是优化方法的重要思想之一:利用求导,得到梯度,然后用梯度下降法更新参数。

与 y=kx+b 类似,逻辑回归使用 Sigmoid等非线性激活函数(神经网络常用),其形式如下:

Sig = 1/(1 + exp(-z)) ,其中 Z是 数据样本X(X1,X2,X3,...,Xn)的线性函数:

Z = W0*X0+W1*Z1+...+Wn*Zn

Sigmoid函数的返回值在0到1之间,大部分值都贴近0或者1.只有z在0附近时,

形成一个上升曲线,z=0是,返回值是0.5.
因此当Sigmoid函数返回值大于0.5,这个阶跃函数返回1,否则返回0.

建立价值函数(cost function)

Fc = label - sigmoid(Z)

使用 梯度上升法 计算 各个权重的值,使得Fc最小。w = w + alpha * (c-f(x))*x


程序详解:

#-*- coding:utf-8 -*-#!/usr/bin/python'''逻辑回归'''# 测试 import logRegres as lr   lr.multiTest()from numpy import *def loadDataSet():    dataMat = []; labelMat = []# 训练样本集  和  对应标签(0/1)    fr = open('testSet.txt')    for line in fr.readlines():# 每一行        lineArr = line.strip().split() # 分解成向量列表         dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) # 前两个为 输入 x1 x2  , x0 为外加的常数项 不变量        labelMat.append(int(lineArr[2]))                            # 后一个为 标签    return dataMat,labelMatdef sigmoid(inX):    return 1.0/(1+exp(-inX)) #  sigmoid 函数输出 把输出变成  0 ~ 1# 梯度上升算法 优化 权重   w = w + a * det f(x,y)def gradAscent(dataMatIn, classLabels):     # 数据 和 标签    dataMatrix = mat(dataMatIn)             # 转换成 矩阵    labelMat = mat(classLabels).transpose() # 转换成 矩阵 转置 成 列矩阵    m,n = shape(dataMatrix) # 列数 为 n = 3(每个样本维度)   行数为m 为样本个数     alpha = 0.001   # 学习率(权重更新步长)    maxCycles = 500 # 最大循环次数    weights = ones((n,1))# 每个样本 的每个 数据都乘以一个权重    for k in range(maxCycles):              # 循环        h = sigmoid(dataMatrix*weights)     # 矩阵乘 在z=w0*x0+...+wn*xn  1/(1+exp(-z)) 函数 激活输出 到0~1之间        error = (labelMat - h)              # 误差 矩阵 减法        weights = weights + alpha * dataMatrix.transpose()* error #按差值 的方向 调整 权重        # w = w + alpha * (c-f(x))*x   迭代公式 需要数据情况调整     return weights# 画 出 回归线def plotBestFit(weights):    import matplotlib.pyplot as plt    dataMat,labelMat=loadDataSet()    dataArr = array(dataMat)    n = shape(dataArr)[0]     xcord1 = []; ycord1 = []# 1类数据    xcord2 = []; ycord2 = []# 0类数据    for i in range(n):        if int(labelMat[i])== 1:# 1类数据            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])        else:            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])# 0类数据    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 stocGradAscent0(dataMatrix, classLabels):    m,n = shape(dataMatrix)# m个数据   每个数据的维度为n    alpha = 0.01    weights = ones(n)   # 权重全部初始化为1    for i in range(m):  # 每个样本         h = sigmoid(sum(dataMatrix[i]*weights))        error = classLabels[i] - h        weights = weights + alpha * error * dataMatrix[i] # w = w + alpha * (c-f(x))*x   迭代公式 需要数据情况调整     return weights# 改进的 随机梯度上升法def stocGradAscent1(dataMatrix, classLabels, numIter=150):    m,n = shape(dataMatrix)# m个数据   每个数据的维度为n    weights = ones(n)   # 权重全部初始化为1    for j in range(numIter):# 最大循环次数        dataIndex = range(m)# 随机样本序列        for i in range(m):# 每个样本             alpha = 4/(1.0+j+i)+0.0001    # alphe 每次迭代都变化 动态步长,在计算中步长逐渐缩短            randIndex = int(random.uniform(0,len(dataIndex)))# 随机的一个样本 用于更新 权重            h = sigmoid(sum(dataMatrix[randIndex]*weights))            error = classLabels[randIndex] - h            weights = weights + alpha * error * dataMatrix[randIndex]# w = w + alpha * (c-f(x))*x   迭代公式 需要数据情况调整             del(dataIndex[randIndex])     # 删除所选的随机样本    return weights# 根据输出  得 到 分类标签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):# 每个数据 21维度            lineArr.append(float(currLine[i]))# 转换成 浮点型数据 添加数据的一个维度数据        trainingSet.append(lineArr)           # 添加样本到训练数据集        trainingLabels.append(float(currLine[21]))# 每个样本的最后一列为标签,添加标签    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 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):            lineArr.append(float(currLine[i]))        if int(classifyVector(array(lineArr), trainWeights))!= int(currLine[21]):#对测试数据进行预测 并和 实际标签比较            errorCount += 1# 错误次数+1    errorRate = (float(errorCount)/numTestVec)#计算错误率    print "本次测试错误率: %f" % errorRate    return errorRatedef multiTest():    numTests = 10; errorSum=0.0    for k in range(numTests):        errorSum += colicTest()    print " %d 次测试后,平均错误率为 : %f" % (numTests, errorSum/float(numTests))