高性能算法的四大实战技巧 | 算法经验(12)

2020-08-04 10:49:09 浏览数 (1)

0.来源说明

作者:Jason Brownlee

出处:Machine Learning Mastery

1.Ideas to Improve Algorithm Performance

提升算法性能的四种主要方法:更多数据、更好的算法、更好的调参、更好的组装。

  1. Improve Performance With Data.
  2. Improve Performance With Algorithms.
  3. Improve Performance With Algorithm Tuning.
  4. Improve Performance With Ensembles.

2.Improve Performance With Data

性能提升的力度按上表的顺序从上到下依次递减。举个例子,新的建模方法或者更多的数据带来的效果提升往往好于调出最优的参数。但这并不是绝对的,只是大多数情况下如此。

  1. Get More Data.
  2. Invent More Data.
  3. Rescale Your Data.
  4. Transform Your Data.
  5. Feature Selection.

1)Get More Data

模型的质量往往取决于你的训练数据的质量。需要确保使用的数据是针对问题最有效的数据。

深度学习和其它现代的非线性机器学习模型在大数据集上的效果更好,尤其是深度学习。这也是深度学习方法令人兴奋的主要原因之一。

2)Invent More Data

如果由于某些原因你得不到更多的数据,也可以制造一些数据。

  • If your data are vectors of numbers, create randomly modified versions of existing vectors.
  • If your data are images, create randomly modified versions of existing images.
  • If your data are text,you get the idea.

这类做法通常被称为数据扩展或是数据生成。你可以使用生成模型,也可以用一些简单的小技巧。

举个例子,若是用图像数据,简单地随机选择和平移已有的图像就能取得很大的提升。它能提升模型的泛化能力,如果新的数据中包含这类变换就能得到很好的处理。有时候是往数据中增加噪声,这相当于是一种规则方法,避免过拟合训练数据。

3)Rescale Your Data

使用神经网络模型的一条经验法宝就是: 将数据缩放到激活函数的阈值范围。

如果你使用sigmoid激活函数,将数据缩放到0~1之间。如果选用tanh激活函数,将值域控制在-1~1之间。

输入、输出数据都经过同样的变换。比如,如果在输出层有一个sigmoid函数将输出值转换为二值数据,则将输出的y归一化为二进制。如果选用的是softmax函数,对y进行归一化还是有效的。

建议你将训练数据扩展生成多个不同的版本:

  • Normalized to 0 to 1.
  • Rescaled to -1 to 1.
  • Standardized.

然后在每个数据集上测试模型的性能,选用最好的一组生成数据。 如果更换了激活函数,最好重复做一次这个小实验。 在模型中不适合计算大的数值。此外,还有许多其它方法来压缩模型中的数据,比如对权重和激活值做归一化。

4)Transform Your Data

与上一节的方法相关,但是需要更多的工作量。你必须真正了解所用到的数据。数据可视化,然后挑出异常值。 先猜测每一列数据的分布:

  • Does a column look like a skewed Gaussian, consider adjusting the skew with a Box-Cox transform.
  • Does a column look like an exponential distribution, consider a log transform.
  • Does a column look like it has some features, but they are being clobbered by something obvious, try squaring, or square-rooting.
  • Can you make a feature discrete or binned in some way to better emphasize some feature.

Lean on your intuition. Try things:

  • Can you pre-process data with a projection method like PCA?
  • Can you aggregate multiple attributes into a single value?
  • Can you expose some interesting aspect of the problem with a new boolean flag?
  • Can you explore temporal or other structure in some other way?

神经网络有特征学习的功能,它们能够完成这些事情。不过你若是可以将问题的结构更好地呈现出来,网络模型学习的速度就会更快。在训练集上快速尝试各种变换方法,看看哪些方法有些,而哪些不起作用。

5) Feature Selection

神经网络受不相关数据的影响很小。它们会对此赋予一个趋近于0的权重,几乎忽略此特征对预测值的贡献。

是否可以移除训练数据的某些属性呢?

我们有许多的特征选择方法和特征重要性方法来鉴别哪些特征可以保留,哪些特征需要移除。

如果你的时间充裕,我还是建议在相同的神经网络模型上选择尝试多个方法,看看它们的效果分别如何。

  • 也许用更少的特征也能得到同样的、甚至更好的效果。
  • 也许所有的特征选择方法都选择抛弃同一部分特征属性。那么就真应该好好审视这些无用的特征。
  • 也许选出的这部分特征给你带来了新的启发,构建出更多的新特征。

