运用机器学习建议
决定下一步做什么?
当你的模型运用于新的样本时,如果产生巨大的误差该怎么办?
一般来说,有以下几种处理方式:
- 获得更多的训练样本——通常是有效的,但代价较大,下面的方法也可能有效,可考虑先采用下面的几种方法。
- 尝试减少特征的数量
- 尝试获得更多的特征
- 尝试增加多项式特征
- 尝试减少正则化程度$\lambda$
- 尝试增加正则化程度$\lambda$
当然我们不可能随机去一个个方法尝试,所以需要一点手段来预测。
评估假设函数
首先,如果你计算出的误差(代价函数值)非常大,那么选取的假设函数就可能存在问题;即便误差小,也有可能引起过拟合。
那么如何来判断过拟合问题?
可以将数据集按比例划分成,训练集(Training set):测试集(Test set)=70:30。
然后将训练集得到的模型运用于测试集,用来计算误差:
1.对于线性回归模型,我们直接计算
2.对于逻辑回归模型,除了计算代价函数
更常见的方法是计算误分类的比例(0/1错误分类度量)
模型选择和交叉验证集
当模型确定的时候可以使用上一节的方法来验证,但是如何确定一个模型呢?首先需要知道,正则化惩罚项系数$\lambda$的选择;增加多项式特征时,多项式的次数等这类问题,称为模型选择问题。
假设我们的输入特征只有一个时,拟合效果是非常不理想的。因此,我们通常会增加特征项,那么问题又来了,多项式特征的次数应该怎么选取,即到底选取什么样的模型(假设)?
我们可以罗列出多种情况
这时再将数据集划分成训练集和测试集,对这些假设分别在训练集上训练,通过最小化训练集的代价,求出最优参数$\Theta_{1}$~$\Theta_{10}$。将其代入测试集,计算每个模型的误差,选择误差最小的那组作为假设,并把这组的误差值作为泛化误差。
然而其中存在一个问题:通过测试集来选取模型,又用测试集来求泛化误差,显然是不是坠吼滴。
因此,我们重新划分数据集的比例,训练集:交叉验证集(Cross Validation set):测试集=60:20:20
然后计算选择出模型:
1.用训练集训练出$\Theta_{1}$~$\Theta_{10}$;
2.用交叉验证集计算出最小误差,选择误差最小的模型;
3.用第2步中选择的模型计算测试集得出泛化误差。
Train/validation/test error
Training error:
Cross Validation error:
Test error:
上面说到的,是关于如何改变特征来减小误差,而接下来的内容则和正则化$\lambda$有关
诊断偏差和方差
当运行结果不理想时,多半有两种情况:过拟合或者欠拟合。而这两种情况,哪种和高偏差有关?哪种和高方差有关?还是都有关系?
从图中可以看出,欠拟合时高偏差,过拟合时高方差。那么在没法画图的情况下(基本都是这种情况)如何来确定是高偏差还是高方差呢?
方法如下:
将训练集误差和验证集误差绘制在图中,其中横坐标为多项式次数。
Training error:
Cross Validation error:
可以明显看出
- 对于训练集,d越大,误差越小
- 对于验证集,随着d增长,误差会先减小后增大,其中的最低点就是开始过拟合的情况。
那么当我们在没有图像的情况下,得出验证集误差较大时,只需要根据训练集误差的大小就能得出是高偏差还是高方差了。
具体来说,就是:
- 训练集误差和交叉验证集误差近似时:偏差/欠拟合
- 交叉验证集误差远大于训练集误差时:方差/过拟合
正则化和偏差、方差
正则化常常用来解决过拟合问题,但是对于正则化项参数$\lambda$,如下图所示不同的选取可能会导致不同的偏差问题,那么应该如何选择合适的值呢?
我们先选择一系列想要测试的$\lambda$,通常是0~12之间呈现2倍的关系,例如:$0,0.01,0.02,0.04,0.08,0.15,0.32,0.64,1.28,2.56,5.12,10$(共12个)。
再像之前那样,把数据集划分为训练集、验证集和测试集。但是因为之前我们都是不带正则化,所以$J(\theta)$和$J_{train}(\theta)$是一样的,但是这里就要如下图中的那样分开。
先在训练集上用最小化代价函数,求得最优的一组参数。然后再用该参数在训练/验证/测试集上根据公式计算相应误差。
(这里存疑?关于$J(\theta)$和$J_{train}(\theta)$什么时候使用)
具体步骤如下:
1.先对每个$\lambda$值,求对应最小化代价函数的参数
2.将上述求得的参数,代入交叉验证集计算代价函数$J_{cv}(\theta)$,选择对应最小代价函数的$\theta$作为最优模型参数。
3.代入测试集$J_{test}(\theta)$计算泛化误差。
还可以把验证集误差和训练集误差绘制成图,横坐标为$\lambda$。
可以看出:
- 当$\lambda$较小时,$J_{train}(\theta)$值较小,$J_{cv}(\theta)$值较大,过拟合
- 当$\lambda$较大时,$J_{train}(\theta)$值较大,$J_{cv}(\theta)$值较大,欠拟合
学习曲线
学习曲线是一个非常好的工具,用于判断模型偏差、方差问题。它是一个以样本个数为横坐标,以误差为纵坐标绘制的图像。
1.如何利用学习曲线识别高偏差?
从图中可以看出,对于欠拟合而言,增加样本个数没有意义,因为模型拟合能力差,没有能力去关注”细节“。
从这张图中也可以看出,当样本到达一定数量时,训练集合测试集的误差会非常接近且不再变化,但高于我们期望的误差。
如何利用学习曲线识别高方差?
可以看出在过拟合情况下,增加数据,可能可以提高算法效果。
增加样本个数会小幅度提高训练集误差,但是始终维持在一个相对较低的水平。而验证集个数增加为增进模型对数据的了解,因此会验证集误差会减小
上面的test error和cross validation error用哪个效果都一样。
决定下一步做什么?
如何通过这些诊断法来帮助我们选择改进模型的方法呢?回到最初的问题上
- 获得更多的训练样本——解决高方差
- 尝试减少特征的数量——解决高方差
- 尝试获得更多的特征——解决高偏差
- 尝试增加多项式特征——解决高偏差
- 尝试减少正则化程度λ——解决高偏差
- 尝试增加正则化程度λ——解决高方差
神经网络
使用神经元较少的神经网络(左图)跟参数较少时情况类似,容易导致高偏差和欠拟合;同理,神经元较多(右图)这容易导致高方差,可以使用正则化手段来解决。
一般使用神经元较多的情况比较好处理。当然你也可以同样把数据集划分为训练集、交叉验证集和测试集。然后从一层隐藏层开始逐一尝试。找到验证集误差最小的作为模型。
机器学习系统设计
确定执行的优先级
以建立一个垃圾邮件分类器为例
step1.用向量表示邮件
输入变量x为邮件的特征;y表示邮件的标签,1代表垃圾邮件,0代表不是。
我们可以人工选择100个单词作为词典,然后比对邮件中单词是否出现,出现则记为1,未出现记为0(注意不是记录出现个数),因此能够得到下图中的100维向量,这个向量作为输入。
实际上,我们不会人工选择单词构成字典,而是在训练集中自动选择出现频率最高的n(10000-50000)个单词构成字典,然后用一个n维的特征向量来表示邮件。
step2.想办法降低分类的错误率
1.收集更多的训练数据,但这种要视情况而定。
2.为每个邮件设计更复杂的特征,比如把邮件正文标题也考虑进去
3.为邮件的正文设计更复杂的特征,比如单词的单复数,discount和discounts是否应该看成一个单词;首字母大小、后缀,deal和Dealer是否应该看作一个单词;是否应该考虑标点符号,可能垃圾邮件中叹号会比较多。
4.构建更复杂的算法来检测邮件中的错误拼写,比如垃圾邮件发送者经常把一些容易被检测到的单词写错,如m0rtgage,med1cine,w4tches等,从而避免被检测到。
当然上述方法如何选择,同样也是个问题。
误差分析
当你准备好构建一个机器学习系统时,最好的方式是先用简单的方法快速实现。具体来说:
1.从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试。
2.绘制学习曲线,判断是高偏差或是高方差,决定是增加更多的数据还是添加更多的特征。
3.误差分析:人工观察交叉验证集,看看被分错的样本是否具有某些规律。
- 举个误差分析的例子:
假设验证集有500个样本,$m_{cv}=500$,分类器分错了100个样本,此时可以人工检查这100个错误:首先分析这100个样本的错分类型和数量。如下所示:
卖药的邮件12封,卖假货的邮件4封,钓鱼的邮件53封,其他的31封;那么我们就可以把关注点放在钓鱼邮件上。
然会继续对钓鱼邮件分析,是否可以发现一些新的特征。能够提高分类器的的性能,比如这些钓鱼邮件存在以下几个问题:
我们又可以把关注点放在“不常用的标点”这一项上,毕竟有32封邮件都存在该问题,进而设计一些包含标点的更复杂的特征,以此提高性能。
- 数值评估:
在做垃圾邮件分类时,可能会遇到这种问题:
应不应该把discount,discounts,discounted,discounting看作是同一个单词,即是否看成一个特征。
在自然语言处理中会使用词干提取,在这种情况下,上述单词会被看作是同一个。但是词干提取有利有弊,这种方法通常指关注前几个字母,比如它可能会把universe/university看作一个单词,这显然不合理。
那么我们到底要不要使用词干提取?这时我们可以使用数值评估的方法:
首先使用词干提取,训练一个分类器,在验证集上计算它的错误率;然后不使用词干提取,训练一个分类器,在验证集上计算它的错误率。二者进行比较,哪个错误率低,就使用哪种方法。
类似的这种问题,还包括是否应该区分单词大小写,如mom和Mom是否应该看作一个单词,都可以使用上述数值评估的方法,选择一个合理的做法。
不对称分类的误差评估
我们通常用错误率/正确率来评估一个算法,但有时这种方法是不合适的,比如偏斜类问题。
以这个判断肿瘤恶性/良性的分类器为例,如果分类器错误率为1%,而实际只有0.5%的病人肿瘤为恶性。这种情况下,尽管错误率看起来非常低,也可能造成严重后果。此时哪怕直接把所有病人都认为良性,也只有0.5%的错误率,高于分类器。
这就是偏斜类问题,情况表现为训练集中同一种类样本非常多,而其他类样本样本比较少。
那么如何解决偏斜类问题?换句话说,如何知道算法把所有病人都认为良性而没有做出真正的分类?
可以使用查准率(Precision)和召回率(Recall)。
召回率又可以叫做查全率,事实上叫查全率显然更符合其含义
我的理解,查准率指预测正确的样本个数占样本总数的多少;查全率指预测正确的样本个数占实际正确的样本个数。
还是以上面肿瘤的例子
准确率等于True positive除以一行;
召回率等于True positive除以一列;
由此可以看出,当使用y=0
(把所有病人判断为良性)的方法预测时,召回率为0,由此可以排除。
查准率和召回率的均衡
在肿瘤例子中,我们一般情况下设置分类的阈值为0.5。
- 我们可能需要在非常准确的情况下,才去预测肿瘤为恶性,否则让良性肿瘤的病人去接受治疗,那肯定要被骂,因此这时候我们需要高查准率,因此可以调高阈值为0.7或0.9,可以更准确的预测出恶性肿瘤。但此时明显,召回率就被降低了
- 但召回率的降低可能导致更多恶性肿瘤的情况被归类为良性肿瘤,这种情况也是我们不愿见到的,因此我们也可能想调高召回率。
由此可以画出查准率和召回率的图像:
综上,我们需要向办法设置合适的阈值,以达到查准率和召回率的平衡。
通常使用$F_{1}score$来权衡,计算公式为${ {F}_{1} }Score:2\frac{PR}{P+R}$,$F_{1}score$值越高,模型的性能越好。
机器学习数据
之前曾经说过,不要盲目的收集大量训练数据。
但是有些时候,收集大量数据会得到一个性能良好的学习算法。
即当你的算法有很多参数,数据特征充足(当一个人类专家拿到输入x时,能做出良好的判断,证明特征充足)时,更多的训练数据会带来更好的性能。
参考资料