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

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

从这节算是开始进入“正规”的机器学习了吧,之所以“正规”因为它开始要建立价值函数(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,labelMat

def 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 errorRate

def multiTest():
    numTests = 10; errorSum=0.0
    for k in range(numTests):
        errorSum += colicTest()
    print " %d 次测试后,平均错误率为 : %f" % (numTests, errorSum/float(numTests))
        


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EwenWanW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值