BERT源码分析(一)---预训练

整个代码文件如下:

BertModel类实现了BERT模型,代码位于modeling.py模块中。

1.配置类(BertConfig)

这段代码定义了BERT模型的一些默认参数和4个文件处理函数。

参数:

  1. vocab_size:词表大小
  2. hidden_size:隐藏层神经元数
  3. num_hidden_layers:Transformer encoder中的隐藏层数
  4. num_attention_heads:multi-head attention 的head数
  5. intermediate_size:encoder的“中间”隐层神经元数(例如feed-forward layer)
  6. hidden_act:隐藏层激活函数
  7. hidden_dropout_prob:隐层dropout率
  8. attention_probs_dropout_prob:注意力部分的dropout
  9. max_position_embeddings:最大位置编码
  10. type_vocab_size:token_type_ids的词典大小
  11. initializer_range:truncated_normal_initializer初始化方法的stdev

函数:

  1. from_dict(cls,json_object):从字典中获取config参数;
  2. from_json(cls,json_file):从json文件中获取config参数;
  3. to_dict():将实例序列化为Python字典;
  4. to_json_string():将此实例序列化为JSON字符串。

2.获取词向量(embedding_lookup) 

1
2
3
4
5
6
def embedding_lookup(input_ids,
                     vocab_size,
                     embedding_size=128,
                     initializer_range=0.02,
                     word_embedding_name="word_embeddings",
                     use_one_hot_embeddings=False) 

功能:输入每句话每个单词的id,返回这句话的embedding表示(获得token embedding)

参数:

  1. input_ids:word id 【batch_size, seq_length】
  2. vocab_size:embedding词表
  3. embedding_size:embedding维度
  4. initializer_range:embedding初始化范围
  5. word_embedding_name:embeddding table命名
  6. use_one_hot_embeddings:是否使用one-hot embedding

返回:

  1. output:输出对应单词的词向量[batch_size, seq_length, num_inputs*embedding_size]
  2. embedding table:单词对应embedding的表【batch_size, seq_length, embedding_size】

  如果使用one-hot,则先对输入word_ids进行one-hot处理,再乘以embedding_table,得到对应word的词向量;不使用one-hot,直接用从embedding_table中获取对应word_ids的词向量。

3.词向量的后续处理(embedding_postprocessor)

1
2
3
4
5
6
7
8
9
10
def embedding_postprocessor(input_tensor,
                            use_token_type=False,
                            token_type_ids=None,
                            token_type_vocab_size=16,# 一般是2
                            token_type_embedding_name="token_type_embeddings",
                            use_position_embeddings=True,
                            position_embedding_name="position_embeddings",
                            initializer_range=0.02,
                            max_position_embeddings=512,#最大位置编码,必须大于等于max_seq_len
                            dropout_prob=0.1):

功能:在token embedding的基础上,增加segment embedding和position embedding。

输入:

  1. input_tensor:float,[batch_size, seq_length, embedding_size].
  2. use_token_type: 布尔,是否添加‘token_type_ids’的embedding
  3. token_type_ids: (可选) int32,[batch_size, seq_length]. 只有use_token_type为True情况下使用
  4. token_type_vocab_size: int. “ token_type_ids”的词汇量
  5. token_type_embedding_name: string,token type ids的embedding table表名称 
  6. use_position_embeddings: 布尔,是否添加position embeddings
  7. position_embedding_name: string,positional embedding的embedding table表名称
  8. initializer_range: float,权重初始化范围 
  9. max_position_embeddings: int,此模型可能曾经使用的最大sequence长度。 该长度可以比input_tensor的序列长度长,但不能短。
  10. dropout_prob: float,应用于最终输出张量的dropout概率

4.构造attention_mask

1
2
3
4
5
6
7
8
9
10
def create_attention_mask_from_input_mask(from_tensor, to_mask):
  """Create 3D attention mask from a 2D tensor mask.
 
  Args:
    from_tensor: 2D or 3D Tensor of shape [batch_size, from_seq_length, ...].
    to_mask: int32 Tensor of shape [batch_size, to_seq_length].
 
  Returns:
    float Tensor of shape [batch_size, from_seq_length, to_seq_length].
  """

功能:从2维的mask生成3维的attention mask。

参数:

  1. from_tensor:padding后的input_ids,2D或者3D张量,[batch_size, from_seq_length,…]
  2. to_mask:mark标记向量[batch_size, to_seq_length]

返回:

  1. mask:[batch_size, from_seq_length, to_seq_length]

