🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
在本章中,我们将介绍两个不同的技术概念,注意力可视化和实验跟踪,我们将通过exBERT和BertViz等复杂工具来实践它们。这些工具为可解释性和可解释性提供了重要功能。首先,我们将讨论如何利用这些工具将注意力的内部部分可视化。重要的是解释学习到的表示并理解 Transformer 中自注意力头编码的信息。我们将看到某些头部对应于语法或语义的某个方面。其次,我们将学习如何通过记录来跟踪实验,然后使用TensorBoard和权重和偏差( W&B )。这些工具使我们能够有效地托管和跟踪实验结果,例如损失或其他指标,这有助于我们优化模型训练。您将学习如何使用 exBERT 和 BertViz 来查看他们自己模型的内部部分,并且将能够在本章结束时使用 TensorBoard 和 W&B 来监控和优化他们的模型。
我们将在本章中介绍以下主题:
我们将使用 Jupyter Notebook 来运行需要 Python 3.6.0 或更高版本的编码练习,并且需要安装以下软件包:
与大多数深度学习( DL ) 架构一样,两者Transformer 模型的成功以及它们的学习方式尚未完全了解,但我们知道 Transformer ——值得注意的是——学习了该语言的许多语言特征。大量学习的语言知识分布在隐藏状态和预训练模型的自注意力头中。最近发表了大量研究,并开发了许多工具来理解和更好地解释这些现象。
多亏了一些自然语言处理( NLP ) 社区工具,我们能够解释 Transformer 模型中的自注意力负责人学习到的信息。由于令牌之间的权重,可以自然地解释头部。我们很快就会看到,在本节的进一步实验中,某些头部对应于语法或语义的某个方面。我们还可以观察到表层模式和许多其他语言特征。
在本节中,我们将使用社区工具进行一些实验,以观察注意力头中的这些模式和特征。最近的研究已经揭示了自我注意的许多特征。在我们进入之前,让我们重点介绍其中的一些实验。例如,大多数头都关注分隔符例如分隔符( SEP ) 和分类( CLS ),因为这些令牌永远不会被掩盖,尤其是带有段级信息。另一个观察结果是,大多数头很少关注当前令牌,但有些头只专注于下一个或上一个令牌,尤其是在较早的层中。以下是最近研究中发现的其他模式列表,我们可以在实验中轻松观察到:
为了观察这些模式,我们可以在这里使用两个重要的工具exBERT和BertViz。这些工具具有几乎相同的功能。我们将从 exBERT 开始。
exBERT 是一个可视化工具来查看变形金刚的内部。我们将使用它来可视化基于BERT 的模型的注意力头,这是 exBERT 界面中的默认模型。除非另有说明,否则我们将在以下示例中使用的模型是BERT-base-cased。这包含 12 层和每层中的 12 个自注意力头,即 144 个自注意力头。
图 11.1 – exBERT 界面
在里面前面的屏幕截图,左边的标记注意正确的令牌。线的粗细代表权重的值。因为 CLS 和 SEP 令牌具有非常频繁和密集的连接,为了简单起见,我们切断了与它们相关的链接。请参阅隐藏特殊令牌切换开关。我们现在看到的是第 1 层的注意力映射,其中的线条对应于所有头部的权重之和。这被称为多头注意力机制,在其中12个头彼此并行工作。这种机制使我们能够捕获比单头注意力更广泛的关系。这就是为什么我们在图 11.1中看到一个广泛参与的模式。我们还可以通过单击Head列来观察任何特定的头部。
如果您将鼠标悬停在左侧的令牌上,您将看到该令牌的特定权重连接到右侧的令牌。有关使用该界面的更多详细信息,请阅读论文exBERT:A Visual Analysis Tool to Explore Learned Representations in Transformer Models,Benjamin Hoover,Hendrik Strobelt,Sebastian Gehrmann,2019或通过以下链接观看视频:https://exbert .net/。
图 11.2 – 先前标记的注意力模式
图 11.3 – Next-token 注意力模式
这些头为其他输入句子提供相同的功能——也就是说,它们独立于输入工作。你可以自己尝试不同的句子。
我们可以将注意力头用于高级语义任务,例如使用一个探测分类器。首先,我们将定性地检查内部表征是否具有代词解析(或共指解析)的能力。代词解析被认为是一项具有挑战性的语义关系任务,因为代词与其先行词之间的距离通常很长。
图 11.4 – <9,9> 头部的共指模式
< 9,12>头部也适用于代词关系。同样,将鼠标悬停在它上面时,我们会得到以下输出:
图 11.5 – <9,12> 头部的共指模式
来自之前的截图,我们看到it代词强烈关注其先行词cat。我们稍微改变了句子,现在它的代词指代食物而不是猫,因为猫没有吃食物,因为它不新鲜。如以下屏幕截图所示,它与<9,9>头部有关,它正确地处理了它的前身food,正如预期的那样:
图 11.6 – 第二个例子的 <9,9> 头部的模式
图 11.7 – <9,9> 头部第二个输入的模式
图 11.8 – 通过掩码评估模型
什么时候你悬停在那个蒙面的令牌上,你可以看到基于Bert 的模型的预测分布,如上图所示。第一个预测是food,这是预期的。有关该工具的更多详细信息,您可以使用exBERT 的网页,位于exBERT。
做得好!在下一节中,我们将使用 BertViz 并编写一些 Python 代码来访问注意力头。
现在,我们将写一些可视化头部的代码使用 BertViz,这是一个在 Transformer 模型中可视化注意力的工具,exBERT 也是如此。它由 Jesse Vig 于 2019 年开发(A Multiscale Visualization of Attention in the Transformer Model,Jesse Vig,2019)。它是 Tensor2Tensor 可视化工具(Jones,2017)工作的扩展。我们可以通过多尺度定性分析来监控模型的内部。BertViz 的优势在于我们可以与大多数拥抱人脸托管模型(例如来自 Transformer 的双向编码器表示( BERT )、生成的预训练 Transformer ( GPT ) 和跨语言语言模型( XLM ))Python应用程序编程接口( API )。因此,我们也可以使用非英语模型或任何预训练模型。我们将很快一起研究这些例子。您可以访问 BertViz 资源以及来自以下 GitHub 链接的其他信息:https ://github.com/jessevig/bertviz 。
与 exBERT 一样,BertViz 在单个界面中可视化注意力头。此外,它支持鸟瞰图和低级神经元视图,我们观察单个神经元如何相互作用以建立注意力权重。可以在以下链接中找到有用的演示视频:https ://vimeo.com/340841955 。
在开始之前,我们需要安装必要的库,如下:
!pip install bertviz ipywidgets
然后我们导入以下模块:
- from bertviz import head_view
-
- from Transformers import BertTokenizer, BertModel
BertViz 支持三种视图:头部视图、模型视图和神经元视图。让我们一一研究这些观点。不过,首先需要指出的是,我们从 1 开始对 exBERT 中的层和头进行索引。但是在 BertViz 中,我们从 0 开始进行索引,就像在 Python 中一样编程。如果我在 exBERT 中说一个<9,9>头,那么它的 BertViz 对应物是<8,8>。
让我们从头视图开始。
头视图是BertViz 相当于我们迄今为止在上一节中使用 exBERT 所经历的。注意力头视图可视化基于一个或多个注意力的注意力模式选定层中的头部:
- def get_bert_attentions(model_path, sentence_a, sentence_b):
- model = BertModel.from_pretrained(model_path,
- output_attentions=True)
- tokenizer = BertTokenizer.from_pretrained(model_path)
- inputs = tokenizer.encode_plus(sentence_a,
- sentence_b, return_tensors='pt',
- add_special_tokens=True)
- token_type_ids = inputs['token_type_ids']
- input_ids = inputs['input_ids']
- attention = model(input_ids,
- token_type_ids=token_type_ids)[-1]
- input_id_list = input_ids[0].tolist()
- tokens = tokenizer.convert_ids_to_tokens(input_id_list)
-
- return attention, tokens
- model_path = 'bert-base-cased'
- sentence_a = "The cat is very sad."
- sentence_b = "Because it could not find food to eat."
- attention, tokens=get_bert_attentions(model_path,
- sentence_a, sentence_b)
- head_view(attention, tokens)
代码输出是一个界面,如下所示:
图 11.9 – BertViz 的头视图输出
界面在图 11.9的左边是第一个。将鼠标悬停在左侧的任何标记上将显示来自该标记的注意力。顶部的彩色瓷砖对应于注意力头。双击其中任何一个将选择它并丢弃其余部分。较粗的注意力线表示较高的注意力权重。
请记住,在前面的 exBERT 示例中,我们观察到<9,9>头部(BertViz 中的等价物是<8, 8>,由于索引)具有代词-先行关系。我们在图 11.9中观察到相同的模式,选择第 8 层和第 8 头。然后,当我们将鼠标悬停在图 11.9右侧时,我们看到了界面,它强烈关注猫和它令牌。那么,我们可以在其他预训练的语言模型中观察到这些语义模式吗?尽管其他模型中的头部并不完全相同,但一些头部可以对这些语义属性进行编码。我们还从最近的工作中了解到,语义特征主要是在较高层中编码的。
- model_path = 'dbmdz/bert-base-turkish-cased'
- sentence_a = "Kedi çok üzgün."
- sentence_b = "Çünkü o her zamanki gibi çok fazla yemek yedi."
-
- attention, tokens=get_bert_attentions(model_path, sentence_a, sentence_b)
- head_view(attention, tokens)
从前面的代码中,sentence_a和sentence_b分别表示The cat is sad和因为它像往常一样吃了太多食物。当悬停在o ( it ) 上时,它会关注Kedi ( cat ),如下所示:
图 11.10 – 土耳其语模型中的共指模式
model_path = 'bert-base-german-caseed'
- model_path = 'bert-base-german-cased'
- sentence_a = "Die Katze ist sehr traurig."
- sentence_b = "Weil sie zu viel gegessen hat"
-
- attention, tokens=get_bert_attentions(model_path, sentence_a, sentence_b)
- head_view(attention, tokens)
图 11.11 – 德语模型中的共指关系模式
如您所见,将鼠标悬停在sie上时,您会看到对Die Katze的强烈关注。虽然这个<8,11>头部是共指关系(在计算语言学文献中称为照应关系)最强的头部,但这种关系可能已经传播到许多其他人的头上。为了观察它,我们必须一一检查所有的磁头。
另一方面,BertViz 的模型视图功能为我们提供了一个基本的鸟瞰图,可以一次看到所有头部。让我们在下一节中看看它。
模型视图允许我们要鸟瞰所有头和层的注意力视图。自注意力头以表格形式显示,行和列分别对应于层和头。每个头部都以可点击缩略图的形式可视化,其中包括注意力模型的广泛形状。
该视图可以告诉我们 BERT 的工作原理并使其更易于解释。最近的许多研究,例如A Primer in BERTology:我们对 BERT 工作原理的了解,Anna Rogers,Olga Kovaleva ,Anna Rumshisky,2021,发现了一些关于层行为的线索并达成了共识。我们已经在解释注意力头部分中列出了其中一些。您可以使用 BertViz 的模型视图自己测试这些事实。
再来看看我们刚刚使用的德语模型,如下:
- from bertviz import model_view
- from Transformers import BertTokenizer, BertModel
- def show_model_view(model, tokenizer, sentence_a,
- sentence_b=None, hide_delimiter_attn=False,
- display_mode="dark"):
-
- . . .
- model_path='bert-base-german-cased'
- sentence_a = "Die Katze ist sehr traurig."
- sentence_b = "Weil sie zu viel gegessen hat"
- model = BertModel.from_pretrained(model_path, output_attentions=True)
- tokenizer = BertTokenizer.from_pretrained(model_path)
- show_model_view(model, tokenizer, sentence_a, sentence_b,
- hide_delimiter_attn=False,
- display_mode="light")
这是输出:
图 11.12 – 德语模型的模型视图
这个视图可以帮助我们轻松地观察许多模式,例如下一个标记(或前一个标记)的注意力模式。正如我们前面在解释注意力头部分中提到的,标记通常倾向于关注分隔符——特别是低层的 CLS 分隔符和上层的 SEP 分隔符。因为这些令牌没有被屏蔽,所以它们可以简化信息的流动。在最后一层,我们只观察 SEP-delimiter-focused attention 模式。可以推测,SEP 用于收集段级信息,然后可以用于句间任务,例如下一句预测( NSP ) 或用于编码句子级别的含义。
另一方面,我们观察到共指关系模式主要编码在<8,1>、<8,11>、<10,1> 和 <10,7>头中。同样,可以清楚地说<8, 11>头是我们已经讨论过的德国模型中编码共指关系的最强头。
图 11.13 – 模型视图中 <8,11> 头部的特写
我认为这对于头部视图和模型视图来说已经足够了。现在,让我们借助神经元视图解构模型,并尝试了解这些头部如何计算权重。
到目前为止,我们有给定输入的可视化计算权重。神经元视图可视化查询中的神经元和关键向量,以及如何基于交互计算令牌之间的权重。我们可以跟踪任何两个令牌之间的计算阶段。
同样,我们将加载德语模型和可视化我们刚刚使用的同句对,以保持连贯性。我们执行以下代码:
- from bertviz.Transformers_neuron_view import BertModel, BertTokenizer
- from bertviz.neuron_view import show
-
- model_path='bert-base-german-cased'
- sentence_a = "Die Katze ist sehr traurig."
- sentence_b = "Weil sie zu viel gegessen hat"
- model = BertModel.from_pretrained(model_path, output_attentions=True)
- tokenizer = BertTokenizer.from_pretrained(model_path)
- model_type = 'bert'
- show(model, model_type, tokenizer, sentence_a, sentence_b, layer=8, head=11)
这是输出:
图 11.14 – 共指关系模式的神经元视图(头部 <8,11>)
视图有帮助我们将注意力的计算从我们在左侧选择的sie标记跟踪到右侧的其他标记。正值是蓝色,负值是橙色。颜色强度表示数值的大小。sie的查询与Die和Katze的键非常相似。如果您仔细查看这些模式,您会注意到这些向量有多相似。因此,他们的点积高于其他比较,这在这些代币之间建立了强烈的关注度。当我们向右移动时,我们还跟踪点积和 Softmax 函数输出。单击左侧的其他标记时,您还可以跟踪其他计算。
现在,让我们为相同的输入选择一个 head-bearing next-token 注意模式,并跟踪它。为此,我们选择<2,6>头。在这种模式下,几乎所有注意力都集中在下一个单词上。我们再次点击sie token,如下:
图 11.15 – next-token 注意力模式的神经元视图(<2,6> 头部)
现在,sie令牌专注于下一个令牌而不是它自己的先行词(Die Katze)。当我们仔细查看查询和候选键时,与sie的查询最相似的键是下一个标记zu。同样,我们观察点积和 Softmax 函数是如何按顺序应用的。
在下一节中,我们将简要讨论用于解释 Transformer 的探测分类器。
什么 DL 的不透明度learns 导致了许多关于此类模型解释的研究。我们试图回答 Transformer 模型的哪些部分负责某些语言特征,或者输入的哪些部分引导模型做出特定决定的问题。为此,除了可视化内部表示之外,我们还可以在表示上训练分类器来预测一些外部形态、句法或语义属性。因此,我们可以确定是否将内部表示与外部属性相关联。模型的成功训练将是这种关联的定量证据——也就是说,语言模型已经学习了与外部属性相关的信息。这种方法是称为探测分类器方法,这是 NLP 和其他 DL 研究中的一种突出分析技术。基于注意力的探测分类器将注意力图作为输入并预测外部属性,例如共指关系或头部修饰关系。
如前面的实验所示,我们使用get_bert_attention()函数获得给定输入的自注意力权重。我们可以直接将它们转移到分类管道,而不是可视化这些权重。因此,通过监督,我们可以确定哪个头适合哪个语义特征——例如,我们可以找出哪些头适合与标记数据共指。
现在,让我们继续讨论模型跟踪部分,这对于构建高效模型至关重要。
到目前为止,我们已经训练了语言模型并简单分析最终结果。我们没有观察训练过程,也没有对使用不同选项的训练进行比较。在本节中,我们将简要讨论如何监控模型训练。为此,我们将在第 5 章“微调文本分类语言模型”中处理如何跟踪我们之前开发的模型的训练。
在这个领域开发了两个重要的工具——一个是 TensorBoard,另一个是 W&B。对于前者,我们将训练结果保存到本地驱动器,并在实验结束时将它们可视化。使用后者,我们能够在云平台上实时监控模型训练进度。
本节将简要介绍这些工具,而不会详细介绍它们,因为这超出了本章的范围。
让我们从 TensorBoard 开始。
张量板是专门用于 DL 实验的可视化工具。它具有许多功能,例如跟踪、训练、将嵌入投影到较低空间以及可视化模型图。我们主要使用它来跟踪和可视化损失等指标。对于 Transformers 来说,使用 TensorBoard 跟踪指标非常容易,只需在模型训练代码中添加几行就足够了。一切都保持几乎一样。
现在,我们将重复我们在第 5 章“文本分类的微调语言模型”中所做的互联网电影数据库( IMDb ) 情绪微调实验,并将跟踪指标。在那一章,我们已经训练了一个具有 IMDb 数据集的情感模型,该数据集由4 公斤( 4K ) 训练数据集、1K 验证集和 1K 测试集组成。现在,我们将使其适应 TensorBoard。有关 TensorBoard 的更多详细信息,请访问https://www.tensorflow.org/tensorboard。
让我们开始:
!pip install tensorboard
- from Transformers import TrainingArguments, Trainer
-
- training_args = TrainingArguments(
- output_dir='./MyIMDBModel',
- do_train=True,
- do_eval=True,
- num_train_epochs=3,
- per_device_train_batch_size=16,
- per_device_eval_batch_size=32,
- logging_strategy='steps',
- logging_dir='./logs',
- logging_steps=50,
- evaluation_strategy="steps",
- save_strategy="epoch",
- fp16=True,
- load_best_model_at_end=True
- )
- %reload_ext tensorboard
-
- %tensorboard --logdir logs
这是输出:
图 11.16 – 训练历史的 TensorBoard 可视化
您可能已经注意到,我们可以跟踪我们之前定义的指标。横轴从 0 到 750 步,这是我们之前计算的。我们不会在这里详细讨论 TensorBoard。让我们只看一下评估/损失图表。当您单击左下角的最大化图标,您将看到以下图表:
图 11.17 – TensorBoard 评估/损失图表,记录步骤为 50
在前面的屏幕截图中,我们使用 TensorBoard 仪表板左侧的滑块控件将平滑设置为 0,以便更准确地查看分数并关注全局最小值。如果您的实验具有非常高的波动性,则平滑功能可以很好地查看整体趋势。它起到移动平均线( MA ) 的作用。这个图表支持我们之前的观察,其中在步骤250的最佳损耗测量值为0.2658。
图 11.18 – 10 步记录的更高分辨率 eval/loss 图表
我们现在已经完成了 TensorBoard。让我们与 W&B 合作!
W&B,不像TensorBoard,在云平台中提供仪表板,我们可以在单个集线器中跟踪和备份所有实验。它还允许我们与团队合作进行开发和共享。训练代码在我们的本地机器上运行,而日志保存在 W&B 云中。最重要的是,我们可以实时跟踪培训过程,并立即与社区或团队分享结果。
!pip install wandb
- import wandb
-
- !wandb login
wandb请求一个 API 密钥,您可以在以下链接中轻松找到该密钥:https ://wandb.ai/authorize 。
!export WANDB_API_KEY=e7d*********
- training_args = TrainingArguments(
- ... the rest is same ...
- run_name="IMDB-batch-32-lr-5e-5",
- report_to="wandb"
- )
wandb.finish()
该执行还会在本地输出运行历史记录,如下所示:
图 11.19 – W&B 的本地输出
当你连接到 W&B 提供的链接,您将进入一个界面看起来像这样:
图 11.20 – W&B 仪表板上单次运行的在线可视化
这个可视化给了我们总结的表现单次运行的结果。如您所见,我们可以跟踪我们在compute_metric()函数中定义的指标。
现在,让我们采取看一下评估损失。下面的截图显示了与 TensorBoard 提供的完全相同的图,其中最小损失约为 0.2658,发生在步骤 250:
图 11.21 – W&B 仪表板上 IMDb 实验的评估/损失图
到目前为止,我们只可视化了一次运行。W&B 允许我们一次在大量运行中动态探索结果——例如,我们可以使用不同的超参数(例如学习率或批量大小)来可视化模型的结果。为此,我们使用另一个不同的超参数设置正确地实例化一个TrainingArguments对象,并为每次运行相应地更改run_name="..." 。
以下屏幕截图显示了我们使用不同超参数运行的几个 IMDb 情感分析。我们还可以看到我们更改的批量大小和学习率:
图 11.22 – 在 W&B 仪表板上探索多次运行的结果
W&B 提供有用的功能——例如,它自动进行超参数优化和搜索可能模型的空间,称为 W&B Sweeps。除此之外,它还提供与图形处理单元( GPU ) 消耗、中央处理单元( CPU ) 利用率等相关的系统日志。更多详细信息,请查看以下网站:https ://wandb.ai/home 。
做得好!在最后一节,参考资料中,我们将更多地关注技术工具,因为使用这些实用工具来开发更好的模型至关重要。
在本章中,我们介绍了两个不同的技术概念:注意力可视化和实验跟踪。我们首先使用 exBERT 在线界面可视化注意力头。然后,我们研究了 BertViz,在那里我们编写了 Python 代码来查看三种 BertViz 可视化:头部视图、模型视图和神经元视图。BertViz 界面为我们提供了更多控制权,以便我们可以使用不同的语言模型。此外,我们还能够观察到令牌之间的注意力权重是如何计算的。这些工具为我们提供了可解释性和可利用性的重要功能。我们还学习了如何跟踪我们的实验以获得更高质量的模型并进行错误分析。我们使用了两种工具来监控训练:TensorBoard 和 W&B。这些工具用于有效跟踪实验和优化模型训练。