吴恩达机器学习笔记(五) —— 应用机器学习的建议和机器学习系统设计

主要内容:

一.Evaluating a hypothesis

二.Model selection and training/validation/test sets

三.Bias and variance

四.Learning curves

五.Precision and recall

六.High Bias 和 high variance 的应对策略

一.Evaluating a hypothesis

如何评价模型的好坏?直接绘图以此判断曲线与数据集的拟合程度似乎是一个不错的办法,但是当特征的数量较大时却不能实现,因为我们最多只能看到三维的图像;而且,怎么判断是否为过拟合或者欠拟合,也不能单凭肉眼去观察,而需要一个科学的方法就判断。如下:

1.将数据集分成两部分,第一部分约占70%,称为训练集;第二部分约占30%,称为测试集。注意:两部分的选取需要是随机的,不能带有偏见。

2.训练集,顾名思义就是用于训练参数;同理,测试集就是用于测试已得参数(确切的说是模型)工作的好坏,而评估的工具依然是代价函数,与训练集的代价函数不同的是:此代价函数不需要加上正则项,为什么呢?其实想想正则项的作用就可以很好理解了,正则项的作用就是在训练参数时降低参数的规模,即正则项的作用体现在求参数的过程,既然参数都求出来了,就不需要再加上正则项画蛇添足了。

例子:

二.Model selection and training/validation/test sets

面对一个数据集,我们又多种备选模型,如特征的数量(或指数次数)不同,或者正则项λ的取值不同,形成了不同的模型。那么该如何从中选择一个最合适的模型呢?如下:

1.我们将数据集分成三部分。第一部分约占60%,称为数据集;第二部分约占20%,称为检验集;第三部分约占20%,称为测试集。

2.训练集用于训练参数;检验集用于评估已得模型的好坏,也是根据这个选择最终模型的;测试集用于测试已选模型工作的好坏。

3.首先利用训练集训练出各个模型的参数;然后再利用检验集评估每个模型工作的好坏程度,并从中挑选出表现最好的模型;最后利用测试集测试已选模型工作的好坏。

4.注意:检验集和测试集的评估和测试工具都是代价函数,并且不需要正则项,原因上文已解释。如线性回归:

三.Bias and variance、

1.bias对应于欠拟合,variance对应于过拟合。

2.当特征的次数从小逐渐变大时,bias和variance所对应的J(train)和J(cv)的情况如下:

对此的解释是:

1) 对于bias,其所对应的情况是欠拟合。所谓欠拟合,也就是曲线不能很好地拟合训练集,其是由特征过于简单导致的(伸缩性不强,不能“神龙摆尾”)。那么它训练集的代价值就当然大,既然连训练集都不能很好拟合,那更不用说测试集的代价值了。所以对于bias,J(train)和J(cv)较大,且两者较为接近。

2)对于variance,其所对应的情况是过拟合。所谓过拟合,就是曲线好地拟合训练集,所以其J(train)较小,但这样曲意逢迎地讨好数据集,就导致了模型不能很好地运用于训练之外的数据,所以对应的J(cv)就比较大。

 

3.当讨论完特征的次数对bias和variance的影响之后,再讨论正则项系数λ对其影响:

对于线性回归,我们熟知:当λ越小时,曲线的伸缩性越好,对数据的拟合程度越好,容易出现过拟合;反之容易出现欠拟合。如下:

那么, 正则项系数λ的影响如下:

四.Learning curves

学习曲线用于检测模型是否存在bias或者variance的问题。其原理是:逐渐增加训练集的规模,观察J(train)和J(cv)的变化情况。

1.如果呈以下的图形,则表明存在high bias的问题,因为在欠拟合是由模型过于简单所造成的,当增加训练数据时,由于模型的伸缩性有限,所以代价也不会发生太大变化,且处于较高水平。这就从侧面表明:对于欠拟合问题,单凭增加训练数据规模,其影响是十分有限的。

2.下图则存在high variance问题。这表明:对于过拟合问题,增加训练集的规模,可以较好地解决问题。因为过拟合是由于模型过于复杂,即模型的伸缩性很强,可以“神龙摆尾”。当数据集的规模较小时,由于限制较小,曲线的许多部位可以随便放,导致其对训练集之外的数据的准确度不高;但当数据集较大时,限制就变多了,曲线的很多部位就被固定了,所以其实用性就更强。

五.Precision 、recall 、 F1 score、ROC曲线和AUC值

1.对于预测结果,我们设置两个指标:precision(准确率)和recall(回召率)

其中:

TP: 预测为真且实际为真    FP: 预测为真但实际为假

FN: 预测为假但实际为真    TN: 预测为假且实际为假

precision:所有预测为1中,真实为1的比率

