最近因为某事要准备一点材料,刚好前段时间给导师做项目的时候遇到一个大坑,浪费了很多时间,所以就着这个问题顺便做点总结。

传统的机器学习,即在深度学习流行之前的问题的一般处理流程通常是“预处理->特征变换->分类/回归”。即便现在深度学习似乎要统治业界,但要转换成这样的步骤,也不过是将“特征变换”与“分类/回归”合二为一而已,该做的预处理往往还是要做。《深度学习(Deep Learning Book)》里提过一种对深度学习的诠释思路——深度表示学习,与之类似。

但放到现实问题中来看,机器学习只不过是整个问题解决过程中一个很小的组成部分。比如在公司做业务,你要收集数据、清洗数据、建立合适的数据结构,对大规模数据可能还要顺便把大规模分布式问题解决一下。等费劲千辛万苦拿到“干净”的数据之后,才进入机器学习/模式识别问题的一般步骤。
而实际上,至少七成时间花在了准备数据的阶段。很多人学机器学习往往只重视算法或者模型,学深度学习的只看网络结构和调参方法,但不要忘了,这是因为有人为你准备好了数据集和评测流程、方法。对于实际问题,这一整套框架都要根据实际情况去设计、改进,使之贴近业务,提供更好的服务。

做科研有做科研的方法,做实际业务是另一套模式。业界需要的大量的算法工程师,往往是做这些看似琐碎的无趣的活,这样看来程序员转算法工程师其实是比较容易的。
啊哀叹一下为什么我编程这么菜……

扯淡结束。这篇博文要记录的内容,与数据集的制作与划分有关。
本文还是以大白话写就,您读着也省劲,我写得也轻松。

Part 1. 实例: 一个信号处理问题

就从实际问题的背景开始,由导师的项目说起吧。
项目需要完成一个系统,我负责实验设计、总体设计和信号处理+识别。这个项目的信号或者说数据是按时间采样得到的,比如说采样率是500Hz每秒就能得到500个点。一次采集在一分钟以上,只需要其中的不到三十秒的数据。
所以问题就来了:得到一组数据需要至少一分钟,而且这个采集过程不能长时间运行,一次实验最多采三十组数据;更尴尬的是,实验比较特殊,不是想做几组就做几组的。
也就是说,我们必须要用比较少的采集组数得到数据集,还要训练一个比较可靠的模型,用来做信号的识别/分类。
一开始我想得很简单——少就少呗,无非是个小样本学习的问题。找一个鲁棒性比较好的特征变换方法,用简单点儿的分类模型,分分钟解决问题,反正设计指标也不高。
但说归说,只有十几二十个样本,谁能保证训出来的模型能用啊。

查了一些文献,又结合系统的要求,最后选择用滑动窗分割的方法来增广数据集,即设置一个固定时长的滑动窗在时域信号上滑动,重叠时长为0,这样把一个样本切割成几十份样本,数据集扩增了几十倍。瞬间就把样本不足的问题解决了。
采取这种方式,一是有人一直在这么做,二是系统实际工作时处理过程也与之类似——总不能后台默默跑一分钟才告诉你一个结果吧?最好是几秒钟就显示一个结果,让甲方知道我们的系统在干活,而不只是琢磨着怎么把他们的钱忽悠走。

离线测试效果奔波儿灞,不是,倍儿棒,正确率直接奔着95%去了。老实说当时我是有点怀疑的,但稍微动了一下脑子,感觉最多也就是线上比离线差点儿,总不能太糟吧。
怕啥来啥。线上测试二分类正确率50%。
当时我就蒙了。接着回炉重造,想到一个比较特殊的情况,改模型再训,嚯!99%!心想这回总不至于那么差吧,一上线还是完蛋。
那几天是真烦,实在想不清楚怎么就完蛋了。

过了大概大半星期,忽然产生了一个念头——是不是数据集有问题
众所周知,我们一般做机器学习要在数据集上 shuffle,然后按比例划分训练、验证和测试集。这个系统模型比较简单没几个超参,样本又少,出于侥幸心理干脆就省略了验证集。
但问题在于,这个数据集是怎么得到的?是从大约二十组信号上“片”出来的。
我隐约察觉问题在哪儿了。然后就实验验证呗。
从时间的角度考虑,系统需要用“过去”的数据去预测“未来”。所以这一回我先划分了训练和测试集数据,然后再做切片。其实在这里,数据根本不需要 shuffle ——分类器是 linear classifier 或 SVM,训练过程是一次把所有数据喂进去。Shuffle 没有任何意义。
这回的测试结果看起来比较“正常”了——在50%和60%之间浮动。好嘛问题终于是定位到了,但新的问题是,这样一来我用的信号处理方法对分类根本没效果,简直一夜回到解放前。

