通过嵌入隐层表征来理解神经网络

本文为 AI 研习社编译的技术博客,原标题 Understanding Neural Networks by embedding hidden representations,作者为 Rakesh Chada。

翻译 | 姚秀清  叶青       整理 |  凡江

通过嵌入隐层表征来理解神经网络

https://rakeshchada.github.io/Neural-Embedding-Animation.html 交叉发布。

可视化神经网络总是很有趣的。例如,我们通过神经元激活的可视化揭露了令人着迷的内部实现。对于监督学习的设置,神经网络的训练过程可以被认为是将一组输入数据点变换为可由线性分类器分离而表示的函数。所以,这一次,我打算通过利用这些(隐藏的)的表示来产生可视化,从而为这个训练过程带来更多内部细节。这种可视化可以揭示和神经网络性能相关的有趣的内部细节。

我集思广益了几个想法,最终从优秀的 Andrej Karpathy 的工作中获得了很好的灵感。

这个想法很简单,可以在下面的步骤中简要说明:

  1. 训练一个训练网络。

  2. 一旦训练完成,就为验证/测试数据中的每个数据点生成最终的隐藏表示(嵌入)。这种隐藏的表示基本上是神经网络中最后一层的权重。这种表示是神经网络对数据进行分类的一种近似表示。

  3. 出于可视化目的,将这些权重的维度降低为 2-D 或 3-D。然后,在散点图上可视化这些点,以查看它们在空间中的分离情况。我们可以使用流行的降维技术,例如 T-SNE 或 UMAP。

虽然上面的插图显示了训练结束后的数据点,但我认为训练过程中在多个点上对数据点进行可视化是一个有趣的扩展。然后,可以单独检查每个可视化,并获得相关数据如何变化的一些细节。例如,我们可以在每个 epoch 之后产生一个这样的可视化,直到训练完成,并看看它们如何比较。对此的进一步扩展将是产生这些可视化的动画。这可以通过采用这些数据点的静态可视化并在它们之间插入点来完成–从而引起逐点过渡。

这个想法让我很兴奋,于是我继续开发了基于 D3.js 的 Javascript 工具,使我们能够生成这些可视化。它允许我们生成静态可视化和动画。对于动画,我们需要上传两个包含我们想要比较的隐藏表示的 csv 文件,并且可以为这些文件设置动画。我们还可以控制动画,因此我们可以观察到一组特定数据点在训练过程中如何移动。

链接到工具:神经嵌入动画生成器https://bl.ocks.org/rakeshchada/raw/43532fc344082fc1c5d4530110817306/

工具的说明文档:README https://bl.ocks.org/rakeshchada/43532fc344082fc1c5d4530110817306

这绝不是一个复杂的工具。我只是想快速可视化我的一些想法。

动画可视化的一大特色 — 我应该提前说明 — 在执行 T-SNE/UMAP 之后会出现每个 2-D/3-D 表示中的不一致性。首先,在设置超参数、随机种子等时必须格外小心。其次,据我所知,T-SNE 只是试图嵌入类似物体出现在附近而将不同物体在远处分开。因此,当我们对两个可视化进行动画处理时,比如 epoch1 和 epoch2,可能不容易区分纯随机性引起的变化与来自神经网络实际学习的权重变化。也就是说,在我的实验中,我有时能够制作合理的动画,帮助我获得有趣的见解。

此可视化框架有多个有趣的应用程序,以下是分类问题的一些背景:

  • 更好地理解模型的行为 w.r.t 数据 

  • 了解神经网络训练过程中数据表示的变化

  • 比较给定数据集上的模型 – 包括超参数变化甚至架构变化

  • 了解嵌入在训练过程中如何及时(在调整时)发生变化 

本文的其余部分通过具体的示例说明了上述背景。

更好地理解模型的行为 w.r.t 数据

恶意评论分类任务

我们在这里使用的第一个例子是来自 Kaggle 的这个有趣的自然语言处理竞赛,当时我正在开发这个工具。目标是将文本评论分为不同类别 – 有毒,淫秽,威胁,侮辱等。这是一个多标签分类问题。

在神经网络模型中,我尝试了几种架构,从简单的(没有卷积/重复的前馈神经网络)到复杂的架构。我在神经网络的最后一层使用了二进制交叉熵损失和 sigmoid 激活。这样 — 它只为每个标签输出两个概率 — 从而实现多标签分类。我们将使用来自双向 LSTM 的隐藏表示,该双向 LSTM 使用未经训练的预训练词嵌入进行初始化,来完成此次演示。

所以我做了上述相同的步骤 — 从最后一层提取验证集中的每个文本注释的隐藏表示,到执行 T-SNE/UMAP 将它们缩小到 2 维并使用该工具可视化它们。在停止之前每个训练持续了 5 个 epoch。使用 UMAP 的一个优点是它的速度提高了一个数量级,并且仍能产生高质量的表现。谷歌确实发布了实时 TSNE,但我还没有去探索。

