Deep Learning Book 学习笔记(11)

Practical Methodology

Posted by Wenlong Shen on May 19, 2018

实践是检验真理的唯一标准

常见的一个设计是:确定目标、建立流程、搭建系统、优化改进。

性能度量

确定目标,即使用什么误差度量,是必要的第一步,确定了改进哪个性能度量,然后专心提高性能度量。如果没有明确的目标,那么我们很难判断机器学习系统上的改动是否有所改进。值得注意的是对于大多数应用而言,不可能实现绝对零误差。即使你有无限的训练数据,并且恢复了真正的概率分布,贝叶斯误差仍定义了能达到的最小错误率。这是因为输入特征可能无法包含输出变量的完整信息,或是因为系统可能本质上是随机的。当然我们还会受限于有限的训练数据。

默认的基准模型

确定性能度量和目标后,任何实际应用的下一步是尽快建立一个合理的端到端的系统。根据问题的复杂性,项目开始时可能无需使用深度学习。如果只需正确地选择几个线性权重就可能解决问题,那么项目可以开始于一个简单的统计模型,如逻辑回归。如果问题属于“AI-完全”类的,如对象识别、语音识别、机器翻译等等,那么项目开始于一个合适的深度学习模型,效果会比较好。

决定是否收集更多数据

在建立第一个端到端的系统后,就可以度量算法性能并决定如何改进算法。许多机器学习新手都忍不住尝试很多不同的算法来进行改进。然而,收集更多的数据往往比改进学习算法要有用得多。怎样判断是否要收集更多的数据?首先,确定训练集上的性能是否可接受。如果模型在训练集上的性能就很差,学习算法都不能在训练集上学习出良好的模型,那么就没必要收集更多的数据。反之,可以尝试增加更多的网络层或每层增加更多的隐藏单元,以增加模型的规模。此外,也可以尝试调整学习率等超参数的措施来改进学习算法。如果更大的模型和仔细调试的优化算法效果不佳,那么问题可能源自训练数据的质量。数据可能含太多噪声,或是可能不包含预测输出所需的正确输入。这意味着我们需要重新开始,收集更干净的数据或是收集特征更丰富的数据集。

选择超参数

大部分深度学习算法都有许多超参数来控制不同方面的算法表现。有些超参数会影响算法运行的时间和存储成本。有些超参数会影响学习到的模型质量,以及在新输入上推断正确结果的能力。有两种选择超参数的基本方法:手动选择和自动选择。手动选择超参数需要了解超参数做了些什么,以及机器学习模型如何才能取得良好的泛化。自动选择超参数算法大大减少了解这些想法的需要,但它们往往需要更高的计算成本。

手动设置超参数,就必须了解超参数、训练误差、泛化误差和计算资源(内存和运行时间)之间的关系。下表列出一些超参数对模型容量的影响:

超参数 容量何时增加 原因 注意事项
隐藏单元数量 增加 增加隐藏单元数量会增加模型的表示能力。 几乎模型每个操作所需的时间和内存代价都会随隐藏单元数量的增加而增加。
学习率 调至最优 不正确的学习速率,不管是太高还是太低都会由于优化失败而导致低有效容量的模型。  
卷积核宽度 增加 增加卷积核宽度会增加模型的参数数量。 较宽的卷积核导致较窄的输出尺寸,除非使用隐式零填充减少此影响,否则会降低模型容量。较宽的卷积核需要更多的内存存储参数,并会增加运行时间,但较窄的输出会降低内存代价。
隐式零填充 增加 在卷积之前隐式添加零能保持较大尺寸的表示。 大多数操作的时间和内存代价会增加。
权重衰减系数 降低 降低权重衰减系数使得模型参数可以自由地变大。  
Dropout比率 降低 较少地丢弃单元可以更多地让单元彼此“协力”来适应训练集。  

理想的学习算法应该是只需要输入一个数据集,就可以输出学习的函数,而不需要手动调整超参数。考虑手动设置超参数的过程,我们可以设计封装学习算法的超参数优化算法。

当有三个或更少的超参数时,常见的超参数搜索方法是网格搜索(grid search)。对于每个超参数,使用者选择一个较小的有限值集去探索。然后,这些超参数笛卡尔乘积得到一组组超参数,网格搜索使用每组超参数训练模型。挑选验证集误差最小的超参数作为最好的超参数。网格搜索带来的一个明显问题是,计算代价会随着超参数数量呈指数级增长。

一个替代网格搜索的方法是随机搜索。我们为每个超参数定义一个边缘分布,当有几个超参数对性能度量没有显著影响时,随机搜索相比于网格搜索指数级地高效。

超参数搜索问题可以转化为一个优化问题。决策变量是超参数。优化的代价是超参数训练出来的模型在验证集上的误差。在简化的设定下,可以计算验证集上可导误差函数关于超参数的梯度,然后我们遵循这个梯度更新。不过,在大多数实际设定中,这个梯度是不可用的。这可能是因为其高额的计算代价和存储成本,也可能是因为验证集误差在超参数上本质上不可导,例如超参数是离散值的情况。

调试策略

当一个机器学习系统效果不好时,通常很难判断效果不好的原因是算法本身,还是算法实现错误。由于各种原因,机器学习系统很难调试。在大多数情况下,我们不能提前知道算法的行为。事实上,使用机器学习的整个出发点是,它会发现一些我们自己无法发现的有用行为。比如,我们在一个新的分类任务上训练一个神经网络,它达到5%的测试误差,我们没法直接知道这是期望的结果,还是次优的结果。另一个难点是,大部分机器学习模型有多个自适应的部分。如果一个部分失效了,其他部分仍然可以自适应,并获得大致可接受的性能。大部分神经网络的调试策略都是解决这两个难题的一个或两个。我们可以设计一种足够简单的情况,能够提前得到正确结果,判断模型预测是否与之相符;我们也可以设计一个测试,独立检查神经网络实现的各个部分。