5.注意力层(attention layer) 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def attention_layer(from_tensor,
                    to_tensor,
                    attention_mask=None,
                    num_attention_heads=1,
                    size_per_head=512,
                    query_act=None,
                    key_act=None,
                    value_act=None,
                    attention_probs_dropout_prob=0.0,
                    initializer_range=0.02,
                    do_return_2d_tensor=False,
                    batch_size=None,
                    from_seq_length=None,
                    to_seq_length=None)

功能:实现multi-head attention,考虑key-query-value形式的attention,输入的from_tensor当做是query, to_tensor当做是key和value,当两者相同的时候即为self-attention。

参数:

  1. from_tensor:[batch_size, from_seq_length, from_width]
  2. to_tensor:[batch_size, to_seq_length, to_width]
  3. attention_mask=None:[batch_size,from_seq_length, to_seq_length]
  4. num_attention_heads=1:attention head numbers
  5. size_per_head=512:每个head的大小
  6. query_act=None:query变换的激活函数
  7. key_act=None:key变换的激活函数
  8. value_act=None:value变换的激活函数
  9. attention_probs_dropout_prob=0.0:attention层的dropout
  10. initializer_range=0.02:初始化取值范围
  11. do_return_2d_tensor=False:是否返回2d张量,
    1. 如果True,输出形状[batch_size*from_seq_length,num_attention_heads*size_per_head]
    2. 如果False,输出形状[batch_size, from_seq_length, num_attention_heads*size_per_head]
  12. batch_size=None:如果输入是3D的, #那么batch就是第一维,但是可能3D的压缩成了2D的,所以需要告诉函数batch_size
  13. from_seq_length=None:同上
  14. to_seq_length=None:同上

具体过程参照:https://www.cnblogs.com/nxf-rabbit75/p/11945130.html

6.Transformer

1
2
3
4
5
6
7
8
9
10
11
def transformer_model(input_tensor,                        # 【batch_size, seq_length, hidden_size】
                      attention_mask=None,                # 【batch_size, seq_length, seq_length】
                      hidden_size=768,
                      num_hidden_layers=12,
                      num_attention_heads=12,
                      intermediate_size=3072,
                      intermediate_act_fn=gelu,            # feed-forward层的激活函数
                      hidden_dropout_prob=0.1,
                      attention_probs_dropout_prob=0.1,
                      initializer_range=0.02,
                      do_return_all_layers=False)

功能:实现Transformer模型

参数:

  1. input_tensor:[batch_size, seq_length, hidden_size]
  2. attention_mask=None:[batch_size, seq_length, seq_length]
  3. hidden_size=768:Transformer隐藏层大小
  4. num_hidden_layers=12:Transformer的层(block)数
  5. num_attention_heads=12:attention头的数目
  6. intermediate_size=3072:transformer的“中间”隐层神经元数
  7. intermediate_act_fn=gelu:feed-forward层的激活函数
  8. hidden_dropout_prob=0.1
  9. attention_probs_dropout_prob=0.1
  10. initializer_range=0.02
  11. do_return_all_layers=False

7.函数入口(init)

 

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Already been converted into WordPiece token ids
  input_ids = tf.constant([[31, 51, 99], [15, 5, 0]])
  input_mask = tf.constant([[1, 1, 1], [1, 1, 0]])
  token_type_ids = tf.constant([[0, 0, 1], [0, 1, 0]])
 
  config = modeling.BertConfig(vocab_size=32000, hidden_size=512,
    num_hidden_layers=8, num_attention_heads=6, intermediate_size=1024)
 
  model = modeling.BertModel(config=config, is_training=True,
    input_ids=input_ids, input_mask=input_mask, token_type_ids=token_type_ids)
 
  label_embeddings = tf.get_variable(...)
  pooled_output = model.get_pooled_output()
  logits = tf.matmul(pooled_output, label_embeddings)

  

 

 

参考文献:

【1】BERT实战(源码分析+踩坑)

【2】BERT源码分析PART I - 知乎

【3】tf.one_hot()函数简介 - nini_coded的博客

【4】tensorflow 1.0 学习:参数初始化(initializer) - denny402 - 博客园

【5】TensorFlow函数(八)tf.control_dependencies() - 章朔 - 博客园

posted @   nxf_rabbit75  阅读(2770)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
历史上的今天:
2018-12-19 Keras 源码分析
1.配置类(BertConfig)2.获取词向量(embedding_lookup) 3.词向量的后续处理(embedding_postprocessor)4.构造attention_mask5.注意力层(attention layer) 6.Transformer7.函数入口(init)
点击右上角即可分享
微信分享提示