2021-12-03

Overview

  • BERT是一个具有绝对位置嵌入的模型,因此通常建议将输入在右侧进行pad,而不是左侧
  • bert被训练在MLM和NSP目标,有效预测masked token 和 自然语言推断,但是对于==文本生成==并不是最优的。

01 BertConfig

class transformers.BertConfig(
    vocab_size=30522, hidden_size=768, num_hidden_layers=12, num_attention_heads=12, intermediate_size=3072, hidden_act='gelu', hidden_dropout_prob=0.1, attention_probs_dropout_prob=0.1, max_position_embeddings=512, type_vocab_size=2, initializer_range=0.02, layer_norm_eps=1e-12, pad_token_id=0, position_embedding_type='absolute', use_cache=True, classifier_dropout=None,
    **kwargs)

这是一个配置类,储存了Bert的配置。它会根据特别的参数实例化bert模型,定义模型结构。以默认的参数实例化一个配置,将会产生一个类似于bert-base-uncased的架构。

Configuration 目标继承自PretrainedConfig,并且可以被用来控制模型的输出,详细信息可以看起文档链接。

from transformers import BertModel, BertConfig
config = BertConfig.from_pretrained('./model/bert-base')  # 储存配置信息,诸如hidden_size等
config.hidden_size==>768
model = BertModel(config)  # 产生encoder模型,拥有和预训练模型一样的架构
model.config  # 可以查看其配置信息
model.config.hidden_size

02 BertTokenizer

在wordpiece上建立了一个基础的BERT tokenizer,这个tokenizer继承自PreTrainedTokenizer

class transformers.BertTokenizer(
    vocab_file,do_lower_case = True,do_basic_tokenize = True,never_split = None,unk_token = '[UNK]', sep_token = '[SEP]', pad_token = '[PAD]', cls_token = '[CLS]', mask_token = '[MASK]', tokenize_chinese_chars = True, strip_accents = None, **kwargs )
#### 2.1    build_inpus_with_special_tokens

( token_ids_0: typing.List[int],token_ids_1: typing.Optional[typing.List[int]] = None ) ⟶ List[int]


通过concat并且增加特殊的token从==一个序列==或者==序列对==建立模型的输入来进行序列分类

1. 单序列: `[CLS] X [SEP]`
2. 序列对: `[CLS] A [SEP] B [SEP]`

#### 2.2  get_special_mask

( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None already_has_special_tokens: bool = False ) ⟶ List[int]


恢复序列id,如果序列没有特殊special token,他会加上并显示出哪些是special token。

```python
input: tokenizer.get_special_tokens_mask([9145, 8139])
Out: [1, 0, 0, 1]

2.2 create_token_type_ids_from_sequences

( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) ⟶ List[int]

再进行sequence-pair分类任务时,创造出两个序列的mask。

0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
| first sequence    | second sequence |

如果==token_ids_1==是None,这个方法只返回第一个部分。

input[33]: tokenizer.create_token_type_ids_from_sequences([10, 34,45], [2,4,5])
Out[33]: [0, 0, 0, 0, 0, 1, 1, 1, 1]

input[34]: tokenizer.create_token_type_ids_from_sequences([10, 34,45])
Out[34]: [0, 0, 0, 0, 0]

input[35]: tokenizer('ada', 'dad')
Out[35]: {'input_ids': [101, 9145, 8139, 102, 10005, 8168, 102], 'token_type_ids': [0, 0, 0, 0, 1, 1, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1]}

### 03  BertModel

```python
class transformers.BertModel( config, add_pooling_layer = True )

赤裸的Bert Model transformers输出原始的hidden-states在顶部没有任何的特殊头。

==如果add_pooling_layer=True则它的输出output有两个==

  • output[0]——>batch_size, seq_len, hidden_size
  • output[1]——>batch_size,hidden_size,==它取cls的时间步并加上了一个线性变换和一个激活函数输出==

model可以作为一个编码器也可以作为一个解码器, 在这种情况下一个cross-attention层被加到两个self-attention之间。如果要作为一个编码器,模型需要被初始化,==config==的参数==is_decoder==和==add_cross_attention==设置为==True==,一个==encoder_hidden_states==作为编码器的输入到forward。

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 ) ⟶ BaseModelOutputWithPoolingAndCrossAttentions or tuple(torch.FloatTensor)
from transformers import BertModel, BertConfig, BertTokenizer
tokenizer = BertTokenizer.from_pretrained('./model/bert-base')
config = BertConfig.from_pretrained('./model/bert-base')
model = BertModel(config)
inputs = tokenizer('你好啊', return_tensors='pt')
out = model(input_ids=inputs['input_ids'], attention_mask=inputs['attention_mask'],token_type_ids=inputs['token_type_ids'] )
out.last_hidden_state.shape

Out[49]: torch.Size([1, 5, 768])
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容