recall:所有真实为1中,预测为1的比率

1)对于precision:我们总是希望预测的准确率高一点,可以通过提高阈值(threshold)实现。但阈值越高,就越容易造成本来是真的被判为时假(当它的预测结果低于阈值时发生),即容易造成漏网之鱼。

2)对于recall:我们希望尽量减少漏网之鱼,于是可以通过降低阈值(threshold)实现。但阈值越低,就越容易造成本来是假的被判为真(当它的预测结果高于阈值时发生),即容易造成误伤。

3)总和上述两点,,我们需要在precision(提取准确率)和recall(提高判真基数)之间做出权衡,这里引入F1 Score:

取F1 Score最大的模型即可。

2.除了利用F1 score判断模型的好坏,我们还可以利用ROC曲线AUC值。首先映入两个概念:

1)真阳率 = TP/(TP+FN),即“实际为真且预测为真/(实际为真)”。可知真阳率只与实际为真的数据点有关。

2)假阳率 = FP/(FP+TN),即“实际为假但预测为真/(实际为假)”。可知假阳率只与实际为假的数据点有关。

而ROC曲线就是:逐步调整模型的阈值,以假阳率为X轴,以真阳率为Y轴的连续曲线,如下:

结论:

1)模型需要尽可能提高真阳率、降低假阳率。其中,当真阳率为1,假阳率为0的时候,模型是完美的。这时对应了点(0,1.0)。

2)图中对角线为随机预测的效果,而左上角区域为优于随机预测的效果,右下角为劣于随机预测的效果(此时将测试结果反过来就能得到优于随机测试的预测效果)。

3)ROC曲线越往左上角靠近,则模型的预测效果越好。为了衡量模型的好坏,我们就引入了AUC值:ROC曲线下的面积。显然AUC值越大,模型的预测效果越好。那么该如下计算AUC值呢?

(以下画ROC曲线及计算AUC值的方法摘选自:AUC计算方法总结

假设已经得出一系列样本被划分为正类的概率,然后按照大小排序,下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率。

 

接下来,初始化所有数据点都预测为真(即阈值无限低),对应点(1.0, 1.0)。我们从低到高,依次将“Score”值作为阈值threshold,当测试样本属于正样本的概率大于这个threshold时,我们认为它为正样本,否则为负样本。举例来说,对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3都被认为是正样本,因为它们的“Score”值都大于0.6,而其他样本则都认为是负样本。每次选取一个不同的threshold,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。这样一来,我们一共得到了20组FPR和TPR的值,将它们画在ROC曲线的结果如下图:

Python代码如下:

'''画出ROC曲线并计算AUC值'''
def plotROC(predStrengths, classLabels):    #predStrengths为通过模型计算出数据预测为真的概率,classLabels为数据实际的标签
    import matplotlib.pyplot as plt
    cur = (1.0,1.0) #cursor        #一开始将所有数据点预测为真(即阈值无限低),对应的点为(1.0, 1.0)
    ySum = 0.0 #variable to calculate AUC    #累加所有AUC小矩形的高度,由于计算AUC值
    numPosClas = sum(array(classLabels)==1.0)    #标签为正的个数
    yStep = 1/float(numPosClas);     # 在y方向,即真阳率方向ROC曲线只会往下走numPosClas步,因而每一步为1/float(numPosClas)
    xStep = 1/float(len(classLabels)-numPosClas) # 在x方向,即假阳率方向ROC曲线只会往左走float(len(classLabels)-numPosClas)步
    sortedIndicies = predStrengths.argsort()#get sorted index, it's reverse        # 对预测为真的概率升序排序
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    '''枚举每一个数据(预测概率从低到高),将其作为阈值。大于阈值的预测为真,小于等于阈值的预测为假,因此被枚举的被预测为假。'''
    for index in sortedIndicies.tolist()[0]:
        if classLabels[index] == 1.0:    #本身为真,预测为假。则真阳率变小,假阳率不变。
            delX = 0; delY = yStep;
        else:
            delX = xStep; delY = 0;    #本身为假,预测为假。则假阳率变小,假真阳率不变。
            ySum += cur[1]
        ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b')      #draw line from cur to (cur[0]-delX,cur[1]-delY)
        cur = (cur[0]-delX,cur[1]-delY)        #更新当前点
    ax.plot([0,1],[0,1],'b--')
    plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
    plt.title('ROC curve for AdaBoost horse colic detection system')
    ax.axis([0,1,0,1])        # 画出随机预测的虚线
    plt.show()
    print "the Area Under the Curve is: ",ySum*xStep    #AUC的值为ySum*xStep

 

六.High Bias 和 high variance 的应对策略

原文地址:https://www.cnblogs.com/DOLFAMINGO/p/9338544.html