当心这个数据科学错误,避免30多个小时的无用工作……这是一个相对简单的模型。它的AUC初始为0.9,符合比赛要求将AUC控制在0到1之间。另外,我对比赛没有太高的期望。正因为如此,当我像往常一样评估权重模型并训练模型时,我惊讶地看到了以下结果:在当时的比赛实时排行榜中,第一名的AUC值为0.965,而我当时的有效AUC值达到了0.9968,离获奖只差一步,遥遥领先一百多支队伍,不敢相信。深度学习之神似乎在这一天开导了我,让我在权重初始化方面取得了如此骄人的成绩,这在优化方面就像拥有超能力一样强大。结果令人难以置信。尽管我很愿意相信模型给出的数字,但我还是有点怀疑。我一次又一次地评估模型预测,首先是部分数据,然后是整个数据。结果是肯定的:验证分数接近完美。于是我确信自己找到了取胜的捷径,做好了夺冠的准备。怀着激动的心情,我赶紧提交了模型对测试数据的预测。奖金触手可及。而且比赛成绩惊人。0.5分。即使是随机提交一个预测,或者只提交比赛提供的样本文件什么都不做也可以获得0.5分。我当时的神奇顿悟比猜测要好一点。结果出来后,我花了30多个小时去review数据,想找出哪里出了问题,累死了。在预测中,那里肯定有问题,可能是文件有误。然而,这30个小时是白费力气。我花了很大的力气来修正结果,但是预测的结果值还是很低。什么地方出了错?答案是:数据泄露。数据泄露是一个如此简单的概念,但我却走进了它的陷阱。在模型训练中,我的编程没有问题,根据测试数据正确训练了模型,问题出现在了不容易发现的地方。简而言之,当模型遇到不该遇到的情况时,就会发生数据泄漏。在一次比赛中,我对模型进行了多次训练,也就是说,我会加载上一次训练的模型权重,训练模型并保存表现最好的权重。由于计算时间的限制,训练是在多个会话中进行的。但是,在每个会话中,我都会重新运行整个代码,包括将数据随机拆分为训练集和验证集的代码,因此每次训练的训练集都不相同。为了避免这种情况,可以设置一个种子来划分训练/验证组,我(非常)没有预先考虑。即使训练数据每次都不同,模型的权重(它知道的)也会被传递。因此,经过充分的训练,模型已经暴露于整个数据集。由于机器学习模型本身的惯性,模型会放弃学习,转而记忆数据。这对于一个没有情感的网络来说很简单,而且这种现象发生过很多次。因此,模型在面对前所未见的数据时无能为力。由于模型在之前的训练中看到了验证数据,能够得到近乎完美的0.9968,让我误以为这是模型本身的能力。如果你回想一下模型早期的表现,想想为什么验证分数比训练分数高,你就会明白这其实是一个比较奇怪和罕见的现象。所以,大家以后每次修行都要牢记这个重要的教训:如果结果完美得令人难以置信,那么十有八九是错误的结果。(此方法在识别数据泄漏时尤为重要。)这是一种数据泄漏。其他类型的泄漏包括:预处理。如果在拆分之前对数据进行处理,可能会导致信息泄露。例如,如果您对整个数据集使用类似均值的方法,则训练集将包含有关验证集的数据,反之亦然。时间。如果预测问题涉及时间,简单的随机训练/验证拆分将不起作用。也就是说,如果你想根据A和B预测C,你应该在[A,B]→C上训练你的模型,而不是[C,A]→B。这是因为知道后面的数据点C的值,模型可以预测之前的数据点B。事情过于完美时三思而后行是个好习惯,但也要注意细微的细节。例如,分数大幅上升并不一定是奇异现象;当模型对测试数据进行预测时,其性能很差。事实上,最好的办法是注意以任何方式拆分数据的目的,以便将它们拆分为训练/验证/测试集,并尽早进行。此外,播种是一种强有力的保障。从更开放的角度来看,数据泄露可能是有益的。如果模型看到它不应该看到的数据,数据泄漏是好事,但它看到的数据有助于它概括和学习。比如Kaggle的排名系统。该系统由一个公共排行榜和一个私人排行榜组成。用户可以访问所有培训内容和部分测试内容(25%的内容在系统中可访问,用于确定在公共排行榜上的位置)直到比赛结束。但在比赛结束后,另外75%的测试内容将用于对模型进行评估,以确定最终私人排行榜的排名。但是,如果我们能用这25%的测试内容来提高私人排行榜上的分数,那就算是数据泄露了。在Kaggle比赛中,相对常见的做法是对75%的测试数据进行某种预处理,知道另外25%的测试数据。例如,PCA可用于减小尺寸。这通常会提高模型性能,因为通常数据越多越好。我们永远不应该停止寻找改善数据连接的方法;一般来说,永远不要将任何复杂的事件标记为纯粹的坏(或好)事件。总之,数据科学家的目标应该是为模型提供更多的数据,但将数据分开用于不同的用途。另外,为了不让你的希望破灭,你应该消极地编程。毕竟,只有预料到最坏的结果,才能从容应对问题,才能在成功面前欣喜若狂。
