这一节是Andrew对应用机器学习给出的建议,虽然没有数学公式,但却是十分重要的一课。
Debugging Learning Algorithms
假设要做一个垃圾邮件分类的模型,已经从海量的词汇表中选出一个较小的词汇子集(100个单词)作为特征。 用梯度上升算法实现了贝叶斯逻辑回归,但测试集的错误率达到了20%,这显然太高了。
如何解决这个问题?
- 收集更多的训练样本
- 进一步减少特征数
- 增加特征数
- 改变特征(考虑邮件标题/正文)
- 将梯度上升多运行几个迭代
- 尝试牛顿方法
- 使用不同的λ
- 改用SVM
"the people in industry and in search that I see that are really good, would not go and try to change a learning algorithm randomly."这是Andrew的原话,有这么多的解决方案,如果我们只是随机地选择,那么既浪费时间又感觉是在碰运气。而更好的方法应该是:先通过诊断分析出问题到底出在哪里,然后再选择合适的解决方案。
1.high variance vs high bias
Typical learning curve for high variance:
- 随着样本量的增大,测试集的错误率将会持续减小(增大样本量将有助于性能的改善)
- 训练集的错误率与测试集的错误率有很大距离
Typical learning curve for high bias:
- 训练集的错误率也无法接受地高
- 训练集与测试集的错误率相差不大
因此,上面列出的解决方案中:
- 收集更多的训练样本 ——可解决high variance问题
- 进一步减少特征数 ——可解决high variance问题
- 增加特征数 ——可解决high bias问题
- 改变特征(考虑邮件标题/正文) ——可解决high bias问题
2.optimization algorithm vs optimization objective
还是刚才垃圾邮件分类的例子,假设贝叶斯逻辑回归对垃圾邮件分类的错误率是2%,对非垃圾邮件分类的错误率也是2%(我们不愿意看到有过多的正常邮件也被过滤);而SVM使用linear kernel在垃圾邮件分类的错误率是10%,而对非垃圾邮件分类的错误率只有0.01%。但考虑到计算的效率,你还是想使用逻辑回归,这时应该如何调优? 这时我们关心的问题有两个:
- 逻辑回归的梯度上升算法是否收敛了?
- 我们是否在优化正确的函数?
这个问题中,我们关心的函数是加权的准确率(非垃圾邮件的权重应高于垃圾邮件的权重):
而贝叶斯逻辑回归与SVM相应的策略函数则需要考虑是否选用了合适的参数:
由问题的背景,我们已经有a(θSVM) > a(θBLR),这时我们需要诊断:J(θSVM) > J(θBLR)? 如果J(θSVM) > J(θBLR),这说明θBLR没能最大化J(θ),也就是算法没能收敛,需要改进最优化算法; 如果J(θSVM) ≤ J(θBLR),这说明J(θ)是错误的优化目标,因为即使J(θ)已经最大化而我们关心的目标函数却没能最大化,需要改进目标函数。 因此,上面列出的解决方案中:
- 将梯度上升多运行几个迭代 ——可解决最优化算法问题
- 尝试牛顿方法 ——可解决最优化算法问题
- 使用不同的λ ——可解决最优化目标问题
- 改用SVM ——可解决最优化目标问题
由上所述的两个问题可见,如果没有诊断清楚问题的根源就随机调优,将很有可能导致做了半天却毫无改进。除此之外,经常需要提出自己的诊断方法以确定算法中出现了什么问题。"solving a really important problem using learning algorithms, one of the most valuable things is just your own personal intuitive understanding of problem." 而诊断确定机器学习应用中的问题是获得“理解问题的直觉”的好方法。
Error Analysis
假设有一个人脸识别的机器学习应用,它由多个不同的机器学习组件构成。
当前整个系统的准确率是85%,我们可以通过误差分析的方法来确定哪个组件的改善能够最大程度地提升整体准确率:
具体的做法是:用人工或者其他手段替换一个机器学习的组件,记录替换后得到的系统准确率。由上表我们可以看到,提升Face detection将显著提升系统的准确率(应该是我们下一步工作的重点),而Preprocess(remove backgroung)则只能微量提升整体准确率。
Ablative analysis
假设,通过添加了一些特征到逻辑回归中:
- Spelling correction
- Sender host features
- Email header features
- Email text parser features
- Javascript parser
- Features from embedded images
我们将一个原本准确率只有94.0%的垃圾邮件分类器提升至准确率为99.9%。此时,我们想知道每一个组件对整体准确率的提升有多大? 消蚀分析通过每次从系统中移除一个组件,看准确率下降多少以解答这个问题:
由上,我们可以看到Email text parser features对准确率提升的帮助最大,如果考虑通过去除一些组件以提升效率的话,这一步是最不应该被去除的。
Getting started on a learning problem
Approach #1: Careful design
- Spend a long term designing exactly the right features, collecting the right dataset, and designing the right algorithmic architecture.
- Implement it and hope it works.
Benefit: Nicer, perhaps more scalable algorithms. May come up with new, elegant, learning algorithms; contribute to basic research in machine learning.
Approach #2: Build-and-fix
- Implement something quick-and-dirty.
- Run error analyses and diagnostics to see what’s wrong with it, and fix its errors.
Benefit: Will often get your application problem working more quickly. Faster time to market.
第一种方法适用于做理论研究。 而在日常的工作中我们应使用第二种方案,避免过早优化(去学一大堆可能用不着的知识,花费大量的精力在只能提升一点点收益的地方),提升工作效率! 最后,Andrew表示他经常要花3分之1甚至更多的时间在诊断方法的设计上,以找出哪里能正常工作,哪里出了问题,而花这部分时间是非常值得的(well-spent)。
总结
从过年期间(第一篇笔记发布于2月24号)到清明假期(今天4月5号),历经40天左右的时间终于把CS229监督学习的部分过了一遍。期间解开了无数困惑已久的机器学习领域的问题,感觉整个人神清气爽。感谢网易公开的翻译,并且细心地提供了讲义下载,当然更感谢Andrew大神的精彩授课。接下来需要先掌握一个好的工具箱(也许是mahout?);然后开始践行先Implement something quick-and-dirty,再通过error analyses优化重点环节。像个ml专家一样去战斗!