transformers库使用--模型构建

1. GPT2相关模型

1.1 GPT2模型

  • transformers.GPT2Model

简介: 最原始的GPT2模型(bare GPT2),transformer输出的hidden_state后不接任何特殊的网络层。该模型继承PreTrainedModel

使用:

from transformers import GPT2PreTrainedModel, GPT2Model, GPT2Config
config = GPT2Config()
# config = GPT2Config.from_json_file(path) # 从json文件中加载配置
# config = GPT2Config.from_pretrained(model_dir)
# config = GPT2Config.from_dict(dict_obj) # 从字典加载

# transformer = GPT2Model.from_pretrained(model_dir) # 直接从指定保存的模型目录加载模型
transformer = GPT2Model(config) # 未加载预训练参数,需要用torch.load加载参数
transformer_outputs = transformer(
            input_ids,
            attention_mask=attention_mask,
            token_type_ids=token_type_ids,
            position_ids=position_ids,
            head_mask=head_mask,
            inputs_embeds=inputs_embeds,
        )

输入参数

forward(input_ids=None, 
		past_key_values=None, 
		attention_mask=None, 
		token_type_ids=None,
		position_ids=None, 
		head_mask=None, 
		inputs_embeds=None, 
		encoder_hidden_states=None, 
		encoder_attention_mask=None, 
		use_cache=None, 
		output_attentions=None, 
		output_hidden_states=None, 
		return_dict=None)
  • input_ids (torch.LongTensor of shape (batch_size, input_ids_length)) 输入序列中单词在词表中的索引
  • attention_mask (torch.FloatTensor of shape (batch_size, sequence_length), optional) 对padding的词(索引)进行mask,防止在padding的词上进行attention操作
  • token_type_ids (torch.LongTensor of shape (batch_size, input_ids_length) 用于标记输入的token是属于第一句话还是第二个句子,0代表当前单词属于第一句子,1表示属于第二句子
  • position_ids (torch.LongTensor of shape (batch_size, sequence_length), optional)
    输入句子每个单词在position embedding中的位置索引

返回值
transformer_outputs[0]是最后一层隐藏层(hidden state),其余的目前不清楚

源码解读
GPT2 Model source

# 片段1
if position_ids is None:
    position_ids = torch.arange(past_length, input_shape[-1] + past_length, dtype=torch.long, device=device)
    position_ids = position_ids.unsqueeze(0).view(-1, input_shape[-1])

从上面可以看出当不传入位置embedding时,会自动生成position embedding(相对位置),而对于attention_mask, token_type_ids参数必须自己传入

# 片段2
return BaseModelOutputWithPastAndCrossAttentions(
            last_hidden_state=hidden_states,
            past_key_values=presents,
            hidden_states=all_hidden_states,
            attentions=all_self_attentions,
            cross_attentions=all_cross_attentions,
        )

从上面这个片段中可以看出返回的只有hidden state, attention等信息,并没有loss等,而输入中也没有label, 所以此处GPT2Model仅仅是transformer模型,输出的是各个字词的编码,比较常用的是3.2GPT2LMHeadModel,它包含了语言模型

1.2 GPT2语言模型

  • transformers.GPT2LMHeadModel

简介: 在transformer输出的后面接了一个语言模型(一个与输入embedding的线性层)

输入参数:
forward(input_ids=None, past_key_values=None, attention_mask=None, token_type_ids=None, position_ids=None, head_mask=None, inputs_embeds=None, encoder_hidden_states=None, encoder_attention_mask=None, labels=None, use_cache=None, output_attentions=None, output_hidden_states=None, return_dict=None)

  • input_ids (torch.LongTensor of shape (batch_size, input_ids_length)) : 输入序列中单词在词表中的索引
  • attention_mask (torch.FloatTensor of shape (batch_size, sequence_length), optional) : 对padding的词(索引)进行mask,防止在padding的词上进行attention操作,Mask的值为0或1,1表示该词没有被mask,0表示该词被mask
  • token_type_ids (torch.LongTensor of shape (batch_size, input_ids_length): 用于标记输入的token是属于第一句话还是第二个句子,0代表当前单词属于第一句子,1表示属于第二句子
  • position_ids (torch.LongTensor of shape (batch_size, sequence_length), optional):
    输入句子每个单词在position embedding中的位置索引
  • labels (torch.LongTensor of shape (batch_size, sequence_length), optional): 语言模型的label,label可以设置成input_ids一样,它将会在模型内部进行转换成真正的label,但是indices从[-100, 0, …, vocabsize]中选择,所有被设置成-100的label会被忽略,将只会计算哪些不是-100的损失

返回值

  • loss (torch.FloatTensor of shape (1,))语言模型的损失(预测下一个单词) 当设置了输入参数label,才会返回该值
  • logits (torch.FloatTensor of shape (batch_size, sequence_length, config.vocab_size)) 语言模型的预测得分(softmax之前词表中每个词的得分)
  • hidden_states (tuple(torch.FloatTensor), optional) 是一个tuple, 一个是输出的embedding,另一个是每一层的输出)只有在输入参数output_hidden_states=True时才会被返回

使用实例

import torch
from transformers import GPT2Tokenizer, GPT2LMHeadModel

tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')

inputs = tokenizer("Hello, my dog is cute", return_tensors="pt")
outputs = model(**inputs, labels=inputs["input_ids"])
loss = outputs.loss
logits = outputs.logits

源码解读

loss = None
if labels is not None:
    # Shift so that tokens < n predict n
    shift_logits = lm_logits[..., :-1, :].contiguous()
    shift_labels = labels[..., 1:].contiguous()
    # Flatten the tokens
    loss_fct = CrossEntropyLoss()
    loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))

