【NLP】BERT代码实现--Bert4keras源码及矩阵计算解析

前言

bert4keras是苏剑林通过keras封装Bert,可以更快速、更友好的使用Bert。
bert4keras链接:https://github.com/bojone/bert4keras
本文是对该链接下bert4keras/bert4keras/的源码进行解析

源码重要性

个人认为了解源码非常重要,主要有两个看法:

  1. 了解源码会让你对原理有个更好的了解,在做下游任务或者模改的时候就更加游刃有余;
  2. 源码中会有很多在代码实现的骚套路,学学后会大大提升自己写代码的能力和简洁性。

在解析bert4keras源码前,需要各位具备如下知识:

  • BERT的基本原理(或Transformer原理)
  • Keras中层(Layer)的定义方式和使用(可以参考苏神科学空间的:“让Keras更酷一些!”:精巧的层与花式的回调:https://kexue.fm/archives/5765)
  • MultiAttention(可以参考本人写的:“基于keras的MultiAttention实现及实例”:https://zhuanlan.zhihu.com/p/231631291)

Bert4keras框架

bert4keras的总体架构由6个代码文件组成,主文件是models.py,其余的文件均为主文件服务,或者为下游任务的建模过程中服务。

models.py:主文件,主体Transformer类,其余的都是以Transformer为父类实现其算法,包括BERT,ALBERT,NEZHA,ELECTRA,GPT2_ML,T5的算法及其优化

layers.py: 实现各类功能的层,类似Keras中的layer,这里包括Embedding,MultiHeadAttention(多头注意力),LayerNormalization,PositionEmbedding(位置编码),RelativePositionEmbedding(相对位置编码),FeedForward等实现

本篇从主文件models.py开始介绍

Transformer类

Transformer类写好了bert等这类预训练模型的整体框架,主要在build,call两个函数中实现。
包括三大内容(在build函数中):Input(输入),self.call(算法计算流程),Model(建模)
实现框架如下图:
在这里插入图片描述
apply函数的妙用:在Transformer类中的apply函数的妙用:通过apply调用层会自动重用同名层,每次层进来都会存储在self.layers字典中,相同名字的层会重复使用,这样很好用而且在后面的Albert中要共享参数的时候也方便实现。

    def apply(self, inputs, layer=None, arguments=None, **kwargs):
        """通过apply调用层会自动重用同名层
        inputs: 上一层的输出;
        layer: 要调用的层类名;
        arguments: 传递给layer.call的参数;
        kwargs: 传递给层初始化的参数。
        """
        if layer is Dropout and self.dropout_rate == 0:
            return inputs

        arguments = arguments or {
   }
        name = kwargs.get('name')  # name='Embedding-Token'
        if name not in self.layers:
            layer = layer(**kwargs)
            name = layer.name
            self.layers[name] = layer  # 保存下来,方便重复调用

        return self.layers[name](inputs, **arguments)  # 可以看Bert中的详细用法

算法实现(以Bert为例)

依照Transformer类的逻辑顺序,总结如下:

  1. Input(输入)
    get_inputs函数:
    实现bert的输入: token(x_in)和segment(s_in)
    shape均为:shape=(btz, seq_len)
    输出:[x_in, s_in]
  2. self.call(算法计算流程)
  • apply_embedding:转成字向量
    x embedding – s embedding – x&s add – Position embedding – LN – dropout
    输出shape=(btz, seq_len, hidden_size)

  • apply_main_layers:计算流程主体
    循环num_hidden_layers次:
    Bert计算主体:Att --> DROPOUT --> Add --> LN --> FFN --> DROPOUT --> Add --> LN
    输出shape=(btz, seq_len, intermediate_size)

  • apply_final_layers:根据下流任务调整输出
    with_pool:提取CLS向量,用CLS向量表示这句话的句向量 shape=(btz, 768)
    with_nsp:预测是否是下一句,shape=(btz, 2)
    with_mask:Mask LM mask语言模型,在预训练的时候会用到,或者要预测句中某个字或词的时候可以用到

代码及矩阵张量运算见代码注释:

class BERT(Transformer):
    """构建BERT模型
    """
    def __init__(
            self,
            max_position,  # 序列最大长度
            with_pool=False,  # 是否包含Pool部分
            with_nsp=False,  # 是否包含NSP部分
            with_mlm=False,  # 是否包含MLM部分
            **kwargs  # 其余参数
    ):
        super(BERT, self).__init__(**kwargs)
        self.max_position = max_position
        self.with_pool = with_pool
        self.with_pool = with_pool
        self.with_nsp = with_nsp
        self.with_mlm = with_mlm

    def get_inputs(self):
        """BERT的输入是token_ids和segment_ids
        """
        x_in = Input(shape=(self.sequence_length,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值