一天后编辑… 令我非常惊讶的是,许多人在 Twitter 上分享了这篇文章,更令我高兴的是,我尊敬的一些人提供了非常有帮助且有趣的评论——请查看此处的主题讨论。
我巧妙地在 Twitter 私信对话中“困住”了Smerity,当时他正被困在火车上无事可做,只能回答我的蠢问题,我也成功地获得了他关于语言建模知识的约 0.001%。这些知识应该够我忙活几个月了…… 这次对话的背景是,在我们USF 的深度学习课程“第二版”中,我们正在整理并在一致的 API 中实现一系列深度学习应用中最重要的最佳实践,包括计算机视觉、文本和推荐系统。不幸的是,对于文本应用而言,这些最佳实践并没有真正被收集起来,因此需要 Smerity 的“知识倾泻”。
我想把这次对话的笔记整理成一篇小博客文章,以防其他人也觉得有用。我假设读者熟悉我们慕课第一部分和第二部分涵盖的主题,如 RNN、dropout、注意力模型和神经翻译。我今天也花了一整天在网上搜索其他资源,并在这里加入了我自己的一些研究,所以如果你看到任何蠢的地方,那几乎肯定是我自己的错,而不是 Smerity 的。
PyTorch 代码示例
Smerity 指出了两个优秀的仓库,似乎包含了我们讨论过的所有技术的示例
- AWD-LSTM 语言模型,这是最近发布的一个模型,使用可能在一系列 NLP 问题中都有用的技术,在语言建模的最先进水平上显示出显著改进。它不适用于最新的 PyTorch,不过可能不需要太多调整就能修复。
- 词级语言建模 RNN,一个更简单且非常“古老”(超过 6 个月了!)的语言建模示例,但仍有一些有用的示例代码。
另外两个值得关注的有趣库是
- Practical pytorch 提供了一些不错的简单教程示例,尽管在方法(例如没有测试集!)、性能和偶尔笨拙的代码方面存在一些显著问题。此外,它没有利用 torchtext 库,导致一些冗余代码。但问题选择得很好,描述也很清晰。
- torchtext 是一个虽小但方便的库,用于执行一些基本的文本处理任务,并提供了一些数据集的便捷访问。
获取最先进 (SotA) 结果的技术
在课程的第二部分,我们通过展示如何使用注意力模型、动态教师强制以及当然还有堆叠双向 LSTM,在神经翻译方面达到了相当接近 SotA 的水平。但自我们开发该课程以来,出现了一些有趣的方法,Smerity 建议结合以下技术,可以在不增加太多额外复杂性的情况下,在一系列 NLP 任务中获得最大的提升。
- 我最喜欢的两位研究人员 Dyer 和 Blunsom,以及非凡的 Kaggle、计算机奥林匹克和 Google AI 获胜者 Gabor Melis,发表了《关于神经语言模型评估的最新技术》,该论文整理了一些最佳实践并使用超参数优化展示了 LSTM 的出色结果。
- Smerity 等人最近也发表了一篇论文,整理并结合了最新的 NLP 技术,并在语言建模的最先进水平上取得了巨大的飞跃,论文题为《正则化和优化 LSTM 语言模型》。
- 这篇论文中最重要的补充或许是使用了指针网络,Smerity 等人 (pointer sentinel) 和 Grave 等人 (continuous cache pointer) 都将其扩展到了语言建模。Smerity 在他最新的工作中使用了 continuous cache,并将其描述为:“指针真的真的真的非常简单!你可以将其应用于任何语言模型(LM)的输出,并获得类似的收益。不过这更多是工程上的事情。它的全部内容就是:将 LM 的隐藏状态存储为历史记录(2000 个时间步),生成单词时,使用当前的 LM 隐藏状态计算对该历史记录的注意力,你的单词分布基于你的隐藏状态在过去最相似的位置对应的下一个单词。”
- 在上面提到的 Melis 和 Smerity 的总结论文中,深思熟虑地使用正则化也被证明很重要。Smerity 发现 Dropconnect(这对 CNN 的帮助不如常规 dropout 大)实际上对 RNN 非常有效,仔细想想这很直观…… 用他的话说:“给定一个 RNN,h = Wx + Uh_t-1 + b,你对循环权重矩阵 U 应用 dropout,并在整个前向 + 反向过程中保持不变。简单、快速,并且防止从 h 到 h 到 h 的过拟合……” 他称之为 weight-dropped LSTM,并在最近的语言建模项目中一个非常简洁的类 WeightDrop 中实现了它。
- 有些东西看起来挺明显的,但实际上直到一年前才被写成论文,那就是权重绑定(weight-tying),在《使用输出嵌入改进语言模型》中有所描述。它简单地意味着输出权重和输入嵌入权重是同一个矩阵,在上面的基本语言模型示例中用一行代码(
self.decoder.weight = self.encoder.weight
)就搞定了。 - 最后,Smerity 建议添加“激活正则化(将 LSTM 输出的 L2 范数添加到损失中)和时间激活正则化(将 ht - h_t-1 的 L2 范数添加到损失中)。这只需三行代码的更改,就能让你通过权重绑定接近旧的 SotA。” 这种方法在这篇论文中有所描述。
待解决的问题
NLP 领域中一些有趣的待解决问题,带有有意义的基准,包括
- 情感分析,或类似的标准分类或回归任务,非常适合学习,因为它们与其他分类和回归问题非常相似,所以你可以专注于文本分析问题而不是问题描述本身。而且它们用途广泛。有一个庞大的亚马逊评论数据集可以使用,尽管我不清楚是否有好的基准。而IMDB 评论数据集已被广泛研究,因此有很多好的基准(我们已经在我们的慕课中使用了这个数据集)。任何具有某种类别的文档集也可以使用,例如我们在计算线性代数课程中使用的20 Newsgroups 数据集。(顺便说一句,我不推荐使用斯坦福的情感数据集,因为它既包含短语标注也包含句子标注,这看起来相当人为,而且似乎是为了让研究人员基于树的技术看起来更厉害而设计的。)
- 语言建模,其基本含义是尝试根据句子中的前几个词预测下一个词。其标准基准是“PTB”(Penn Treebank),可在PyTorch 语言建模示例仓库中找到。
- 语言翻译,现在有很多相关的数据集和教程,尽管我认为我们在课程第二部分使用的数据集和方法还不错……
- 文本蕴含(Textual entailment),最好通过斯坦福自然语言推理 (SNLI) 语料库页面上的示例来解释。你会得到成对的句子,需要判断它们是互相支持还是互相矛盾。例如,“一个男人正在检查某个东亚国家的人物的制服”和“这个男人正在睡觉”将被标记为矛盾。除了上述语料库之外,优秀的 Sam Bowman 和朋友们最近还发布了多类型 NLI 语料库;这两个数据集可以结合使用。这是深度学习强大能力的一个很酷的展示,尽管(至少对我来说)还不完全清楚它是否实际有用……
- 文本摘要是目前活跃的研究领域,最近取得了一些重大进展,尽管我还不清楚它在实践中是否有用。
- 许多语言处理工作者将时间花在子任务上,例如词性标注和实体识别,这些结果可以用于更大型的应用。这些特定任务属于序列标注领域的一部分,关于这一点,NLP 研究者 Yoav Goldberg 在 Twitter 上写道:“大量的知识抽取任务可以建模为序列标注。它是一个‘杀手级应用’。”