6) Reframe Your Problem

在回到你问题的定义上来。

你所收集到的这些观测数据是描述问题的唯一途径吗?

也许还有其它的途径。也许其它途径能更清晰地将问题的结构暴露出来。

我自己非常喜欢这种练习,因为它强迫我们拓宽思路。很难做好。尤其是当你已经投入大量的时间、精力、金钱在现有的方法上。

即使你列举了3 ~ 5种不同的方式,至少你对最后所选用的方式有充足的信心。

也许你可以将时间元素融入到一个窗口之中

也许你的分类问题可以转化为回归问题,反之亦然

也许可以把二值类型的输出转化为softmax的输出

也许你可以对子问题建模

深入思考问题是一个好习惯,最好在选择工具下手之前先完成上述步骤,以减少无效的精力投入。

无论如何,如果你正束手无策,这个简单的连续能让你思如泉涌。

另外,你也不必抛弃前期的大量工作,详情可以参见后面的章节。

3. Improve Performance With Algorithms

机器学习总是与算法相关。

所有的理论和数学知识都在描述从数据中学习决策过程的不同方法(如果我们这里仅讨论预测模型)。

你选用深度学习来求解,它是不是最合适的技术呢?

在这一节中,我们会简单地聊一下算法的选择,后续内容会具体介绍如何提升深度学习的效果。

下面是概览:

· Spot-Check Algorithms.

· Steal From Literature.

· Resampling Methods.

1) Spot-Check Algorithms

你事先不可能知道哪种算法对你的问题效果最好。

如果你已经知道,你可能也就不需要机器学习了。你有哪些证据可以证明现在已经采用的方法是最佳选择呢?我们来想想这个难题。当在所有可能出现的问题上进行效果评测时,没有哪一项单独的算法效果会好于其它算法。所有的算法都是平等的。这就是天下没有免费的午餐理论的要点。

也许你选择的算法并不是最适合你的问题。 现在,我们不指望解决所有的问题,但当前的热门算法也许并不适合你的数据集。我的建议是先收集证据,先假设有其它的合适算法适用于你的问题。 筛选一些常用的算法,挑出其中适用的几个。

· Evaluate some linearmethods like logistic regression andlinear discriminate analysis.

· Evaluate some treemethods like CART, Random Forest and Gradient Boosting.

· Evaluate some instancemethods like SVM and KNN.

· Evaluate some otherneural network methods like LVQ, MLP, CNN, LSTM, hybrids, etc.

采纳效果较好的几种方法,然后精细调解参数和数据来进一步提升效果。 将你所选用的深度学习方法与上述这些方法比较,看看是否能击败他们? 也许你可以放弃深度学习模型转而选择更简单模型,训练的速度也会更快,而且模型易于理解。

2) Steal From Literature

从文献中“借鉴”思路是一条捷径。其它人是否已经做过和你类似的问题,他们使用的是什么方法。阅读论文、书籍、问答网站、教程以及Google给你提供的一切信息。记下所有的思路,然后沿着这些方向继续探索。这并不是重复研究,这是帮助你发现新的思路。优先选择已经发表的论文已经有许多的聪明人写下了很多有意思的事情。利用好这宝贵的资源吧。

3) Resampling Methods

你必须明白自己模型的效果如何?你估计的模型效果是否可靠呢? 深度学习模型的训练速度很慢。 这就意味着我们不能用标准的黄金法则来评判模型的效果,比如k折交叉验证。

· 也许你只是简单地把数据分为训练集和测试集。如果是这样,就需要保证切分后 的数据分布保持不变。单变量统计和数据可视化是不错的方法。

· 也许你们可以扩展硬件来提升效果。举个例子,如果你有一个集群或是AWS的账号,我们可以并行训练n个模型,然后选用它们的均值和方差来获取更稳定的效果。

· 也许你可以选择一部分数据做交叉验证(对于early stopping非常有效)。

· 也许你可以完全独立地保留一部分数据用于模型的验证。

另一方面,也可以让数据集变得更小,采用更强的重采样方法。

也许你会看到在采样后的数据集上训练得到的模型效果与在全体数据集上训练得到的效果有很强的相关性。那么,你就可以用小数据集进行模型的选择,然后把最终选定的方法应用于全体数据集上。也许你可以任意限制数据集的规模,采样一部分数据,用它们完成所有的训练任务。

4. Improve Performance With Algorithm Tuning

你通过算法筛选往往总能找出一到两个效果不错的算法。但想要达到这些算法的最佳状态需要耗费数日、数周甚至数月。