这是在第 5 个 epoch 结束时可视化的放大版本。可视化的类是侮辱。所以红点是侮辱,绿点是非侮辱。

通过嵌入隐层表征来理解神经网络

关于恶意评论分类任务的第 5 个 epoch 后的隐藏表示。

让我们从一个有趣的地方开始,看看上面蓝色箭头指向的两个点。其中一个是侮辱,另一个则不是。文本说了什么?

文本 1(带蓝色箭头的绿点):「废话废话废话废话废话废话」。

文本 2(带蓝色箭头的红点):「我讨厌你我讨厌你我讨厌你我讨厌你我讨厌你我讨厌你我恨你」。

模型如何将两个重复的文本放在一起,这很有趣。而且侮辱的概念在这里似乎很微妙!

我也好奇地看着红色星团中心的一些绿点。为什么模型会对它们感到困惑?他们的文本会是什么样的?例如,这是上图中黑色箭头指向的点的文字:

「不要把我称为麻烦制造者,你和他一样,你就像 XYZ 一样是种族主义的右翼分子」(审查和名称遗漏是我的 — 他们在文本中不存在)。

嗯,这似乎是一种侮辱 — 所以它看起来像一个糟糕的标签!应该用一个红点代替!

可能并非所有这些错位都是坏标签,但如上所述,我们可以通过可视化深入挖掘数据的所有这些特征。

我也认为这有助于我们找到诸如标记化/预处理之类的事物对模型性能的影响。在上面的文本 2 中,如果有适当的标点符号,它可能对模型有所帮助 — 在每次」讨厌你「之后可能是一个句号。还有其他一些例子,我认为大写可能有所帮助。

Yelp 审查情绪分类任务

我还想在不同的数据集上尝试这种方法。所以我选择了来自 Kaggle 的 yelp 评论数据集并决定实现一个简单的情绪分类器。我将星级评分转换为二进制 — 使事情变得更容易一些。所以 — 1,2 和 3 星是负面的,4 星,5 星是积极的评论。同样,我从一个简单的前馈神经网络架构开始,该架构对嵌入进行操作,展平它们,发送给全连接层并输出概率。这是 NLP 分类任务的非常规架构 — 但我很想知道它是如何做的。在提前停止前我们完成了 10 个 epoch 的训练。

这是最后一个 epoch 可视化的内容:

通过嵌入隐层表征来理解神经网络

yelp 二元情绪分类任务在第 10 个 epoch 之后的隐藏表示。

黑色箭头指出的文字说:

每次去这里的时候,食物一直很美味。不幸的是服务不是很好。所以我再次光顾只是因为我喜欢这里的食物。

它看起来像个中性的评价甚至更倾向于积极面。所以模型把这个点归类在积极类也不是毫无道理。此外,这个模型将每个单词单独处理(没有 n-gram 模型),这可能解释了为什么模型会漏掉上面「不太好」中的「不」字之类的东西。下面是与上述负面点最接近的积极点的文本。

“喜欢这个地方。 简单的拉面与非常基本的菜单,但总是有美味和优质的服务相伴。 价格合理,气氛优雅。 绝对将其归类为附近的精品店。“

模型将上面的两个文本置于非常接近空间的事实可能重新证实了模型的局限性(诸如不捕获 n-gram 之类的东西)。

 我有时想象这种分析可以帮助我们理解哪些例子对于模型来说是「困难」vs「简单」。可以通过对比错误分类的点和它们附近的点来理解这个问题。一旦我们有了一些理解,我们就可以使用这些知识来添加更多个性化的功能,以帮助模型更好地理解这些示例,或者更改模型的结构以便更好地理解那些「困难」示例。   

了解神经网络训练过程中数据表示的演变

我们将使用动画来理解这一点。我通常理解动画可视化的方式是选择一个点的子集并观察他们的邻域如何在训练过程中发生变化。我想象当神经网络逐渐学习时,邻域变得越来越代表手头进行的分类任务。或者换句话说,如果我们定义相对于分类任务的相似性,那么当网络学习时,类似的点将在空间中越来越接近。上面工具中的滑块可帮助我们控制动画,同时密切关注一组点的变化。

下面的动画显示了在毒性评论分类任务中,数据的隐藏表示如何在 4 个 epoch(第 2-5 个 epoch)的过程中进化。我选择了一小组点,因此很容易观察它们是如何移动的。绿点代表无毒类,红点代表有毒类。

通过嵌入隐层表征来理解神经网络

第 2-5 epoch 中隐藏表示的动画

有一些点对(如 F 和 G 、 C 和 I)在四处舞动,而另一些点对(如 D 和 K、 N 和 O)始终离的很近。

因此,当我手动查看与这些点相对应的句子时,我有时可以了解到那个 epoch 神经网络可能学到了什么。如果我看到两个完全不相关的句子靠近在一起(例如,在 epoch2 中的 E 和 F),那么我想模型还需要再进行一些学习。我有时会看到神经网络将有相似的单词的句子放在一起 – 尽管整个句子的含义是不同的。我确实看到这种影响随着训练的进行(验证损失减少)逐渐消失。

