bert源码解析-modeling.py

bert源码解析-modeling.py

bert是transformer的encoder部分,以google-bert源代码为例。

由两个重要的class组成:

1.BertConfig 大多时候改动的参数并不多,知晓这些参数可以便于推算模型的大小,比如隐藏层大小768

class BertConfig(object):
  def __init__(self,
               vocab_size,
               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=16,
               initializer_range=0.02):
    """
    构造参数
    :param vocab_size: 词汇量大小
    :param hidden_size: 隐藏层输出大小
    :param num_hidden_layers: 隐藏层单元层数
    :param num_attention_heads: 注意力模块个数
    :param intermediate_size: 中间层输出大小 用于前向传播时 由hidden_size->intermediate_size
    :param hidden_act: 隐藏层激活函数
    :param hidden_dropout_prob: 隐藏层dropout
    :param attention_probs_dropout_prob: 注意力部分dropout
    :param max_position_embeddings: 位置编码最大值默认是512
    :param type_vocab_size: token_type_ids的词典大小,用于句子上下句是否是同一个用的标识,默认是大小是2 也就是用0或1表示
    :param initializer_range: 初始化方法的范围
    """
    self.vocab_size = vocab_size
    self.hidden_size = hidden_size
    self.num_hidden_layers = num_hidden_layers
    self.num_attention_heads = num_attention_heads
    self.hidden_act = hidden_act
    self.intermediate_size = intermediate_size
    self.hidden_dropout_prob = hidden_dropout_prob
    self.attention_probs_dropout_prob = attention_probs_dropout_prob
    self.max_position_embeddings = max_position_embeddings
    self.type_vocab_size = type_vocab_size
    self.initializer_range = initializer_range

2.BertModel 模型部分

模型部分主要分成三个部分说明,对应的可以看transformer单个block的结构。

在这里插入图片描述

从初始化方法__init__开始说明 初始化定义:

config 即上述BertConfig is_training 判断是否是训练,如果不是训练则不需要进行dropout,因为dropout是为了避免训练过程过拟合 input_ids 输入句子的数字化表示,例如源代码注释 tf.constant([[31, 51, 99], [15, 5, 0]]) input_mask 表示该位置是否有数字,长度和input_ids一致 token_type_ids 字的type use_one_hot_embeddings 输入初始化词是否使用独热编码 scope tf变量作用域的名称,默认是“bert”

初始化三个输入: input_shape 大小是的[batch_size, seq_length] input_mask 大小是的[batch_size, seq_length] token_type_ids 大小是的[batch_size, seq_length]

主要结构如下,一个个来介绍。

  • 声明变量作用域(“bert”)
  • 变量作用域(“embeddings”)
  • 词嵌入
  • 位置编码及mask编码
  • 变量作用域(“encoder”)
  • 变量作用域(“pooler”)

(1)embedding-词嵌入

①初始化词嵌入矩阵 矩阵大小及 [vocab_size, embedding_size] 词表大小*词向量维度

②输入input_ids拍平和嵌入矩阵相乘得到输入的嵌入矩阵,再reshape成[batch_size, seq_length, embedding_size]输出。

详细注释如下:

def embedding_lookup(input_ids,
                     vocab_size,
                     embedding_size=128,
                     initializer_range=0.02,
                     word_embedding_name="word_embeddings",
                     use_one_hot_embeddings=False):
  """
  获取词嵌入
  :param input_ids: 输入词的id
  :param vocab_size: 词典大小
  :param embedding_size: 词嵌入输出维度
  :param initializer_range: 生成截断正态分布的初始化的标准差
  :param word_embedding_name: 词嵌入再网络中的name
  :param use_one_hot_embeddings: 判断是使用何种初始编码方式,one-hot或tf.gather
  :return:
  """

  #如果输入大小是[batch_size, seq_length]
  #如果输入是二维的 reshape成三维[batch_size, seq_length, 1]
  if input_ids.shape.ndims == 2:
    input_ids = tf.expand_dims(input_ids, axis=[-1])

  #这个矩阵大小就是[vocab_size, embedding_size] 那么每个词都可以通过one-hot获取到其对应的嵌入矩阵
  embedding_table = tf.get_variable(
      name=word_embedding_name,
      shape=[vocab_size, embedding_size],
      initializer=create_initializer(initializer_range))

  #输入id reshape 成一维 例如[[1,2],[3,4]]=>[1,2,3,4]
  flat_input_ids = tf.reshape(input_ids, [-1])

  #获取输出矩阵 两种方式
  #1.用one-hot与embedding_table相乘得到嵌入矩阵
  #2.tf.gather直接切片提取
  #得到output是(batch_size * seq_length) * embedding_size
  if use_one_hot_embeddings:
    one_hot_input_ids = tf.one_hot(flat_input_ids, depth=vocab_size)
    output = tf.matmul(one_hot_input_ids, embedding_table)
  else:
    output = tf.gather(embedding_table, flat_input_ids)

  #获取input_ids的 [batch_size, seq_length]
  input_shape = get_shape_list(input_ids)

  #reshape的尺寸input_shape[0:-1]是[batch_size, seq_length] + 1*embedding_size
  #所以输出是[batch_size, seq_length, embedding_size]
  output = tf.reshape(output,
                      input_shape[0:-1] + [input_shape[-1] * embedding_size])
  return (output, embedding_table)

