XLM 预训练模型的使用
XLM 预训练模型的使用
本文使用的是 Transformer 库的预训练模型, 主要是对 xlm 部分的翻译.
xlm 模型是在 BERT 模型的基础上使用多种语言或者跨语言语料库训练得到的预训练模型, 根据训练数据与训练方法的不同, 有三张预训练模型, 分别是
- a causal language modeling (CLM) objective (next token prediction), 传统的语言模型的训练方式
- a masked language modeling (MLM) objective (Bert-like), 类似于 BERT 的mask 方式, 不同的是输入可以是多个句子
- a Translation Language Modeling (TLM) object (extension of Bert’s MLM to multiple language inputs), 输入是两种语言的并行语料库
Tips:
xlm 在使用时的特点有:
- 模型参数的多样性, 可以是三种模型的任意一个
- 语言的多样性, 使用不同的语料库, 不同的语言
XLM Config (XLM 的配置)
源码中的配置与参数:
class
transformers.``XLMConfig
(vocab_size=30145, emb_dim=2048, n_layers=12, n_heads=16, dropout=0.1, attention_dropout=0.1, gelu_activation=True, sinusoidal_embeddings=False, causal=False, asm=False, n_langs=1, use_lang_emb=True, max_position_embeddings=512, embed_init_std=0.02209708691207961, layer_norm_eps=1e-12, init_std=0.02, bos_index=0, eos_index=1, pad_index=2, unk_index=3, mask_index=5, is_encoder=True, summary_type='first', summary_use_proj=True, summary_activation=None, summary_proj_to_labels=True, summary_first_dropout=0.1, start_n_top=5, end_n_top=5, mask_token_id=0, lang_id=0, bos_token_id=0, pad_token_id=2, kwargs)**
这是 xlm 模型的配置类, 用于使用特定的参数实例化一个 xlm 模型, 同时定义模型的结构, 对于默认的结构, 得到的模型类似于 xlm-mlm-en-2048 的结构. 这个类是继承自 PretrainedConfig
, 同时可以控制模型的输出, 如果想要获取更多信息, 可以参考 PretrainedConfig
.
下面解释一下这个类的参数与使用方法:
-
vocab_size (
int
, optional, defaults to 30145) – 词典的大小, 定义了对于 xlm 来说, 分词方法使用的是 BPE, 这就表示分词之后的词典的 subword 的总数, 也是在模型的最初结构的 embedding 的输入的向量的长度 -
emb_dim (
int
, optional, defaults to 2048) – encoder 与 pooler 层的维度, 也就是从 embedding 层输出的维度. -
n_layer (
int
, optional, defaults to 12) – Transformer Encoder 层的个数 -
n_head (
int
, optional, defaults to 16) – Transformer encoder 中 self_Attention 的 Attention 的个数 -
dropout (
float
, optional, defaults to 0.1) – 全连接层的 dropout -
attention_dropout (
float
, optional, defaults to 0.1) – Attention 机制的 Dropout -
gelu_activation (
boolean
, optional, defaults toTrue
) – 在 encoder 与 pooler 层的非线性激活函数, 如果是 False, 那么就使用默认的 relu 激活函数 -
sinusoidal_embeddings (
boolean
, optional, defaults toFalse
) – Transformer 的 embedding 阶段使用 sin 的位置编码信息还是绝对位置编码信息, 这里在 Google 的Transformer 模型中使用的是 sin 的位置编码 -
causal (
boolean
, optional, defaults toFalse
) – 对应与 CLM 模型, Attention 机制不是双向的, 而是序列的 -
asm (
boolean
, optional, defaults toFalse
) – 最后的预测层是使用 log softmax 还是线性层 -
n_langs (
int
, optional, defaults to 1) – 模型处理的语言, 1 表示单语语料库 -
use_lang_emb (
boolean
, optional, defaults toTrue
) – 是否使用多语言模型, 使用方法见 the multilingual models page -
max_position_embeddings (
int
, optional, defaults to 512) – 训练模型是使用的句子的最长的长度 -
embed_init_std (
float
, optional, defaults to 2048^-0.5) – 初始化 embedding 矩阵的标准差 -
init_std (
int
, optional, defaults to 50257) – embedding 矩阵以外的参数矩阵的正态分布初始化标准差 -
layer_norm_eps (
float
, optional, defaults to 1e-12) – 归一化层使用的超参数 \(\epsilon\) -
bos_index (
int
, optional, defaults to 0) – 句子的开头在词典中的索引 -
eos_index (
int
, optional, defaults to 1) – 句子的结尾在词典中的索引 -
pad_index (
int
, optional, defaults to 2) – padding 在词典中的索引 -
unk_index (
int
, optional, defaults to 3) – 未知单词在词典中的索引 -
mask_index (
int
, optional, defaults to 5) – mask 标志在词典中的索引 -
is_encoder (
boolean
, optional, defaults toTrue
) – 初始化模型是 Transformer 中的encoder 结构还是 decoder 结构, 在双向的时候是 encoder, 单向的时候是 decoder -
summary_type (
string
, optional, defaults to “first”) –文本分类任务的时候, 在隐藏层采用的 token 的位置, bert 是第一个, xlnet 是最后一个, 将得到的隐藏层状态经过一个全连接层即可完成分类任务,:
- ’last’ => take the last token hidden state (like XLNet)
- ’first’ => take the first token hidden state (like Bert)
- ’mean’ => take the mean of all tokens hidden states
- ’cls_index’ => supply a Tensor of classification token position (GPT/GPT-2)
- ’attn’ => Not implemented now, use multi-head attention
-
lang_id (
int
, optional, defaults to 1) – 生成文本模型时指定一种语言
下面是默认的情况下的例子:
from transformers import XLMConfig, XLMModel
# Initializing a XLM configuration
configuration = XLMConfig()
# Initializing a model from the configuration
model = XLMModel(configuration)
# Accessing the model configuration
configuration = model.config
XLM Tokenizer
xlm 的 BPE 分词
- Moses preprocessing & tokenization 支持大多数模型支持的语言
- 特殊的语言分词器有: Chinese (Jieba), Japanese (KyTea) and Thai (PyThaiNLP)
- 对文本的小写化与正则化
- 使用参数
special_tokens
与函数set_special_tokens
可以添加额外的标志进入词典 - lang2id 属性会映射模型支持的语言及其ID,
- id2lang 会映射 ID及其支持的语言
使用的参数有:
- vocab_file (
string
) – Vocabulary file. - merges_file (
string
) – Merges file. - do_lower_case (
bool
, optional, defaults toTrue
) – 小写化 - remove_space (
bool
, optional, defaults toTrue
) – 去掉开头与末尾的空格 - keep_accents (
bool
, optional, defaults toFalse
) – 标记时是否保留重音符号 - unk_token (
string
, optional, defaults to “”) – 未知单词的默认 index - bos_token (
string
, optional, defaults to “”) – 训练的时候往往使用的是 cls_token sep_token (”) –句子之间分开的标志string
, optional, defaults to “- cls_token (
string
, optional, defaults to “”) – 在进行序列分类时使用的分类器令牌(对整个序列进行分类,而不是按令牌分类)。使用特殊标记构建时,它是序列的第一个标记
下面还有这个类常用的几个函数, 从源码的部分解释一下
def build_inputs_with_special_tokens(
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
) -> List[int]:
"""
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and adding special tokens.
A XLM sequence has the following format:
这是在输入中添加特殊的 tokens, 也就是这一对训练数据是特殊的 tokens,
- single sequence: ``<s> X </s>``
- pair of sequences: ``<s> A </s> B </s>``
Args:
token_ids_0 (:obj:`List[int]`):
List of IDs to which the special tokens will be added
token_ids_1 (:obj:`List[int]`, `optional`, defaults to :obj:`None`):
Optional second list of IDs for sequence pairs.
Returns:
:obj:`List[int]`: list of `input IDs <../glossary.html#input-ids>`__ with the appropriate special tokens.
"""
if token_ids_1 is None:
return [self.cls_token_id] + token_ids_0 + [self.sep_token_id]
sep = [self.sep_token_id]
cls = [self.cls_token_id]
return cls + token_ids_0 + sep + token_ids_1 + sep
# 添加了 cls 与 sep 的特殊 tokens
def get_special_tokens_mask(
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False
) -> List[int]:
"""
Retrieves sequence ids from a token list that has no special tokens added. This method is called when adding
special tokens using the tokenizer ``prepare_for_model`` or ``encode_plus`` methods.
Args:
token_ids_0 (:obj:`List[int]`):
List of ids.
token_ids_1 (:obj:`List[int]`, `optional`, defaults to :obj:`None`):
Optional second list of IDs for sequence pairs.
already_has_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`False`):
Set to True if the token list is already formatted with special tokens for the model
Returns:
:obj:`List[int]`: A list of integers in the range [0, 1]: 0 for a special token, 1 for a sequence token.
"""
if already_has_special_tokens:
if token_ids_1 is not None:
raise ValueError(
"You should not supply a second sequence if the provided sequence of "
"ids is already formated with special tokens for the model."
)
return list(map(lambda x: 1 if x in [self.sep_token_id, self.cls_token_id] else 0, token_ids_0,))
# 找出 cls 与 sep 的tokens 在 tokens_ids 中的位置
if token_ids_1 is not None:
return [1] + ([0] * len(token_ids_0)) + [1] + ([0] * len(token_ids_1)) + [1]
return [1] + ([0] * len(token_ids_0)) + [1]
# 如果没有 special tokens , 那么中间的就全部都是 0, 特殊字符在 cls 与 sep 位置
def create_token_type_ids_from_sequences(self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None) -> List[int]:
"""
Creates a mask from the two sequences passed to be used in a sequence-pair classification task.
An XLM sequence pair mask has the following format:
::
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
| first sequence | second sequence |
if token_ids_1 is None, only returns the first portion of the mask (0s).
Args:
token_ids_0 (:obj:`List[int]`):
List of ids.
token_ids_1 (:obj:`List[int]`, `optional`, defaults to :obj:`None`):
Optional second list of IDs for sequence pairs.
Returns:
:obj:`List[int]`: List of `token type IDs <../glossary.html#token-type-ids>`_ according to the given
sequence(s).
"""
sep = [self.sep_token_id]
cls = [self.cls_token_id]
if token_ids_1 is None:
return len(cls + token_ids_0 + sep) * [0]
return len(cls + token_ids_0 + sep) * [0] + len(token_ids_1 + sep) * [1]
# 将前半句设为 0, 后半句设为 1, 再加上 特殊符号
XLM Model 的使用
传统的XLM模型变压器输出原始的隐藏状态,而顶部没有任何特定的头部。
这个类的参数有: config (XLMConfig
) 模型所有参数的配置类, 初始化一个配置文件并不会导入这个模型的权重, 使用 from_pretrained()
导入模型的权重.
所以我们直接看一下模型前向传播的参数, 对于使用方法后面会给出一个例子:
XLM Model 的 Forward
-
input_ids (
torch.LongTensor
of shape(batch_size, sequence_length)
) – 输入 tokens 在词典中的索引张量, 可以通过分词的方法获得, 这里 one-hot的本质其实就是数字而已 -
attention_mask (
torch.FloatTensor
of shape(batch_size, sequence_length)
, optional, defaults toNone
) – Attention 机制中 mask 机制的矩阵, -
langs (
torch.LongTensor
of shape(batch_size, sequence_length)
, optional, defaults toNone
) – 输入的 tokens 的语言的类别 id,
-
token_type_ids (
torch.LongTensor
of shape(batch_size, sequence_length)
, optional, defaults toNone
) – 对应与上面的create_token_type_ids_from_sequences
函数, 表示句子的前后, -
position_ids (
torch.LongTensor
of shape(batch_size, sequence_length)
, optional, defaults toNone
) – 位置 embedding 信息 -
lengths (
torch.LongTensor
of shape(batch_size,)
, optional, defaults toNone
) – 因为有的句子的 Length 不是 max_Length, 所以会 Padding, 这里记录句子的长度用于防止 Attention 的时候对 Padding 的Attention. -
cache (
Dict[str, torch.FloatTensor]
, optional, defaults toNone
) – dictionary withtorch.FloatTensor
that contains pre-computed hidden-states (key and values in the attention blocks) as computed by the model (see cache output below). Can be used to speed up sequential decoding. The dictionary object will be modified in-place during the forward pass to add newly computed hidden-states. 应该是存储好的参数, -
head_mask (
torch.FloatTensor
of shape(num_heads,)
or(num_layers, num_heads)
, optional, defaults toNone
) – mask Attention 的头部, 相当于有的 Attention 会被舍去掉, 对应参数为 0, 否则参数为 1 -
input_embeds (
torch.FloatTensor
of shape(batch_size, sequence_length, hidden_size)
, optional, defaults toNone
) – 如果不想使用默认的 input_ids 构成的 embedding 方法, 可以自己选择输入一个 embedded 过的向量
XLM Model 模型 Forward 的返回值:
-
last_hidden_state (
torch.FloatTensor
of shape(batch_size, sequence_length, hidden_size)
): 也就是序列在输出层的 hidden-states, 可用于下游任务. -
hidden_states (
tuple(torch.FloatTensor)
, optional, returned whenconfig.output_hidden_states=True
):torch.FloatTensor
shape 为(batch_size, sequence_length, hidden_size)
类型的元祖, 一个用于输出 embedding 的信息, 一个是每一层的输出, shape 都是一样的 -
attentions (
tuple(torch.FloatTensor)
, optional, returned whenconfig.output_attentions=True
):Tuple of
torch.FloatTensor
(one for each layer) of shape(batch_size, num_heads, sequence_length, sequence_length)
. Attention 层之后的平均值, 用于计算权重的平均值.
使用示例:
import torch
tokenizer = XLMTokenizer.from_pretrained('xlm-mlm-en-2048')
model = XLMModel.from_pretrained('xlm-mlm-en-2048')
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True)).unsqueeze(0) # Batch size 1
outputs = model(input_ids)
last_hidden_states = outputs[0] # The last hidden-state is the first element of the output tuple
上面是最简单的模型的例子, 对于输出由于 batch_size== 1, 所以只能是 outputs[0], 同时隐含层的数据可以用于下游任务.