从上面可看到可以将label设置成label=input_ids, 因为在模型内部会重新将label进行shift操作得到真正的label

return CausalLMOutputWithCrossAttentions(
            loss=loss,
            logits=lm_logits,
            past_key_values=transformer_outputs.past_key_values,
            hidden_states=transformer_outputs.hidden_states,
            attentions=transformer_outputs.attentions,
            cross_attentions=transformer_outputs.cross_attentions,
        )

该片段展示了返回值

1.3 双头GPT2

  • GPT2DoubleHeadsModel

简介

该模型包含语言模型和多分类两个任务

输入参数

forward(input_ids=None, past_key_values=None, attention_mask=None, token_type_ids=None, position_ids=None, head_mask=None, inputs_embeds=None, mc_token_ids=None, labels=None, mc_labels=None, use_cache=None, output_attentions=None, output_hidden_states=None, return_dict=None, **kwargs)

大部分参数与GPT2中一样

  • mc_token_ids (torch.LongTensor of shape (batch_size, num_choices)) 每个输入序列用于分类的token id, 默认是最后一个token
  • labels (torch.LongTensor of shape (batch_size, sequence_length)) 语言模型的标签,可以设置成label=input_ids

源码解读

mc_loss = None
if mc_labels is not None:
    loss_fct = CrossEntropyLoss()
    mc_loss = loss_fct(mc_logits.view(-1, mc_logits.size(-1)), mc_labels.view(-1))
lm_loss = None
if labels is not None:
    shift_logits = lm_logits[..., :-1, :].contiguous()
    shift_labels = labels[..., 1:].contiguous()
    loss_fct = CrossEntropyLoss()
    lm_loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))

如上包含了多分类和语言模型的两个任务

return GPT2DoubleHeadsModelOutput(
            loss=lm_loss,
            mc_loss=mc_loss,
            logits=lm_logits,
            mc_logits=mc_logits,
            past_key_values=transformer_outputs.past_key_values,
            hidden_states=transformer_outputs.hidden_states,
            attentions=transformer_outputs.attentions,
        )

返回值如上,后续可以将lm_loss和mc_loss合并进行联合训练

2. BERT相关模型

2.1 transformers.BertModel(config, add_pooling_layer=True)

简介

这是最原始的bert模型,transformer输出hidden_states,后面没有接任何特殊任务。

输入参数

forward(input_ids=None, 
        attention_mask=None, 
        token_type_ids=None, 
        position_ids=None, 
        head_mask=None, 
        inputs_embeds=None, 
        encoder_hidden_states=None,
        encoder_attention_mask=None,
        past_key_values=None, 
        use_cache=None, 
        output_attentions=None,
        output_hidden_states=None, 
        return_dict=None)
  • input_ids (torch.LongTensor of shape (batch_size, sequence_length)) 输入序列的id
  • attention_mask (torch.FloatTensor of shape (batch_size, sequence_length), optional) 为了避免在padding token 上执行attention操作,可选数值为0或1,1表示该token不被mask, 0表示该token被mask
  • token_type_ids (torch.LongTensor of shape (batch_size, sequence_length), optional) 输入片段索引,指明哪个是输入序列的第一部分哪个是输入序列的第二部分(sequenceA sep sequenceB),可选数值为0或1,0表示sequenceA的token,1表示sequenceB的token
  • position_ids (torch.LongTensor of shape (batch_size, sequence_length), optional) 每个输入序列中字(词)的位置索引,可选数值[0, config.max_position_embeddings - 1]
  • inputs_embeds (torch.FloatTensor of shape (batch_size, sequence_length, hidden_size), optional) 可以不传如input_id,而直接传入一个输入序列的embedding

输出

  • last_hidden_state (torch.FloatTensor of shape (batch_size, sequence_length, hidden_size)) 模型最后一层的hidden-state
  • pooler_output (torch.FloatTensor of shape (batch_size, hidden_size)) 最后一层的hidden-state中对应的输入序列的第一个token,即【cls】对应的向量
  • 还有其他的返回,需要设定特定参数才能返回,具体参考BERTModel

参考

transformers各种模型参数及介绍

transformers各种预训练模型下载/模型仓库

你可能感兴趣的:(pytorch,pytorch,python,算法,自然语言处理)