继续分析我们之前提到的猫咪图片的案例:现在你负责运营着一个移动端 app,用户会向这个 app 上传许多不同内容的图片。而你希望这个 app 能够从图片中自动地找到猫咪图片。
你的团队通过在不同的网站下载含猫咪的图片(正样本)以及不含猫咪的图片(负样本)得到了一个巨型的数据集。他们将数据集按照 70% / 30% 的比例划分为训练集 (training set) 和测试集 (test set),并且使用这些数据构建出了一个在训练集和测试集上均表现良好的猫咪检测器。
可是当你将这个分类器 (classifier) 部署到移动应用中时,却发现它的性能相当之差!
到底发生了什么?
你发现从网站上下载作为训练集的图片与用户上传的图片有较大的区别 --- 用户上传的图片大部分是用手机拍摄的,此类型的图片往往分辨率较低,且伴随模糊,采光不理想。由于用来进行训练和测试的数据集图片均取自网站,这就导致了算法没能很好地泛化 (generalize) 到我们所关心的手机图片的实际分布 (actual distribution) 情况上。
在大数据时代来临前,机器学习中的普遍做法是使用 70% / 30% 的比例来随机划分出训练集和测试集。这种做法可行,但在越来越多的实际应用中,训练数据集的分布(例如上述案例中的网站图片)与你最终所关心的数据分布情况(例如上述案例中的手机图片)往往不同,此时执意要采取这样的划分则是一个坏主意。
我们通常定义:
- 训练集 (Training set) --- 用于运行你的学习算法。
- 开发集 (Dev/development set) --- 用于参数调整,特征选择,以及对学习算法作出其它决定。有时也称为留出交叉验证集 (hold-out cross validation set)。
- 测试集 (Test set) --- 用于评估算法的性能,但不会据此决定使用什么学习算法或参数。
一旦定义好了开发集和测试集,你的团队将可以尝试许多的想法,比如调整学习算法的参数来探索出哪些参数的效果最好。开发集和测试集能够帮助你的团队快速检测算法性能。
换而言之,开发集和测试集的作用就是引导你的团队对机器学习系统做出最重要的改变。
所以你应当:
合理地选择开发集和测试集,使之能反映你预期将要获得的以及你想要处理好的数据的实际数据情况。
也就是说你的测试集不应该仅是简单地将可用的数据划分出30%,尤其是将来获取的数据(移动端图片)在性质上可能会与训练集(网站图片)不同时。
如果你尚未推出移动端 app,那么可能还没有任何的用户,因此也无法获取能够准确反映你要处理好的情况下的真实数据。但你仍然能够尝试去模拟这种情况,例如邀请你的朋友用手机拍一些猫咪照片并发送给你。当你的app上线后,就能够使用实际的用户数据对开发集和测试集进行更新。
如果你实在没有途径获取近似将来实际情况的数据,也可以从使用已有的网站图片开始进行尝试。但你应时刻牢记其中的风险,它可能导致系统不能够很好地泛化。
这就要求你主观地进行判断,应该投入多少来确定一个理想的开发集和测试集。但请千万不要假定你的训练集数据分布和测试集数据分布是一致的。不是任意选取你在训练过程中拥有的数据组成测试集,而是尽可能地选出能够反映你最终期望能处理好的数据作为测试样本。