正如帖子开头所提到的,这种行为并不能保证一致。 绝对存在一些时候一个点的邻域根本没有任何意义。 但我确实希望 – 通过制作这些动画 – 并注意点数运动的任何显着变化,我们将能够得出一些有用的见解。

我还使用yelp数据集重复了相同的实验并发现了类似的东西。

在训练了一个 epoch 以后的神经网络是这样的:

通过嵌入隐层表征来理解神经网络

Yelp – epoch 1之后的表示(绿色为积极情绪,红色为负面情绪)

这两个类之间有很多重叠,网络还没有真正学会一个清晰的边界。 

以下一个动画,表示在 5 个 epoch 训练之后表现形式的演变:

通过嵌入隐层表征来理解神经网络

Yelp – epoch1 到 5 中隐藏表示的动画

你可以看到两类点在各自的类方面变得更密集,并且网络在分离这两个类方面做得更好。

旁注:我现在做的动画是为了表示 epoch 之间代表性变化。但是没有理由表示人们不可以进一步细化 – 比如使用迷你批次或半个 epoch 或者其他的。这可能有助于发现更细微的变化。

模型比较

这同样是一个比较直观的做法。我们仅仅选取想比较模型在最后一个 epoch 结束时模型的表示,并将它们插入到工具中。

在这里我用于比较的两个模型是一个简单的前馈神经网络(没有卷积和循环)和一个双向的 LSTM 模型。它们都使用预先训练的词嵌入进行初始化。

因此对于毒性和淫秽类评论的分类挑战,以下是模型之间表示的变化。

所有红点表示淫秽类,绿点代表非淫秽类。

通过嵌入隐层表征来理解神经网络

前馈神经网络和双向LSTM网络隐层展示的动画


可以看出双向LSTM在区分这两类上表现更好。

词嵌入可视化

我应该说我喜欢词嵌入,在任何 NLP 相关分析中它们都是我必须尝试的。 这个框架应该特别适合词嵌入。那么让我们看看我们可以如何理解它的使用。

下面这个例子是有关词嵌入在 yelp 任务上如何变化的动画。它们使用 50 维度的 Glove 词向量进行初始化。

通过嵌入隐层表征来理解神经网络

词嵌入随着在 yelp 数据集上调整的变化

令人着迷的是,「食物」这一词一开始与「拉面」,「猪肉」等实际的食物相距甚远。随着我们对嵌入物进行调整,它们之间的距离逐渐开始缩小。所以这个模型可能学习到了所有那些「拉面」,「猪肉」等都是食物实例。同样,我们也看到「餐桌」靠近「餐厅」等等。动画可以很容易地发现这些有趣的模式。

另一个可以尝试的有趣的事情是对工具进行反向工程并进行一些自定义分析。例如,我很好奇有毒词的嵌入如何在上述毒性评论分类任务中发生变化。我在上面的毒性评论分类任务中创建了一个模型,从头开始学习嵌入(因此没有使用预先训练的嵌入进行权重初始化)。我想在给定数据量的情况下对模型有点困难 – 但我认为这值得一试。该架构与双向 LSTM 相同。因此,我只是将所有有毒词汇染成红色并在动画中跟踪它们。这是嵌入式如何变化的动画:(PG-13 预警!!)

通过嵌入隐层表征来理解神经网络

在有害评论数据中从头开始学习的词嵌入的变化 

这看起来不是很迷人吗?该模型将咒骂词(代表毒性)分成一个漂亮的小簇。

我希望这篇文章能够阐明以不同方式可视化数据点的隐藏表示以及它们如何揭示有关模型的有用见解。我期待将这些分析应用于越来越多的机器学习问题。并希望其他人考虑相同并从中获益。我相信他们会帮助机器学习模型更不像一个黑盒子!

如果您认为合适,请随时提供任何反馈!

PS:我尝试使用PCA将隐藏表示降维到2维,然后从中生成动画。PCA的一个好处是它不具有概率性,因此最终的表示是一致的。然而,PCA中的局部邻域不如T-SNE那样可解释。 所以这是一个权衡,但如果有人对如何充分利用这两个方面有其他想法,非常感谢!

原文链接:https://medium.com/@rakesh.chada/understanding-neural-networks-by-embedding-hidden-representations-f256842ebf3a

号外号外~

一个专注于

AI技术发展和AI工程师成长的求知求职社区

诞生啦!

欢迎大家访问以下链接或者扫码体验

https://club.leiphone.com/page/home

通过嵌入隐层表征来理解神经网络

雷锋网(公众号:雷锋网)雷锋网

雷锋网雷锋网

雷锋网雷锋


通过嵌入隐层表征来理解神经网络

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/134277.html

(0)
上一篇 2021年9月1日
下一篇 2021年9月1日

相关推荐

发表回复

登录后才能评论