Logistic回归(2)

本文主要讲机器学习实践第五章从疝气病症预测病马的死亡率带给我们的启示。

有了上一篇Logistics的核心代码和知识背景后,学习这个案例本身会很简单,这个案例除开加强了logistics算法的理解和实用价值之外,最大的意义在于教会我们在现实数据不理想有部分缺失的情况下我们要如何处理训练集。


机器学习原书中给的训练样本在git上(https://github.com/yejingtao/forblog/blob/master/MachineLearning/trainingSet/horseColicTraining.txt)(https://github.com/yejingtao/forblog/blob/master/MachineLearning/trainingSet/horseColicTest.txt),里面有368个样本,每个样本有28个特性,我们不一定是兽医方面的专家,所以我们不必知道这28个特性具体代表的意义,我们只需要量化这28个特性并利用Logistic回归找到他们与结果集之间的规律既可。


数据集中有30%的数据是缺失的,这也是我们现实使用时往往遇到的问题,当我们的数据缺失时要如何处理?数据往往是通过很高的代价得来的,如何合理的继续利用这些数据成为我们面临的一个难题。

 

一般分两种情况,如果是结果数据丢失,这条数据就可以放弃了,因为无论代价多么昂贵,没有结果的数据我们不知道对齐如何分析。

如果是特性数据丢失,一般有以下方法进行处理和使用:

1 利用该特性的均值来替换

2 利用特殊值来替换

3 利用相似样本的该特性来替换

4 利用其他的机器学习算法来预测该特性

这四种方式都比较好理解,没有好坏之分,根据使用的算法和实际情况做选取,我们来看下在Logistic回归中我们这里使用哪个处理方式。


直接给出结果,结果是将空缺的特性设置为0.原因有2个:

1 不影响梯度上升时的修订

         weights= weights + alpha*error*dataMatrix[randIndex]

         如果缺失的特性设置成0,该特性上该数据的修订将为0,所以缺失的数据正好不会印象到梯度上升时的修订。

2 sigmoid(0)=0.5,正好不属于01,空缺的特性就不会对结果集造成误差

 

补齐代码,函数classifyVector做结构预测,大于0.5我们预测为1,小于0.5预测为0

 

def classifyVector(testX, weights) :
    prob = sigmoid(sum(testX*weights))
    if prob>0.5 : return 1
    else : return 0

主函数colicTest,用训练集训练出线性参数,然后用测试集进行验证:

 

def colicTest () :
    #打开训练集文件,解析并生成训练的特性集和结果集
    trainingFile = open('C:\\2017\\提高\\机器学习\\训练样本\\horseColicTraining.txt')
    trainingSet = []
    trainingClassLabel = []
    for line in trainingFile.readlines() :
        fileLineArray = line.strip().split('\t')
        dataLineArray = []
        for i in range(21) :
            dataLineArray.append(float(fileLineArray[i]))
        trainingSet.append(dataLineArray)
        trainingClassLabel.append(float(fileLineArray[21]))
    #训练并生成回归系数
    weights = stocGradAscent1(array(trainingSet),trainingClassLabel,200)
    errorCount = 0
    numTestVec = 0.0
    #打开测试样本
    testFile = open('C:\\2017\\提高\\机器学习\\训练样本\\horseColicTest.txt')
    for line in testFile.readlines() :
        numTestVec +=1
        testFileLineArray = line.strip().split('\t')
        testDataLineArray = []
        for i in range(21) :
            testDataLineArray.append(float(testFileLineArray[i]))
        if int(classifyVector(testDataLineArray,weights))!=int(testFileLineArray[21]) :
            errorCount +=1
    errorRate = float(errorCount/numTestVec)
    print('errorRate is %f' %errorRate)
    return errorRate


在训练时由于是随机选取训练集进行训练的,所以难免存在偏差,所以多训练和验证几次求平均值才能代表该算法的最终效果:

def multiTest() :
    numTest = 10
    errorCount = 0.0
    for k in range(numTest) :
        errorCount +=colicTest()
    print('after %d cycle test, average error rate is %f' %(numTest,float(errorCount/numTest)))

结果是:

errorRate is 0.432836
errorRate is 0.343284
errorRate is 0.447761
errorRate is 0.432836
errorRate is 0.313433
errorRate is 0.388060
errorRate is 0.328358
errorRate is 0.313433
errorRate is 0.328358
errorRate is 0.373134
after 10 cycle test, average error rate is 0.370149

平均的成功率在63%左右,虽然没有我们想象中的理想,但也不算太差,将梯度的步长设置短一些结果最终可以提高到20%左右。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值