吴恩达机器学习系列内容的学习目录 → \rightarrow →吴恩达机器学习系列内容汇总。
1. 优先处理的工作:垃圾邮件分类例子
在实际的工作过程中,我们应该明白哪些事情要优先处理,接下来我们以一个垃圾邮件分类器算法为例子进行讨论。为了解决这样一个问题,我们首先要做的决定是如何选择并表达特征向量
x
x
x。我们可以选择一个由100个最常出现在垃圾邮件中的词所构成的列表,根据这些词是否在邮件中出现来获得我们的特征向量(出现为1,不出现为0),尺寸为100×1。
在实际应用中,我们会在训练集中挑选出出现频率最多的n个单词(n一般在10,000-50,000之间),然后将它们作为我们的特征向量,这显然不同于现在手动挑选的100个单词的训练样本。
如何在有限的时间内让我们的垃圾分类器具有高精准度和低错误率?
1. 收集更多的数据,让我们有更多的垃圾邮件和非垃圾邮件样本(例如,Honey Pot项目通过创建虚假的邮箱地址,并故意将这些地址暴露给垃圾邮件的发送者以此来收集大量的垃圾邮件,然后得到大量的垃圾邮件数据来训练分类算法);
2. 通过邮件的标题来构建一个基于邮件的路由信息的更为复杂的特征,来捕捉到邮件信息的来源并以此来判断邮件是否垃圾邮件;
3. 对邮件的主体部分构建更为复杂的特征(例如,单词“discount”和“discounts”是否应该被视为同一单词,或者是否应该把“deal”和“dealer”视为同一个单词,在这个例子中可以关注单词首字母的大小写或者通过标点符号来构建复杂的特征);
4. 为了检测故意出现的拼写错误构建更复杂的算法,例如,“m0rtgage”、“med1cine”、“w4tches”。
在上面这些选项中,我们通常很难决定应该在哪一项上花费时间和精力,但作出明智的选择比随着感觉走要更好。
2. 误差分析
如果我们准备研究机器学习的东西,或者构造机器学习应用程序,构建一个学习算法的推荐方法为:
1. 通过一个简单的算法来快速实现它,而不是设计一个很复杂的系统,即使这个速成的东西不是很完美,然后使用交叉验证集来测试数据;
2. 通过画出相应的学习曲线以及检验误差来找出我们的算法是否有高偏差和高方差的问题或者别的问题,在做出这些分析之后,再来决定是否使用更多的数据训练或者加入更多的特征变量等等。这么做的原因是在我们刚接触机器学习问题时这是一个很好的方法,因为我们并不能提前知道是否需要复杂的特征变量或者是否需要更多的数据,因此通过一次简单快速的实现,我们可以通过学习曲线来做出下一步的选择;
3. 误差分析:实现比如一个垃圾邮件分类器的时候,人工观察交叉验证集的情况,看一看哪些邮件被算法错误的分类。通过查看这些被错误分类的垃圾邮件和非垃圾邮件,找出经常被错误分类的邮件的共同特征和规律。
误差分析并不总能帮助我们判断应该采取怎样的行动,有时我们需要去尝试不同的模型并进行比较。在模型比较时,用数值来判断哪一个模型更好更有效,通常我们是看交叉验证集的误差。
数值估计:当我们改进学习算法的时候,如果我们的算法能够返回一个数值评价指标来估计算法执行的效果将会很有帮助。可能算法是准确的,也有可能是错误的,但这个数字(能够看出误差变大还是变小、效果变好还是变坏)能够告诉我们学习算法的效果怎么样。
在我们的垃圾邮件分类器例子中,对于“我们是否应该将discount/discounts/discounted/discounting处理成同一个词?”的问题,如果这样做可以改善算法的性能,我们会使用词干提取软件。但这些词干提取软件只会简单地检查单词的前几个字母,可能会将“universe/university”看做是同一个单词。误差分析可能也无法帮助我们去决定进行词干提取到底是不是一个好主意,所以如果要判断词干提取软件是否对我们的分类器有益,最好的方法就是用最快的方式来尝试使用一下它,然后看它是否能起到效果。如果要这样做的话,通过数值方法来评估算法的效果将会非常有用,我们可以通过观察交叉验证集在使用和不使用词干提取软件时各自的错误率来估算算法的效果。
推荐在交叉验证集上进行误差分析,而不是在测试集上。
总结一下,在我们开始研究一个新的机器学习问题时,需要尽可能快的实现一个算法。一旦有了一个初始的算法实现,我们就能使用一个强有力的工具来帮助我们决定下一步的做法。第一步,先看看算法造成的错误,通过误差分析来看看它出现了什么错误,然后依次来决定之后的优化方法。第二步,假设我们已经有了一个快速而不完美的算法实现,又有了一个数值评价指标,这些会帮助我们尝试新的想法并快速地发现我们尝试的这些想法是否能够提高算法的表现,从而使我们更快地决定我们的算法应该放弃什么或者应该包含什么。
3. 偏斜类的误差度量
设定某个实数来评价我们的学习算法并衡量它的表现,有了算法的评估和误差度量值后,要注意的是使用一个合适的误差度量值有时会对于我们的学习算法造成非常微妙的影响,这就是偏斜类的问题。
在癌症分类例子中,我们训练Logistic回归模型(
y
=
1
y=1
y=1为癌症,
y
=
0
y=0
y=0为其他),假设使用测试集来检验这个分类模型,发现它只有1%的错误,因此我们99%会做出正确的诊断,这看起来是一个不错的结果。但假设我们发现在测试集中只有0.5%的患者真正患了癌症,那么1%的错误率就不显得那么好了。
function y=predictCancer(x)
y=0;
return
上述代码忽略了
x
x
x,让
y
y
y总是等于0,因此它总是预测没有人得癌症,这个算法只有0.5%的错误率,甚至比我们之前的得到的1%的错误率更好。这是一个非机器学习的算法,只是预测
y
y
y总是等于0,这种情况发生在训练集中有非常多的同一种类的样本且只有很少或没有其他类的样本,把这种情况称为偏斜类。
偏斜类:一个类中的样本数与另一个类的样本数相比多很多,通过总是预测
y
=
0
y=0
y=0或
y
=
1
y=1
y=1,算法可能表现得非常好,因此使用分类误差或者分类精确度来作为评估度量会产生问题。
如果我们有一个偏斜类,用分类精度并不能很好的衡量算法。因为我们可能会获得一个很高的精确度、非常低的错误率,但是我们并不知道我们是否真的提升了分类模型的质量。就像总是预测
y
=
0
y=0
y=0并不是一个好的分类模型,但是会将我们的误差降低至更低水平。所以当我们遇到偏斜类问题时,希望有一个不同的误差度量值或不同的评估度量值,例如查准率(Precision)和查全率(Recalll)。
根据算法的预测结果和实际结果出现的不同情况, 我们分成以下四种:
1. 真阳性(True Positive,TP):预测为真,实际为真;
2. 真阴性(True Negative,TN):预测为假,实际为假 ;
3. 假阳性(False Positive,FP):预测为真,实际为假 ;
4. 假阴性(False Negative,FN):预测为假,实际为真。
查准率:一个分类模型的查准率等于真阳性除以所有我们预测为阳性的数量。公式为:查准率(Precision)=
T
P
T
P
+
F
P
\frac{TP}{TP+FP}
TP+FPTP。
查全率:查全率也叫召回率,一个分类模型的查全率等于真阳性除以所有实际为阳性的数量。公式为:查全率(Recall)=
T
P
T
P
+
F
N
\frac{TP}{TP+FN}
TP+FNTP。
对于癌症分类例子来说,查准率就是指对于所有我们预测的患有癌症的病人中,有多大比率的病人是真正患有癌症的,高查准率说明我们预测病人患了癌症的准确率很高。查全率是指在所有患了癌症的病人中,有多大比率我们正确预测他们得了癌症,即有多少人我们能够正确告诉他们你需要治疗,查全率越高越好。
通过计算查准率和查全率,我们能更好的知道分类模型到底好不好。如果有一个算法总是预测
y
=
0
y=0
y=0,即总是预测没有人患癌症,那么这个分类模型的查全率为0,所以它不是一个好的分类模型。高查准率和高查全率可以表示一个模型是好模型。
4. 查准率和查全率之间的权衡
对于癌症预测的例子,构建Logistic回归模型 0 ⩽ h θ ( x ) ⩽ 1 0\leqslant h_{\theta}(x) \leqslant1 0⩽hθ(x)⩽1,如果 h θ ( x ) ⩾ 0.5 h_{\theta}(x)\geqslant 0.5 hθ(x)⩾0.5预测 y = 1 y=1 y=1,如果 h θ ( x ) < 0.5 h_{\theta}(x)< 0.5 hθ(x)<0.5预测 y = 0 y=0 y=0。假设想要实现下面两种情况,该怎么做?
- 假设我们想要在非常确信的情况下才去告诉患者得了癌症:实现这种情况的一种方法是修改算法,我们不再将临界值设为0.5,也许我们只在 h θ ( x ) ⩾ 0.7 h_{\theta}(x)\geqslant 0.7 hθ(x)⩾0.7的情况下才预测 y = 1 y=1 y=1,因此我们会在一个病人有大于等于70%概率得癌症的情况下才去告诉他患了癌症。如果只在非常确定的情况下才预测病人得癌症,那么回归模型会有较高的查准率,但是有较低的查全率,因为我们做预测时只给一小部分病人预测 y = 1 y=1 y=1。当我们把临界值设为0.9时,我们只在至少90%肯定这个病人患有癌症的情况下预测 y = 1 y=1 y=1,这是一个高查准率模型,但是召回率会变得很低。
- 假设我们想要避免遗漏掉患有癌症的人:这种情况下,我们不再设置高的临界值,而是会将临界值设的比较低,比如0.3。这样做的话,如果他们有大于30%的概率患有癌症,我们便以更保守的方式告诉他们患有癌症。这个模型会有一个较高的查全率,因为确定患有癌症的病人有很大一部分被正确标记出来了,但是会有一个较低的查准率,我们预测患有癌症的病人比例越大,那么就有越大比例的病人实际没有患癌症。
我们可以将不同阀值情况下查全率与查准率的关系绘制成图表,如图1所示。
从图1可以看出,查全率和查准率的曲线有各种各样的形状,这取决于回归模型的具体算法。
我们希望有一个帮助我们选择阈值的方法。一种方法是计算F1 值(F1 Score),其计算公式为:
F
1
S
c
o
r
e
=
2
P
R
P
+
R
F1\ _{} \ _{}Score=2\frac{PR}{P+R}
F1 Score=2P+RPR
其中,P为查准率,R为查全率。
F1 值会考虑一部分查准率和查全率的平均值,但是它会给查准率和查全率中较低的值更高的权重,因此它结合了查准率和查全率。我们选择使得F1值最高的阈值。
5. 机器学习的数据
事实证明,在一定条件下,得到大量的数据并在某种类型的学习算法中进行训练可以是一种有效的方法来获得一个具有良好性能的学习算法,而这种情况往往出现在这些条件对于我们的问题都成立并且我们能够得到大量数据的情况下。这可以是一个很好的方式来获得非常高性能的学习算法。
看一个通过机器学习算法来区分常见的易混淆的单词的例子,比如这样的句子:For breakfast I ate __ eggs(to,two,too),这是一个易混淆的单词的例子。研究员把诸如此类的机器学习问题当做一类监督学习问题,并尝试将其分类,什么样的词在一个英文句子特定的位置才是合适的。他们用了几种不同的学习算法,一种是感知器(perceptron),用于逻辑回归上的一个方差;一种是 Winnow算法,类似于回归问题;一种是基于内存的学习算法(Memory-based);还有一种是朴素贝叶斯算法(Naive Bayes)。这些具体算法的细节并不那么重要,他们所做的就是改变了训练数据集的大小,并尝试将这些学习算法用于不同大小的训练数据集中,得到的结果如图2所示。
从图2可以看出,在尝试了许多种不同的算法后发现数据量非常大时,这些不同类型的算法效果都很好。这些趋势非常明显,首先大部分算法都具有相似的性能,其次随着训练数据集的增大,这些算法的性能也都对应地增强了。 事实上,如果我们选择任意一个算法,可能是选择了一个"劣等的"算法,但如果给这个劣等算法更多的数据,那么它可能看上去会比其他算法好,甚至会比"优等算法"更好。
这些结果表明,许多不同的学习算法有时倾向于表现出非常相似的表现,这还取决于一些细节,但是真正能提高性能的是能够给一个算法大量的训练数据。这样的结果引起了一种在机器学习中的普遍共识:“取得成功的人不是拥有最好算法的人,而是拥有最多数据的人”。
当我们有一个高性能的学习算法时,我们希望它不要有高的偏差和方差。 因此偏差问题,我们将通过确保有一个具有很多参数的学习算法来解决,以便我们能够得到一个较低偏差的算法,并且通过用非常大的训练集来保证。保证低误差的关键假设:特征值有足够的信息量,且有一类很好的函数。
有大量的训练数据集,这能保证得到更多的方差值,而且训练了一种带有很多参数的学习算法,那么这将会是一个很好的方式来提供一个高性能的学习算法。