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