下面是一些想法,在调参时能有助于提升算法的性能。

1. Diagnostics.

2. Weight Initialization.

3. Learning Rate.

4. Activation Functions.

5. Network Topology.

6. Batches and Epochs.

7. Regularization.

8. Optimization and Loss.

9. Early Stopping.

你可能需要指定参数来多次(3-10次甚至更多)训练模型,以得到预计效果最好的一组参数。对每个参数都要不断的尝试。

1) Diagnostics

只有知道为何模型的性能不再有提升了,才能达到最好的效果。 是因为模型过拟合呢,还是欠拟合呢? 千万牢记这个问题。

模型总是处于这两种状态之间,只是程度不同罢了。

一种快速查看模型性能的方法就是每一步计算模型在训练集和验证集上的表现,将结果绘制成图表。

在训练集和验证集上测试模型的准确率:

  • 如果训练集的效果好于验证集,说明可能存在过拟合的现象,试一试增加正则项。
  • 如果训练集和验证集的准确率都很低,说明可能存在欠拟合,你可以继续提升模型的能力,延长训练步骤。
  • 如果训练集和验证集的曲线有一个焦点,可能需要用到Eearly stopping的技巧了。

经常绘制类似的图表,深入研究并比较不同的方法,以提高模型的性能。

这些图表也许是你最有价值的诊断工具。 另一种有效的诊断方法是研究模型正确预测或是错误预测的样本。

在某些场景下,这种方法能给你提供一些思路。

  • 也许你需要更多的难预测的样本数据
  • 也许你可以从训练集中删去那些容易被学习的样本
  • 也许你可以有针对性地对不同类型的输入数据训练不同的模型

2) Weight Initialization.

有一条经验规则:用小的随机数初始化权重。 事实上,这可能已经足够了。但是这是你网络模型的最佳选择吗? 不同的激活函数也可以有不同的应对策略,但我不记得在实践中存在什么显著的差异。 保持你的模型结构不变,试一试不同的初始化策略。 记住,权重值就是你模型需要训练的参数。几组不同的权重值都能取得不错的效果,但你想得到更好的效果。

  • 尝试所有的初始化方法,找出最好的一组初始化值
  • 试一试用非监督式方法预学习,比如自动编码机
  • 尝试用一组现有的模型权重参数,然后重新训练输入和输出层(迁移学习)

记住,修改权重初始化值的方法与修改激活函数或者目标函数的效果相当

3) Learning Rate.

调节学习率也能带来效果提升。 这里也有一些探索的思路:

  • 尝试非常大、非常小的学习率
  • 根据参考文献,在常规值附近用网格化搜索
  • 尝试使用逐步减小的学习率
  • 尝试每隔固定训练步骤衰减的学习率
  • 尝试增加一个向量值,然后用网格搜索

大的网络模型需要更多的训练步骤,反之亦然。如果你添加了更多的神经节点和网络层,请加大学习率。 学习率与训练步骤、batch大小和优化方法都有耦合关系。

4) Activation Functions

也许你应该选用ReLU激活函数。仅仅因为它们的效果更好。

在ReLU之前流行sigmoid和tanh,然后是输出层的softmax、线性和sigmoid函数。除此之外,我不建议尝试其它的选择。

这三种函数都试一试,记得把输入数据归一化到它们的值域范围。

显然,你需要根据输出内容的形式选择转移函数。

比方说,将二值分类的sigmoid函数改为回归问题的线性函数,然后对输出值进行再处理。同时,可能需要调整合适的损失函数。在数据转换章节去寻找更多的思路吧。

5) Network Topology

Changes to your network structure will pay off.How many layers and how many neurons do you need?No one knows. No one. Don’t ask.You must discover a good configuration for your problem. Experiment.

  • Try one hidden layer with a lot of neurons (wide).
  • Try a deep network with few neurons per layer (deep).
  • Try combinations of the above.
  • Try architectures from recent papers on problems similar to yours.
  • Try topology patterns (fan out then in) and rules of thumb from books and papers (see links below).

这是一个难题。越大的网络模型有越强的表达能力,也许你就需要这样一个。 更多层的结构提供了抽象特征的更多结构化组合的可能,也许你也需要这样一个网络。 后期的网络模型需要更多的训练过程,需要不断地调节训练步长和学习率。

6) batch & epoch

batch的大小决定了梯度值,以及权重更新的频率一个epoch指的是训练集的所有样本都参与了一轮训练,以batch为序。

