接触深度学习四年来,大概工作中有六成以上的时间都在写模型/调模型/分析模型为什么好或不好。这个过程中总结来一些经验, 特此记录。
由于现在还在做相关工作,这篇文章可能后续还会不断更新。
切实有效的评价指标
一个例子,asr 效果优化任务中,需要针对不同领域进行测试。假如现在有六个不同的测试集, 希望模型能在这六个测试集上都有好的表现从而对其分别测试 wer。但领域不同导致数据集规模差别较大 (例如模某些领域只有很小的测试集,却同样重要)。 在每次模型效果迭代时,我们采用这样的判据:若六个测试集中四个 wer 降低,则说明新模型更好。
这是一个正确的做法吗?
结论:是不对的。这个标准不具备传递性,很容易构造反例,出现A<B, B<C, C<A的情况。 (例如7.0/7.0/7.0/7.0/7.0/7.0 -> 6.9/6.9/6.9/6.9/7.3/7.3 -> 7.2/7.2/6.8/6.8/7.2/7.2 -> 7.1/7.1/7.1/7.1/7.1/7.1/)
每次迭代都有一多半测试集效果变好了,但几个周期后,模型效果反而不如最开始的版本了。这种情况下,也许用一个加权平均测试 wer 是个更好但选择。
对于有明确指标的 asr 尚且如此,那对 TTS/DS/VC 这种以 mos 为主要评价指标的问题更需谨慎小心。
另一个例子,之前在tts上的惨痛教训。每次模型的迭代时候,在少数几条样本上进行 ABtest 对比,每次汇报都提升了一点点。 但经过了六个月迭代后,发现模型总效果几乎没提升。是不是和之前 asr 的例子有一点像?
不要在测试集上调参
看上去道理简单通俗易懂,但不小心还是会经常犯错。
一个例子,asr 声学模型优化过程中,A/B/C 三个模型,通过一个测试集进行判断,选择 wer 最小的用于上线。
这是一个正确的做法吗?
结论:不正确。不同模型可以认为是不同的超参,犯了在测试集上调参的错误。 因此,不能仅凭一组实验,简单得出不同模型/方法之间的优劣。
注意模型本身的效果波动
神经网络模型由于 dropout 和参数随机初始化等因素,每次训练的效果可能有微小波动。需要了解模型效果的置信区间。
一个例子, asr 声学模型优化过程中,模型a的wer指标优于b 0.05%, 但模型两次训练精度误差有0.5%, 模型提升的结论可信吗?
显然不可信。
重复说,了解结果的置信区间很重要(就像tts评分中总是尽量给出 mos 的置信区间。)
方法应该对训练数据鲁棒
如果一个方法是有效的,那么应该对应用场景大部分数据有效。好的模型应该”不太挑”数据。
小心特征泄漏
刚开始学习机器学习时候,经常会由于不小心把标签信息混入训练数据中,从而得到 “相当出色” 的测试效果。
但类似的问题,有时会隐蔽的发生而不易察觉。
一个例子,语音情感分类,总数据有 20 个说话人,每个说话人有20x5条数据(5个情感标签,每个标签20句), 我们对这2000条数据进行shuffle后,取5%做为测试集,这是一个正确的操作吗?
不正确,也许并不是很显然,但实践经验表明,如果测试样本对应说话人在训练数据中见过,分类准确率会大幅度提升。
依据说话人做 shuffle,划分测试集可能是一个更好的做法。
有一些类似说话人之类的隐性特征不容易被注意到。
调参并不重要
实际做项目不是比赛,80%和82%差别并没有那么重要。绝大多数调参技巧对结果提升相当有限, 如果一个模型对参数很敏感,通过反复调参才能达到产品要求,那这多半不是一个好对模型。尤其是考虑到之前提到模型对训练集鲁棒性, 每次增加数据或更换领域,整个模型表现都变得不可预知。
这是一场灾难。
事实上,大多数语音任务,因为其训练数据多训练时间久,我们不太花时间和精力调参,只是在卡有空余的时候跑一下。
以上,收录了语音算法任务中和模型调参相关中一些常见的错误。看上去平常的描述,其实每一条都有血的教训。 一个方法论层面的错误往往会导致高达数个月的徒劳。适时总结,才能避免少走弯路。