(2)embedding-位置编码及mask编码

①token type 用于标识当前字的类型,比如上下句标识。“小明爱学习,小林爱学习”标识上下句[0,0,0,0,0,1,1,1,1,1] bert-chinese模型默认大小为2

token_type_ids 输入大小是 [batch_size, seq_length],对应的嵌入矩阵是[token_type_vocab_size, embedding_size]

输入拍平之后和嵌入矩阵相乘在reshape得到[batch_size, seq_length, embedding_size]直接和词嵌入相加

②use_position_embeddings 位置编码,因为注意力机制部分没有位置信息,所以输入时候单独添加,注意!!bert的位置是通过参数学习的,不是使用sin cos组合得到。

初始化嵌入矩阵 大小为[max_position_embeddings, embedding]

根据seq_length直接截取前seq_length即可,但是此时矩阵大小是[seq_length,embedding ]

因为每个batch使用相同的位置向量,为了能直接相加,进行广播到batch size 得到[batch_size, seq_length, embedding_size]

和上述output相加

③接入layer_norm_and_dropout 输出

详细注释如下:</

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这些警告信息是关于一些 TensorFlow 函数和类的变化和更新的提示。我会逐个解释每个警告的含义: 1. "From E:\pycharm-workspace\BERT\BERT-BiLSTM-CRF-NER-master\bert_base\bert\modeling.py:359: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version. Instructions for updating: Please use rate instead of keep_prob. Rate should be set to rate = 1 - keep_prob." 这个警告表示在 "modeling.py" 文件的第 359 行中,使用了 `dropout` 函数,并传递了 `keep_prob` 参数。然而,将来的 TensorFlow 版本将移除 `keep_prob` 参数,并建议使用 `rate` 参数代替。`rate` 参数的计算方式为 `rate = 1 - keep_prob`。 你可以将代码中的 `keep_prob` 替换为 `rate` 来消除这个警告。 2. "From E:\pycharm-workspace\BERT\BERT-BiLSTM-CRF-NER-master\bert_base\bert\modeling.py:673: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version. Instructions for updating: Use keras.layers.Dense instead." 这个警告表示在 "modeling.py" 文件的第 673 行中,使用了 `dense` 函数,但该函数已被废弃,并将在将来的 TensorFlow 版本中移除。建议使用 `keras.layers.Dense` 来代替。 你可以将代码中的 `dense` 替换为 `keras.layers.Dense` 来消除这个警告。 3. "From E:\pycharm-workspace\BERT\BERT-BiLSTM-CRF-NER-master\venv\lib\site-packages\tensorflow_core\python\layers\core.py:187: Layer.apply (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version. Instructions for updating: Please use layer.__call__ method instead." 这个警告表示在 "core.py" 文件的第 187 行中,使用了 `Layer.apply` 方法,但该方法已被废弃,并将在将来的 TensorFlow 版本中移除。建议使用 `layer.__call__` 方法来代替。 你可以将代码中的 `Layer.apply` 替换为 `layer.__call__` 来消除这个警告。 4. "From E:\pycharm-workspace\BERT\BERT-BiLSTM-CRF-NER-master\bert_base\bert\modeling.py:277: The name tf.erf is deprecated. Please use tf.math.erf instead." 这个警告表示在 "modeling.py" 文件的第 277 行中,使用了 `tf.erf` 函数,但该函数已被废弃。建议使用 `tf.math.erf` 函数来代替。 你可以将代码中的 `tf.erf` 替换为 `tf.math.erf` 来消除这个警告。 总之,这些警告信息是为了提醒你在代码中使用了已被废弃或即将被移除的 TensorFlow 函数和类。建议根据警告信息中的建议进行相应的更新,以保持代码的兼容性和稳定性。 如果你对这些警告信息有更多疑问或需要进一步帮助,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值