栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

BART源码阅读

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

BART源码阅读

在大航哥的建议下,阅读了Transformers的Bart源代码:modeling_bart.py。

这里记录一下阅读时的思路和笔记,主要是从软件工程的视角梳理了一下源代码中几个类之间的关系,方便后续的理解、使用和修改。至于每个类中一些中间结果的shape,则可以自己在调试的时候跟进去看。

在这里我会以自顶向下的方式来分析:

  1. 首先对整个modeling_bart.py 文件中类的关系进行分析和介绍
  2. 然后介绍父类的作用:PretrainedBartModel、PreTrainedModel
  3. 接下来以 BartForConditionalGeneration 为例子进行介绍,modeling_bart.py 文件中的三个功能类都使用到了 BartModel
  4. 因此,最后分析 BartModel 以及构成它的相关组件(咕咕咕):BartEncoder, BartDecoder,EncoderLayer 和 DecoderLayer

1. 类的关系总览

modeling_bart.py 文件中,类之间的关系如下图所示:

  1. PretrainedBartModel 是 BartModel,BartForConditionalGeneration,BartForSequenceClassification 和 BartForQuestionAnswering的父类
  2. BartForConditionalGeneration,BartForSequenceClassification 和 BartForQuestionAnswering 在实现功能的过程中都使用了BartModel
  3. BartModel 就是 BART 的 backbone network。BART 本质上还是一个 Encoder Decoder 的架构,因此,在 BartModel 中由 BartEncoder 和 BartDecoder组成
  4. BartEncoder 和 BartDecoder中,分别由多个 EncoderLayer 和 DecoderLayer构成

2. PretrainedBartModel 和 PreTrainedModel

在具体地介绍 BartModel 之前,先来看看他的父类 PretrainedBartModel。

PretrainedBartModel 继承自 PreTrainedModel 类。

PreTrainedModel 类提供了诸如:from_pretrained(),init_weights() 等方法。所以PretrainedBartModel 也拥有PreTrainedModel 类的方法啦,比较常用的就是from_pretrained():

3. BartForConditionalGeneration

我们先从一个具体的功能类 BartForConditionalGeneration 来看。BartForConditionalGeneration 可用于摘要生成,也可以做 mask filling 的任务(需要使用bart-large)。

3.1 __init()__ 函数

从代码中可以看出,BartForConditionalGeneration 在初始化时,创建了 BartModel 的对象,并赋值给了self.model。

因此,BartModel 主干网络是我们后面需要重点分析的部分。

3.2 forward() 函数

然后我们直接来看 forward() 函数,参数可以分为 encoder 的部分和 decoder 的部分。
这里有个 past_key_values 变量,我们留到后面再讲,先把整体的流程摸清楚。


具体的参数应该传入什么,可以参考github 上的issue:Can I training a bart model from scratch by transformers?

在 forward() 的函数体中,首先,把参数传入到 self.model,也就是 BartModel 的对象中,这里其实是调用了 BartModel 的forward() 方法。得到输出结果 outputs,outputs 包含了 encoder 和 decoder 在 encode 和 decode 过程中的一些中间结果,可以从 return 语句看出,包括了 decoder_hidden_states,decoder_attentions, cross_attentions, encoder_last_hidden_state等信息。

然后将输出结果 outputs 中的 decoder hidden state:outputs[0] 传入到全连接层中,得到 lm_logits。lm_logits 可以在 mask filling 时判断 [mask] 处应该填入什么单词。

接下来,如果 labels 不为空的话,则通过 CrossEntropyLoss() 计算 masked_lm_loss。

4. BartModel

ok,接下来就是 BartModel 这个重头戏了。

4.1 __init()__ 函数

首先,创建了一个embedding函数,赋值给了self.shared,用于在后面的 BartEncoder 和 BartDecoder 中提取embedding。

然后创建了 BartEncoder 和 BartDecoder 的对象,分别用于 encode 和 decode 。因此,我们后面需要进一步分析 BartEncoder 和 BartDecoder 。

最后通过init_weights() 函数初始化权重。

4.2 forward()函数

首先通过 encoder 得到 encoder_outputs:

  • 当 encoder_outputs 为None时,会调用 BartModel 中的 self.encoder 进行编码(self.encoder 是 BartEncoder 的对象);
  • 当给定了 encoder_outputs 时,则直接将其封装到 BaseModelOutput 中,并实例化给 encoder_outputs 。猜测这个写法是方便用户使用不同的 encoder?

然后将 decoder 的相关参数以及 encoder_outputs[0] (encoder 的 last_hidden_state)传入到 self.decoder 中,得到 decoder_outputs。

最终将 decoder_outputs 的内容封装到 Seq2SeqModelOutput 并返回该类的对象。

至此,我们已经得到了 BartForConditionalGeneration 中的 outputs。
并且,可以看到,outputs[0] 就是 decoder_outputs.last_hidden_state。

后面还可以再继续深入了解BartEncoder等内容,溜了…


参考资料
  1. BART源码剖析(transformers 4.9.0)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/982367.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号