你尝试过不同的batch大小和epoch的次数吗?

在前文中,我们已经讨论了学习率、网络大小和epoch次数的关系。

深度学习模型常用小的batch和大的epoch以及反复多次的训练。

这或许对你的问题会有帮助。

  • 尝试将batch大小设置为全体训练集的大小(batch learning)
  • 尝试将batch大小设置为1(online learning)
  • 用网格搜索尝试不同大小的mini-batch(8,16,32,…)
  • 尝试再训练几轮epoch,然后继续训练很多轮epoch

Consider a near infinite number of epochs and setup check-pointing to capture the best performing model seen so far, see more on this further down.Some network architectures are more sensitive than others to batch size. I see Multilayer Perceptrons as often robust to batch size, whereas LSTM and CNNs quite sensitive, but that is just anecdotal.

7) Regularization

正则化是克服训练数据过拟合的好方法。最近热门的正则化方法是dropout,你试过吗? Dropout方法在训练过程中随机地略过一些神经节点,强制让同一层的其它节点接管。简单却有效的方法。

  • 权重衰减来惩罚大的权重值
  • 激活限制来惩罚大的激活函数值

尝试用各种惩罚措施和惩罚项进行实验,比如L1、L2和两者之和。

8) Optimization and Loss

以往主要的求解方法是随机梯度下降,然而现在有许许多多的优化器。

你尝试过不同的优化策略吗? 随机梯度下降是默认的方法。先用它得到一个结果,然后调节不同的学习率、动量值进行优化。 许多更高级的优化方法都用到更多的参数,结构更复杂,收敛速度更快。这取决于你的问题,各有利弊吧。

为了压榨现有方法的更多潜力,你真的需要深入钻研每个参数,然后用网格搜索法测试不同的取值。过程很艰辛,很花时间,但值得去尝试。

我发现更新/更流行的方法收敛速度更快,能够快速了解某个网络拓扑的潜力,例如:

  • ADAM
  • RMSprop

你也可以探索其它的优化算法,例如更传统的算法(Levenberg-Marquardt)和比较新的算法(基因算法)。其它方法能给SGD创造好的开端,便于后续调优。 待优化的损失函数则与你需要解决的问题更相关。

不过,也有一些常用的伎俩(比如回归问题常用MSE和MAE),换个损失函数有时也会带来意外收获。同样,这可能也与你输入数据的尺度以及所使用的激活函数相关。

  • 梯度下降优化算法概览
  • 什么是共轭梯度和Levenberg-Marquardt?
  • 深度学习的优化方法,2011

5. Improve Performance With Ensembles

你可以将多个模型的预测结果融合。继模型调优之后,这是另一个大的提升领域。 事实上,往往将几个效果还可以的模型的预测结果融合,取得的效果要比多个精细调优的模型分别预测的效果好

我们来看一下模型融合的三个主要方向:

  • Combine Models.
  • Combine Views.
  • Stacking.

1) Combine Models

不必挑选出一个模型,而是将它们集成

如果你训练了多个深度学习模型,每一个的效果都不错,则将它们的预测结果取均值。 模型的差异越大,效果越好。举个例子,你可以使用差异很大的网络拓扑和技巧。 如果每个模型都独立且有效,那么集成后的结果效果更稳定。

相反的,你也可以反过来做实验。 每次训练网络模型时,都以不同的方式初始化,最后的权重也收敛到不同的值。多次重复这个过程生成多个网络模型,然后集成这些模型的预测结果。 它们的预测结果会高度相关,但对于比较难预测的样本也许会有一点提升。

2) Combine Views

如上一节提到的,以不同的角度来训练模型,或是重新刻画问题。

我们的目的还是得到有用的模型,但是方式不同(如不相关的预测结果)。

你可以根据上文中提到的方法,对训练数据采取完全不同的缩放和变换技巧。

所选用的变化方式和问题的刻画角度差异越大,效果提升的可能性也越大。

简单地对预测结果取均值是一个不错的方式。

3)stacking

你还可以学习如何将各个模型的预测结果相融合

这被称作是stacked泛化,或者简称为stacking。

通常,可以用简单的线性回归的方式学习各个模型预测值的权重。

把各个模型预测结果取均值的方法作为baseline,用带权重的融合作为实验组。

  • Stacked Generalization (Stacking)

|中文链接:https://mp.weixin.qq.com/s/3xImPz9v14jptmuQH2gJkg

|英文链接:https://machinelearningmastery.com/improve-deep-learning-performance/

0 人点赞