后来我对一些小细节做了一点调整,最近参与的三个人差不多把全新的系统调试完了,具体效果……我猜设计要求的70%还是能达到吧。不再细说。

Part 2. 数据集的制作与划分,方法要根据问题而定

所以说,通过这一课我学到了什么?

  1. shuffle 不要乱用
  2. 算法一定要贴在具体业务上

为什么我的模型会线下99%、线上50%?
显然是对线下模型过拟合了。但我明明做了训练集和测试集啊?问题就出在这儿:
我增广之后,先 shuffle、再划分。对学术界的很多数据集,这么做可能完全没影响,但没影响不代表它是对的。Kaggle 、天池之类的数据竞赛,训练集和测试集都是提前划分好的,有没有想过其中的道理?
打个比方,我的错误操作,就像中学时候不会做的题目抄答案,但每次只看一半,理由是“只要给个思路我就会做了”。当然,这纯粹是自己骗自己。
先 shuffle 再划分,就相当于“答案只看一半”——“过去”的数据和“现在”的数据混到了一起,模型既学到了“过去”的模式,又学到了“现在”的模式,准确率自然可观;而“未来”的数据是不可见的,模型显然学不到“未来”的模式。
所以正确的方法是先划分。Shuffle 可以不用。因为 shuffle 的作用体现在 mini-batch learning 的时候。一次性训练的分类器使用 shuffle 并没有什么意义。

第二点体会就结合我的方向来说了。去年去北京听课,天津大学的一位博后在讲实验设计和信号处理方法的时候提到,我们这个领域多年来已经遇到了瓶颈,具体体现在算法的提升作用越来越小,实验设计反倒比处理方法重要得多。
我非常赞同。
深度学习火起来之后,领域内不少人也研究过基于深度学习的处理方法,但经得起考验的成果不多。一方面深度学习不是万能的,另一方面,多年来进展缓慢,侧面说明我们这个领域可能真地存在这么一个天花板。我觉得具体问题就在信号采集的方式和设备上面——这个话题不展开讨论——结果就是,受制于“硬件”限制,在实验设计上出成果比在算法上出成果要容易。
这就是说,对很多实际问题来说,算法并不是关键。按照 Andrew Ng. 和国外很多博客的观点,围绕你的目标设计一个好的 pipeline,包括如何对数据的建模、一个衡量模型好坏的基准等等,然后不断改进,这才是使用机器学习的有效方式,而不是只针对其中算法的部分尝试各种分类/回归器,或者想用深度学习调参搞定一切。这正是 NFL 定理的意义:如果不考虑具体问题,所有的算法都是随机猜测,没有好坏之分。

Part 3. 另一个案例: Google MLCC 十八世纪文学

因为一些缘故不太想把我的方向说太细,结果刚好前几天把 Google 新出的机器学习课程 MLCC 过了一遍,发现最后有个案例跟我遇到的问题简直一模一样,在这里简单介绍一下吧。
课程页面见 https://developers.google.com/machine-learning/crash-course/ ,显然需要翻墙。课程自带中文、中文字幕和机器配音(非常带感,建议体验一下)。案例在 https://developers.google.com/machine-learning/crash-course/18th-century-literature。

Google 工程师与一位研究十八世纪文学的教授合作,开发了一个“心灵隐喻(the metaphors to the mind)”数据库,记录了十八世纪所有的文学作品中关于“心灵”的隐喻的句子,比如“心灵是一座花园”“心灵是一块白板”。这位教授想了解是否能从这些作者使用的隐喻中得知他们的政治派别。
把数据集划分、训练之后,发现准确率非常高。他们觉得这里面肯定有问题。


这是他们最开始划分数据集的方式:
逐句拆分样本。某位作者的句子在训练、验证和测试集中均存在。这样一来,模型不仅学到了隐喻,还学到了这位作者写作语言的特点,即模型记忆了关于作者的额外信息。
发现这个问题后,他们重新划分数据集,把某位作者的作品仅放在训练或测试或验证集中,即:


现在准确率大幅下降,而且很难得到比较高的准确率,即仅根据隐喻来判断政治派别,是一件非常困难的事情。


讲师最后总结说,这个案例说明:在随机打乱数据和拆分数据之前,需要考虑数据本身的意义。

Update

写完发出去才反应过来:
正在跑着的程序,一篇 AAAI-18 上本领域的文章,我顺着作者找到了他们没有公开的 Github 地址。当时看到 paper 就怀疑他们结果有问题,准确率未免太高了。
看了一下代码,发现跟上面讲过的一样,也是把所有数据拿出来打乱再划分。唉,简直是……特么的在逗我。
一叶知秋,可见顶会 paper 也未必靠谱。

