什么是 ML 策略
比如说你的猫分类模型已经达到了 90% 的正确率. 你想继续提升你的正确率, 可能就会想到以下的方式:
通常来说是有非常多的方式, 当是如果你选错了方向. 可能就会浪费掉大量的时间. 就比如你可能花了6 个月的时间去收集数据.但是最终发现更多的数据对网络没有任何帮助
所以怎么去判断优化方法是 有效的 就至关重要.
正交化
深度学习的过程中有很多参数需要调整, 一些效率高的深度学习专家特别清楚, 调整哪些参数来达到某种效果. 这个过程我们成为正交化.
以下是例子:
如果只有一个按钮去同时调整, 电视的画面参数, 那么你很难将画面调对. 但是如果每个旋钮只调整一个参数, 那么将会变得容易得多. 正交化就是指, 一种参数对应一种效果.
正交化意味着互成 90 度, 这样调整参数时将会容易一些.
在训练的过程中一般有以下几个步骤, 而对应这个步骤, 需要相应的”按钮”进行控制:
- 训练集的拟合: 需要更大的网络, 或是使用更好的优化算法(adam), 等
- 开发集的拟合: 可能需要正则化的进行调整, 或者增大训练集
- 测试集的拟合: 如果在开发集上拟合了, 但是在测试集上的效果并不好, 那可能需要增大开发集的样本数量
- 最终使用效果不好: 可能就需要更换开发集或者 cost function.
过早停止像一个按钮调整了两个方面, 所以酌情使用
单一数字评估指标
为你的问题设置一个可评估的单一指标, 让我们来看一个例子:
应用机器学习是一个非常经验性的过程, 通常是有一个想法, 编程序, 跑实验. 然后查看最终的效果如何. 然后使用这些实验结果来改善你的想法.
假设现在你有两个预测猫的分类器: A / B .
我们使用两个指标进行评估:
- Precision(精确率):在预测为猫的样本中,有多少是真正的猫。
- Recall(召回率):在所有的猫样本中,有多少被预测为猫。
在这个例子中, AB 分类器在不同的指标下各有优势, 所以你需要找到一个新的评估指标, 对这两个指标进行结合. 也就是 F1 Score(harmonic mean)
大多数会使用测试集 以及 F1 的指标进行评估, 快速淘汰网络.
类似的还有观测部署后的, 模型的平均正确率. 可以让你更快的筛选出优势网络.
满足和优化指标
假设你对猫分类器的正确性非常在意. 但是在 准确度之外, 运行时间也是我们非常在意的一个点.
所以, 对此我们也能定义一个指标. 例如, 成本 = 准确度 - 运行时间 * 0.5
或者不使用线性的方式进行约束.
只是进行要求在 100ms 响应, 并准确率越高越好.
训练 / 开发 / 测试 集的划分方式
假设你有以下 8 个地区的数据, 不能以不同国家的方式划分 开发集 和 测试集.
而是应该将所有国家的数据随机排序放入测试集和训练集.
让开发集和测试集都来自同一分布, 否则可能出现在开发集上表现很好, 但是测试集上出现偏差。 ( 因为开发集和测试集的”靶子”是不一样的, 所以花时间在开发集上调试之后, 就会出现在测试集上作用不佳
开发集和测试集的划分
你可能听说过 测试集 和 测试集 的划分方式: 训练集 70% 测试集 30%
如果需要开发集的话, 可能会这样进行划分: 训练集 60% 开发集 20% 测试集 20%
但这种划分方式比较适合过去训练数据较小的时候: 100 ~ 10000 个样本数量
而当你拥有 1,000,000 个样本时, 可能 训练集 98% 开发/测试集 1% 更加合适
测试集的选择是可选的, 不过如果你的开发集不够大, 那么干净的测试集也是对模型效果的一种保障
发现方向错误 如何调整
假设你正在构建一个猫分类器, 试图找到很多猫的照片, 你有 A/B 两个模型, 误差分别为: 3% 和 5%
但是因为算法 A 可能推荐色情图片. 这是不可接受的. 但是算法 B 不会. 所以即使 B 算法的错误率有 5% 但 B 算法才是最适合的.
所以这时候你需要, 修改判断指标的计算公式.
还有另外一个例子, 在你的猫分类模型的开发过程中, 可能你的训练集使用的是网上下载的, 高质量的图片,而你的用户可能发送的是低清, 或者是没有聚焦的图片.
这也会导致你的模型最终效果不好, 所以你也要改变你的评估指标
为什么是人类的级别
因为人类的能力很接近贝叶斯最优误差(Bayes’optimal error), 所以当模型拥有超过人类的表现时, 已经没有更多的提升空间了。
如果你的模型比人的能力还差, 那么就有其他手段来提升至人类水平。比如:
- 获得更多人类标记的样本
- 人工误差分析
- 分析偏差和方差
avoidable bias
假设你在训练一个猫分类器, 判断一张图片中是否有猫. 你目前的情况如下:
错误率 | |
---|---|
人类表现 | 1% |
测试集 | 8% |
开发集 | 10% |
可以看到, 相比开发集 和训练集之间的错误率差距, 训练集与人的差距更大. 所以训练集的拟合程度还是不好. 所以这时候将重点放在减少偏差(avoidable bias)上, 可能训练更大的神经网络, 或者运行梯度下降更久一些, 以提升训练集的表现.
错误率 | |
---|---|
人类表现 | 7.5% |
测试集 | 8% |
开发集 | 10% |
但, 如果人类的表现是在 7.5% .那么实际上训练集的效果已经很好了, 这时候需要减少算法的方差. 可以试试正则化, 或者收集更多的数据.
使用人类的水平当作, 贝叶斯误差或者贝叶斯最优误差值进行判定当前模型的状态. 然后选择合适的优化方式, 确定优化方向.
人类水平表现的定义
假设你想要训练一个医学图像分类的模型, 对于不同的医生, 识别图像的错误率可能如下:
分类错误率 | |
---|---|
普通人 | 3.0% |
主治医生 | 1.0% |
主任医生 | 0.7% |
专业的医生团队 | 0.5% |
此时你的目标贝叶斯误差取的值决于你的选择。 在这个例子中, 贝叶斯误差值小于等于 0.5%
分类错误率(%) | |||
情况A | 情况B | 情况C | |
人类的基准 (接近贝叶斯误差) | 1 | 1 | 0.5 |
0.7 | 0.5 | ||
0.7 | 0.5 | ||
测试集错误 | 5 | 1 | 0.7 |
开发集错误 | 6 | 5 | 0.8 |
- 情况A: 这种情况下选择哪种人类水平没有任何影响. 偏差在 4% 到 4.5% 之间, 且方差是 1%. 因此, 重点应该放在减少偏差上.
- 情况B: 这种情况下选择哪种人类水平没有任何影响. 偏差在 0% 到 0.5% 之间, 且方差是 4%. 因此, 重点应该放在减少方差上.
- 情况C: 这种情况下贝叶斯偏差接近 0.5% 你无法低于这个值,除非你的训练集拟合了. 此外 偏差是 0.2% 方差是 0.1% .因此, 重点应该放在减少偏差上.
超越人类
分类错误率(%) | |||
情况A | 情况B | ||
一个人类团队 (接近贝叶斯误差) |
0.5 | 0.5 | |
普通人 | 1 | 1 | |
测试集错误 | 0.6 | 0.3 | |
开发集错误 | 0.8 | 0.4 |
- 情况A: 这种情况下贝叶斯误差是 0.5%, 因此偏差是 0.1% 方差是 0.2%.
- 情况B: 这种情况下没有足够的信息判断偏差和方差. 这并不意味着没有方法提升模型的能力, 只是说明我们之前提到的方式对这种情况的判断没有作用.
有许多的算法能力已经超过了人类的能力, 尤其是在结构化数据领域:
- 在线广告
- 产品推荐, 推荐书或者电影
- 统计学预测(物流时间预测)
- 贷款偿还意愿
这些都不是自然感知问题(natural perception problems). 例如, 计算机视觉, 语音识别, 自然语言处理任务. 在这些问题上超越人类还是有一定难度.
进行误差分析
让我们继续使用猫分类器进行举例。 假设你的网络已经达到了 90% 的正确率, 那么这时候你发现在错误分类的图片中出现了狗的图片, 那么此时你是否应该优化网络更好的区分猫和狗呢?
实际上应该需要这样做:
- 先大致浏览错误识别的图片, 然后将可能优化的方向列出
- 建立表格, 横轴是这张图片需要优化的方向, 竖轴是每张图片
- 选取大约100张错误分类的图片, 并且分类并在表格中做出标记
比如, 在猫分类模型中可能的优化方向有: 将狗错误识别了, 错误识别了猫科动物, 模糊的画面, 由于滤镜的原因, 就可以像这样进行列表:
图片 | 狗 | 猫科动物 | 模糊 | 滤镜 | 备注 |
---|---|---|---|---|---|
1 | √ | √ | 比特犬 | ||
2 | √ | √ | |||
3 | √ | √ | 由于雨天导致 的图片模糊 |
||
… | … | … | … | … | … |
百分比 | 8% | 43% | 61% | 12% |
中途中发现的新的情况, 也可以直接加入表中.
这样就可以根据情况所占的百分比进行优化, 比如猫科动物和模糊导致的错误识别情况较多, 优化这些相比优化错误识别狗或者滤镜原因, 可能带来的收益更高.
清理错误标记的数据
神经网络对于随机的错误具有抗性. 对于训练集来说, 只要样本数量足够大, 放着这些误差不管也没事, 看见了修正下就行.
但是如果标记时, 总是将某类(例如,总是将白色的狗标记为猫), 那这就成了问题. 神经网络也会将白色的狗标记为猫.
但随机错误或者近似随机的错误, 对于神经网络来说不是问题.
也可以在误差分析的时候, 加入标签错误的你分析. 然后检查所占百分比是否值得去纠正.
- 无论使用什么修正手段, 都要同时对开发集和测试集进行处理
- 对正确的例子也进行分析
- 训练集和 开发/测试集 可能会有些不一样
快速搭建你的第一个系统
假设你需要构建一个语音识别系统, 那么你可能考虑以下问题:
- 嘈杂的背景音
- 咖啡厅
- 汽车噪音等
- 口音
- 离麦克风很远
- 儿童的语音: 单词发音不清晰等
- 口吃的人, 或者说了很多无意义的短语, 比如: oh / ah / um
而我给你的建议是, 直接快速的搭建一个系统, 然后开始迭代
- 快速设立开发集/测试集/指标, 这样就确定了你的目标所在. 就算是目标错了, 也可以及时修改.
- 快速构建一个机器学习系统原型, 然后使用训练集, 试试效果. 然后在 开发/测试集 上试试效果. (可以说一个快速的肮脏的实现, 不要想太多, 有一个大致的系统, 方便后续的优化)
- 然后就可以使用前面提到的 偏/方差分析 / 误差分析, 对模型进行优化. 之后再对, 就像上面列出的问题那些进行优化.
但以上的步骤比较适合, 研究比较少的领域. 如果已经有了成熟的实现, 不妨试试在这些论文的基础上进行优化.
在不同分布的数据上进行训练和测试
由于深度学习需要非常多的数据, 这就导致尽可能将所有的可用数据都加入训练集, 这就导致了, 训练集可能与 开发/测试集 的分布不同. 所以有一些处理训练集和测试集存在差异的手段.
假设你开发了一个手机应用, 用户会上传图片, 你想要识别用户上传的图片是不是猫. 现在你有两个数据来源, 一个是你真正关心的, 也就是用户上传的图片, 比较业余, 取景不太好, 甚至有些模糊, 另一个数据来源是你使用网络爬虫挖掘网页, 直接下载的.
也许你的用户还不多, 你可能只能获取到 10,000 张用户上传的图片. 但是通过网络爬虫你可以获得大概 200,000 张图片. 而你真正关系的是你的网络在用户图片识别上效果的好坏.
所以你现在就陷入的困境:
- 用户数据是你最终关系的数据, 但是数据集较小
- 网络收集的数据并不完全是你的需要
以下是几种选择:
- 将两组数据混合/打乱, 然后确定开发集的测试集各包含 2500 个样本.这样训练集就有 205,000 个样本了.
- 优势: 这样你的 训练/开发/测试集 都来自同一样本分布, 这样更好的管理
- 劣势: 开发集和测试集只有很少一部分的样本(平均而言大概119张)是来自你真正关心的用户上传的照片, 而测试集是你的目标, 所以你可能大部分的时间都是在优化来自网页下载的图片, 这其实并不是你想要的
- 所以第一个选项是不建议的
- 训练集使用网络上下载的全部照片 + 用户上传的 5,000 张照片, 然后 开发/测试集 都是使用用户上传的照片. 相对来说能长期带来好处.
- 优势: 这样你”瞄准”的目标就是你想要处理的目标
- 劣势: 训练集和 开发/测试集 的分布是不同的
另一个例子: 一个语音激活汽车后视镜, 你要怎么收集训练数据去训练这个产品的语言识别模块呢?
在不同分布的数据上进行 分差/方差 分析
假设你在训练一个猫分类器
你所知道人的识别误差是 0%, 训练集为: 1%, 开发集为 10%.
加入你的训练集和开发集是来自同一分布, 那么你能够快速判断是因为 方差 较大的问题. 但是因为这里是来自不同的分布, 你就无法如此武断了. 因为可能训练集都是高清的图片, 而开发集难识别的多, 所以网络也许没有方差问题, 只是说明了开发集包含了更难正确分类的照片.
所以这边有两个原因导致了误差:
- 算法只知道训练集数据, 并没有使用开发集数据
- 开发集的数据来自不同的分布
这导致很难确认 9% 的误差是不是因为, 训练集与开发集数据分布不同导致的.
所以我们需要定义一个新的数据集: 训练-开发集(与训练集同源但是不用于训练)
这样就能使用 偏/方差 分析工具进行分析了.
分类错误率(%) | |||
情况A | 情况B | ||
训练集误差 | 1 | 1 | |
训练-开发集误差 | 9 | 1.5 | |
开发集误差 | 10 | 10 |
- 情况A: 可以看到 训练集和训练-开发集 的误差较大, 可能是出现了方差导致的
- 情况A: 可以看到 开发集和训练-开发集 的误差较大, 可能是数据不匹配导致的
错误概率不总是增大的, 如果减小. 可能是说明你的识别目标比你的训练集容易.
后视镜语音识别的例子
数据不匹配可能的解决方式
- 通过手动错误分析, 尝试了解 训练集 和 开发/测试集 的具体差异.
- 对于后视镜语音识别来说可能会发现: 背景噪音(汽车噪音), 特定的词, 比如街道代码(street numbers)
- 使 训练集 变得更接近 开发/测试集, 或者尝试收集更多接近于 开发/测试集 的数据.
- 对于后视镜语音识别来说, 你可以: 对训练的声音添加车辆的噪声模拟, 人工合成一些语音
不过以上并不是系统化的过程, 只是粗略的指南, 或者说是你可以做的尝试.
不过人工合成的语音数据,需要注意一些事项. 就比如你合成在汽车中说话的语音. 你拥有 10,000 小时的安静情况下的语音. 但是车辆行驶中的噪音你只有 1 小时. 虽然你这样合成对于人来说没有什么问题, 但是对于神经网络来说, 可能会过拟合这段汽车噪音. 而你的这一小时的汽车噪音, 可能只是所有汽车噪音中的一种.
另一个自动驾驶的例子, 使用合成的照片代替真车的识别, 可能会导致数据只集中在所有车中的几种, 或者使用电脑游戏中车的截图, 也可能使你的神经网络过拟合.
人工合成是数据已经证明是有效的, 但是在合成时, 需要注意你的数据是否具有代表性, 还是说只是集中在某些数据上的模拟.
迁移学习
将神经网络从这个任务中学到的知识, 迁移到另外的一个网路中.
假设你已经训练好了一个图像识别神经网络, 你想拿来 适应/迁移 到不同任务中. 比如放射科诊断, 用于阅读 X 射线扫描图.
你需要做的是, 把神经网络的输出层拿走. 然后将最后一层或几层的权重删除. 并进行重新赋值. 然后使用 放射诊断数据 进行训练.
具体地说, 在第一阶段的训练过程中. 你可以训练神经网络的所有常用参数, 所有层的权重. 这样你就得到了能够做图像识别预测的网络. 得到了这个网络之后, 要实现迁移学习, 你现在要做的就是将数据集换成全新的 x,y. 就像现在所说的 放射诊断数据. 然后初始化最后一层的权重. 然后在这个新数据集上重新训练网络.
- 如果你的数据很少, 那么你可能只需要重新训练最后一层的权重.
- 如果你有足够的数据, 那么你可以训练神经网络中的所有层. 这样的做法也成为 预训练(pre-training). 后续的步骤称为 微调(fine tuning).
为什么有这样的效果呢? 因为有很多低层次的特征, 比如边缘检测, 曲线检测, 阳性对象检测. 这些从非常大的图像识别库中, 学习到的这些能力. 可能有助于你的算法在放射科诊断中做的更好. 因为预训练的算法已经学到了很多结构信息, 图像形状的信息, 其中一些信息可能很有用处.
另一个是语音识别系统的例子. 假设你已经训练了一个能够进行语音识别的网络. 这时你想搭建一个 “唤醒词(wake words)” 或 “触发词(trigger words)” 的检测系统.
假设你想要做到这个, 你可能需要去掉神经网络的最后一层, 然后加入新的输出节点(不仅仅是一个, 可能是多个). 然后使用唤醒词的数据集进行训练.
那么迁移学习什么时候是有意义的呢? 当你想创建 任务A 到 任务B 的迁移学习时
- 任务A 与 任务B 有着同样的输入 x, 比如都是音频, 或者都是图像
- 任务A 的数据比 任务B 的数据多得多时, 迁移学习的意义更大.
- 觉得 任务A 的低层次特征(low level features) 可以帮助 任务B 学习, 那么迁移学习是有意义的.
多任务学习
迁移学习中, 任务是串行的. 你从 任务A 里学到的信息然后迁移到 任务B 中. 在多任务学习中, 你是同时开始学习的, 试图让一个神经网络同时做几件事. 然后希望这里的每个任务都能帮到其他所有任务.
假设你正在研究无人驾驶车辆, 那么你的无人驾驶车可能需要同时检测不同的物体. 比如检测行人, 车辆, 停车标志, 交通灯, 等. 所以你的标签不再是简单的 1/0
而是一个 [4, 1]向量
那么你现在做的就是训练一个神经网络, 来预测这些 y 值.
与之前猫分类不同的是, 这次你需要对 j=1 ~ 4 进行求和. 与 softmax 回归不同, softmax 将单个标签分配给单个样本. 这张图片拥有多个不同的标签. 所以说不是每张图片都仅仅是一张行人 / 车 / 停车标识 / 交通灯图片. 你需要知道每张图片是否都有以上这些元素. 多个物体可能同时存在.
以上这些就是建立单个神经网络, 然后解决四个问题. 或者你也可以训练四个网络, 而不是一个网络做四件事. 但是神经网络前面几层的一些低层次特征在识别不同的物体时都可以用到.
那么多任务学习什么时候是有意义的呢? 在以下三种情况下:
- 你训练的一组任务中, 可以公用低层次的特征.
- (通常来说), 如果你的一组任务数据相当接近.
- 训练一个足够大的网络, 那么多任务学习是有意义的.
端到端深度学习(end-to-end deep learning)
之前的数据处理系统他们需要多个阶段的处理. 端到端深度学习就是忽略这些不同的阶段, 使用单个神经网络进行替代.
以语音识别为例子: 你的目标输入是 x 比如说是一段音频, 然后映射到一个输出 y 也就是对应的文本(transcript). 所以传统的语音识别需要很多阶段的处理.
- 首先, 你需要提取一些特征, 一些手工设计的音频特征. 例如 MFCC
- 提取一些低层次特征之后, 应用机器学习算法.在音频片段中找到音位(phonemes, 声音的基本单元).
- 然后将音位串在一起构成独立的词
- 然后得到对应的文本
而端到端的深度学习是, 直接从这段音频输出听写文本. 这可能让有些人难以接受.
端到端深度学习的挑战之一是你可能需要大量的数据才能让系统表现良好.
比如, 如果你只有 3,000 小时的音频数据, 那么可能使用传统的流水线更好.
比如, 如果你拥有 10,000 ~ 100,000 小时的音频数据, 那么端到端方法突然就开始变得厉害了.
是否应该使用端到端学习
- 优势
- 是让数据说话, 使用机器学习能更好的捕获数据中的任何统计信息, 并且不受人类的偏见影响
- 需要手工设计的组件更少, 简化你的设计工作流程.
- 缺点
- 需要大量的数据
- 不过也排除了可能有用的手工设计组件, 排除了将人类知识注入算法的途径(一些组件已经包含了人类总结的知识), 算法的知识来源有两个地方, 一个是数据, 一个是你手工设计的任何东西. 当你有足够的数据时, 可能手工设计的东西就不太重要了. 所以使用端到端训练时, 可能排除了有益的组件, 也有可能避免了有害的组件偏见
所以是否构建端到端的组件, 关键问题在于: 你是否有足够的数据, 能够直接学到足够复杂(complexity)的函数从 x 映射到 y.