机器学习实战(五):逻辑回归实战

从疝气病症状预测病马的死亡率

1、实战背景

使用Logistic回归来预测患疝气病的马的存活问题,数据包含了368个样本和28个特征;除了部分指标主观和难以测量外,该数据还存在一个问题,数据集中有30%的值是缺失的。如何处理数据集中的数据缺失问题,然后再利用Logistic回归和随机梯度上升算法来预测病马的生死。

2、准备数据

解决数据缺失问题的可选方法:
1.使用可用特征的均值来填补缺失值;
2.使用特殊值来填补缺失值,如-1;
3.忽略有缺失值的样本;
4.使用相似样本的均值添补缺失值;
5.使用另外的机器学习算法预测缺失值。

预处理数据做两件事:
1.如果测试集中一条数据的特征值已经确实,那么我们选择实数0来替换所有缺失值,因为本文使用Logistic回归。因此这样做不会影响回归系数的值。sigmoid(0)=0.5,即它对结果的预测不具有任何倾向性。
2.如果测试集中一条数据的类别标签已经缺失,那么我们将该类别数据丢弃,因为类别标签与特征不同,很难确定采用某个合适的值来替换。
原始的数据集经过处理,保存为两个文件:horseColicTest.txt和horseColicTraining.txt。

3、使用Python构建Logistic回归分类器

先用自己写的改进的随机梯度上升算法进行预测
在这里插入图片描述
错误率高的,耗时久,并且每次运行的错误率也是不同的,错误率高的时候可能达到40%多。因为数据集本身有30%的数据缺失,这个是不能避免的。另一个主要原因是,我们使用的是改进的随机梯度上升算法,因为数据集本身就很小,就几百的数据量。用改进的随机梯度上升算法显然不合适。
再试试梯度上升算法
在这里插入图片描述
算法耗时减少了,错误率稳定且较低。

当数据集较小时,我们使用梯度上升算法
当数据集较大时,我们使用改进的随机梯度上升算法

在Sklearn中,可以根据数据情况选择优化算法,比如数据较小的时候,使用liblinear,数据较大时,使用sag和saga。

4、使用Sklearn构建Logistic回归分类器
solver='liblinear’
在这里插入图片描述
solver=‘sag’ max_iter=5000
在这里插入图片描述
小数据集,sag算法需要迭代上千次才收敛,而liblinear只需要不到10次。根据数据集情况,选择最优化算法。
代码汇总

import numpy as np
import random
from sklearn.linear_model import LogisticRegression

"""
函数说明:sigmoid函数
Parameters:
            inX - 数据
Returns:
        sigmoid函数
"""
def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))


"""
函数说明:随机梯度上升算法
"""
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    # 返回dataMatrix的大小。m为行数,n为列数。
    m, n = np.shape(dataMatrix)
    # 参数初始化
    weights = np.ones(n)
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            # 降低alpha的大小,每次减小1/(j+i)。
            alpha = 4 / (1.0 + j + i) + 0.01
            # 随机选取样本
            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


"""
函数说明:梯度上升算法
Parameters:
            dataMatIn - 数据集
            classLabels - 数据标签
Returns:
        weights.getA() - 求得的权重数组(最优参数)
"""
def gradAscent(dataMatIn, classLabels):
    # 转换成numpy的mat
    dataMatrix = np.mat(dataMatIn)
    # 转换成numpy的mat,并进行转置
    labelMat = np.mat(classLabels).transpose()
    # 返回dataMatrix的大小。m为行数,n为列数。
    m, n = np.shape(dataMatrix)
    # 移动步长,也就是学习速率,控制更新的幅度。
    alpha = 0.001
    # 最大迭代次数
    maxCycles = 500
    weights = np.ones((n,1))
    for k in range(maxCycles):
        # 梯度上升矢量化公式
        # g(X)=h(theta) = theta * X
        h = sigmoid(dataMatrix * weights)
        error = labelMat - h
        # theta = theta + alpha * X^T(y - g(X))
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights.getA()


"""
函数说明:使用Python写的Logistic分类器做预测
"""
def colicTest():
    # 打开训练集
    frTrain = open('horseColicTraining.txt')
    # 打开测试集
    frTest = open('horseColicTest.txt')
    # 训练数据集
    trainingSet = []
    # 训练集标签
    trainingLabels = []
    # 遍历所有训练集
    for line in frTrain.readlines():
        # 去除空格,并以'\t'分割
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(len(currLine) - 1):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[-1]))

    # trainWeights = gradAscent(np.array(trainingSet), trainingLabels, 500)
    # 使用梯度上升训练
    trainWeights = gradAscent(np.array(trainingSet), trainingLabels)
    errorCount = 0
    numTestVec = 0.0
    for line in frTest:
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(len(currLine) - 1):
            lineArr.append(float(currLine[i]))
        # if int(classifyVector(np.array(lineArr), trainWeights)) != int(currLine[-1]): # 改进的梯度上升算法
        if int(classifyVector(np.array(lineArr), trainWeights[:, 0])) != int(currLine[-1]):
            errorCount += 1
    errorRate = (float(errorCount) / numTestVec) * 100
    print("测试集合错误率为: %.2f%%" % errorRate)


"""
函数说明:分类函数
Parameters:
            inX - 特征向量
            weights - 回归系数
returns:
        分类结果            
"""
def classifyVector(inX, weights):
    prob = sigmoid(sum(inX * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0


"""
函数说明:使用sklearn构件Logistic回归分类
"""
def colicSklearn():
    # 打开训练集
    frTrain = open('horseColicTraining.txt')
    # 打开测试集
    frTest = open('horseColicTest.txt')
    # 训练集和标签
    trainingSet = []
    trainingLabels = []
    # 测试集和标签
    testSet = []
    testLabels = []
    # 遍历训练集
    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(len(currLine) - 1):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[-1]))
    # 遍历测试集
    for line in frTest.readlines():
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(len(currLine) - 1):
            lineArr.append(float(currLine[i]))
        testSet.append(lineArr)
        testLabels.append(float(currLine[-1]))

    # sklearn中的分类器
    classifier = LogisticRegression(solver='sag', max_iter=5000).fit(trainingSet, trainingLabels)
    test_accurcy = classifier.score(testSet, testLabels) * 100
    print('正确率:%f%%' % test_accurcy)

    if __name__ == '__main__':
        colicSklearn()


if __name__ == '__main__':
    # 梯度上升算法测试
    # colicTest()

    # sklearn中的分类器
    colicSklearn()

总结
Logistic回归的优缺点
优点:实现简单,易于理解和实现;计算代价不高,速度很快,存储资源低。
缺点:容易欠拟合,分类精度可能不高。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值