一个项目的经验教训:关于打乱和拆分数据相关推荐

  1. java项目教训_[免费电子书]分析超过600,000个Java项目的经验教训

    java项目教训 建立明智的错误处理工作流程需要什么? 调查和解决生产中的应用程序错误对于维持性能和可靠性至关重要. 但是,这并不意味着要花很多时间. 要理解为什么在生产中的故障排除,可这样的头痛,我 ...

  2. 如何改进项目的经验教训总结会

    [size=medium] 大多数在经验教训总结会上被提出的问题只集中在那些[b]已经完成的项目[/b]. 但即使同一个团队,也不会可能会再做同一个项目,一些与具体项目相关的问题也可能也不会出现在下一 ...

  3. 一个项目实施经验的总结

    背景:产品是公司研发开发的产品,我们在其上面为客户做了二次开发. 1,服务器是和本地开发环境是不同的,如果调用第三方服务,一定要在开始调用的时候和结束调用的记下日志,主要写下开启用时,是否开始成功,以 ...

  4. 几点项目里的经验教训

      年后上班,正是项目新的一个开发阶段开始了.果然年后是人员流动的高峰期,有几个同事辞职了.为了工作的顺利衔接,又有新的人员开始补充进来.项目总是时间紧,任务重.第一批任务即将开始,已经没有退路了.回 ...

  5. 做事用人 用人做事_做事:构建我的第一个Web应用程序的经验教训

    做事用人 用人做事 On the 5th of June, 2020, after almost two weeks of (re)learning javascript, fixing bugs, ...

  6. 我为期一个月的GitHub的经验教训

    by JS 由JS 我为期一个月的GitHub的经验教训 (Lessons from my month-long GitHub commit streak) "I want to learn ...

  7. 项目文件2 问题日志 经验教训登记册 里程碑清单 实物资源分配单 项目日历 项目沟通记录 项目进度计划 项目进度网络图

    9. 问题日志 在整个项目生命周期中,项目经理通常会遇到问题.差距.不一致或意外冲突. 项目经理需要采取某些行动加以处理,以免影响项目绩效. 问题日志是一种记录和跟进所有问题的项目文件,所需记录和跟进 ...

  8. 使用Flutter完成10个商业项目后的经验教训

    作者:Łukasz Kosman 和 Jakub Wojtczak 原文:https://medium.com/swlh/lessons-learned-after-making-the-first- ...

  9. 使用Flutter完成10个商业项目后的经验教训,2021大厂安卓面试集合

    自从我们交付了第一个应用程序并从客户那里收集到了五星级好评,我们认为,我们应该开始更加积极地向客户推荐Flutter.从2019年5月开始,我们决定Flutter将是我们移动技术的第一选择.同时,我们 ...

最新文章

  1. pat数素数 20 c语言,PAT乙级C语言1013 数素数
  2. python安装环境傻瓜式安装_Python环境安装(两种方式)
  3. [评论]为什么程序员的社会地位不高?--转载
  4. block在美团iOS的实践
  5. 编写一个成绩分类程序
  6. 计算机Auto服务错误1053,Win7电脑宽带连接错误1053的原因和解决方案
  7. 日立电梯举办2018“新思维 新动能”创新分享汇
  8. MATLAB图像灰度图处理
  9. 【面试必过系列,15个经典面试问题及回答思路
  10. 傅里叶变换中采样频率(fs)的解读
  11. HEVC学习(二十八) —— 量化之二
  12. 双臂二指魔方机器人的制作(三)--还原控制
  13. Ubuntu查看一些版本 1
  14. Vi下编辑和退出编辑方法
  15. 数字图像频谱的中心化
  16. 多线程分批次查询数据
  17. 基础(一):SCSI硬盘与IDE硬盘有什么区别
  18. 国外客户最讨厌的开发信
  19. 《经营最重要的事》-- 梅纳德.韦伯
  20. ios ---扩音器(外放)

热门文章

  1. input file本地图片预览的方法(兼容IE、Chrome和Firefox)
  2. 三菱FX5U程序,双FX5U80MT主从站控制,普洛菲斯触摸屏程序,搭配三菱伺服,松下变频器控制运动控制数轴运动控制
  3. 数据库常见笔试面试题
  4. android翻书效果实现原理( 贝塞尔曲线绘制原理/点坐标计算)
  5. java 约分_约分的方法
  6. POJ 最小公倍数
  7. 如何在手机查看电脑html
  8. Linux安装及美化Typora详细步骤
  9. linux安全配置技术论文,基于linux平台的web安全技术研究apache安全大学论文.doc
  10. 【渝粤题库】陕西师范大学400009 行政管理学 作业(专升本)