使用PyTorch微调ALBERT中文预训练模型

Overview

    • ALBERT简介
      • Embedding因式分解
      • 层间参数共享
      • 句子间关联损失
      • ALBERT系列&Bert比较
    • transformers简介
    • tf模型转torch模型
    • torch实现微调ALBERT
    • 参考文献

ALBERT简介

    通常情况下,增加预训练模型大小会带来效果的提升;然而,当模型大小达到一定的程度之后,就很难再进行了,因为受到了GPU内存和训练时间的限制。为了减小模型参数和模型训练时间,ALBERT提出了两种解决方法。ALBERT也是采用和Bert一样的Transformer的Encoder[1]结构,激活函数也是GLUE[2]。相比于Bert,ALBERT主要改进之处在于以下几点:Embedding因式分解(Factorized embedding parameterization)、层间参数共享(Cross-layer parameter sharing)、句子间关联损失(Inter-sentence coherence loss)。

Embedding因式分解

    我们用H表示隐藏层大小,E表示embedding维度,V表示词汇表的大小。
    Bert base模型的Encoder输出大小(H)和embedding维度(E)都是768,然而,ALBERT认为词级别的embedding是没有上下文依赖的表述;而隐藏层的输出值,不仅包括了词本身的意思,还包含了上下文信息。理论上来说隐藏层包含的信息更多一些,因此应该让H >> E。所以ALBERT的embedding维度是小于encoder输出维度的。在NLP任务中,通常词典都很大,embedding矩阵的大小是E×V,如果和Bert一样让H = E,那么embedding矩阵的参数量会很大,并且在反向传播过程中,更新的内容也比较稀疏。
    结合上述所说的两点,ALBERT采用了一种因式分解的方法来降低参数量。首先把one-hot向量映射到一个低纬度的空间,大小为E,然后再映射到一个高纬度的空间(H);从而把参数量从O(V×H)降低到了O(V×E + E×H),当E << H时,参数量就减少得很明显了。

层间参数共享

    Transformer中共享参数的方案有多种,比如,只共享全连接层,只共享Attention[1]层。ALBERT结合了上述两种方案,对全连接层和Attention都进行参数共享,也就是共享encoder所有的参数。同量级下的Transformer采用该共享方案后实际效果有所下降,但是参数量减少了很多,训练速度也提升了很多。
    ALBERT减小了模型参数,提升了训练速度,且每一层的输出的embedding相比于BERT来说震荡幅度更小一些。可见参数共享其实是有稳定网络参数的作用的。

句子间关联损失

    Bert的NSP任务实际上是一个二分类,训练数据的正样本是通过采样同一个文档中的两个连续的句子,而负样本是通过采用两个不同文档的句子。该任务主要是希望能提高下游任务的效果,例如自然语言推理任务。但是后续的研究发现该任务效果并不好,主要原因是其任务过于简单。NSP其实包含两个子任务,主题预测与关系一致性预测,但是主题预测相比于关系一致性预测简单太多了,并且在MLM任务中其实也有类似的效果。
    这里解释一下为什么包含了主题预测,因为正样本是在同一个文档中选取的,负样本是在不同的文档选取的,假如我们有2个文档,一个是娱乐相关的,一个是新中国成立70周年相关的,那么负样本选择的内容就是不同的主题,而正样都在娱乐文档中选择的话预测出来的主题就是娱乐,在新中国成立70周年的文档中选择的话就是后者这个主题了。
    在ALBERT中,为了只保留一致性任务去除主题识别的影响,提出了一个新的任务Sentence-Order Prediction(SOP),SOP的正样本和NSP的获取方式是一样的,负样本把正样本的顺序反转即可。由于SOP是在同一个文档中选的,其只关注句子的顺序并没有主题方面的影响。并且SOP能解决NSP的任务,但是NSP并不能解决SOP的任务,该任务的添加让最终的结果提升了一个点。

ALBERT系列&Bert比较

使用PyTorch微调ALBERT中文预训练模型_第1张图片

注:上述内容参考博客以及原始论文ALBERT[3]。

transformers简介

    transformers是一个很强大的预训练模型库,实现了几乎所有开源的预训练模型的调用接口【主页】。albert_xlarge_zh使用指南

tf模型转torch模型

  • [albert_xlarge_zh]模型下载链接
    使用PyTorch微调ALBERT中文预训练模型_第2张图片

  • 转换脚本

"""Convert ALBERT checkpoint."""

import argparse
import logging

import torch

from transformers import AlbertConfig, AlbertForPreTraining, load_tf_weights_in_albert

logging.basicConfig(level=logging.INFO)

def convert_tf_checkpoint_to_pytorch(tf_checkpoint_path, albert_config_file, pytorch_dump_path):
    # Initialise PyTorch model
    config = AlbertConfig.from_json_file(albert_config_file)
    print("Building PyTorch model from configuration: {}".format(str(config)))
    model = AlbertForPreTraining(config)

    # Load weights from tf checkpoint
    load_tf_weights_in_albert(model, config, tf_checkpoint_path)

    # Save pytorch-model
    print("Save PyTorch model to {}".format(pytorch_dump_path))
    torch.save(model.state_dict(), pytorch_dump_path)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    # Required parameters
    parser.add_argument(
        "--tf_checkpoint_path", default=None, type=str, required=True, help="Path to the TensorFlow checkpoint path."
    )
    parser.add_argument(
        "--albert_config_file",
        default=None,
        type=str,
        required=True,
        help="The config json file corresponding to the pre-trained ALBERT model. \n"
        "This specifies the model architecture.",
    )
    parser.add_argument(
        "--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model."
    )
    args = parser.parse_args()
    convert_tf_checkpoint_to_pytorch(args.tf_checkpoint_path, args.albert_config_file, args.pytorch_dump_path)

'''
python convert_albert_tf_checkpoint_to_pytorch.py \
    --tf_checkpoint_path=./albert_xlarge/model.ckpt-best \
    --albert_config_file=./albert_xlarge/albert_config.json \
    --pytorch_dump_path=./albert_xlarge/pytorch_model.bin
'''

torch实现微调ALBERT

  • 调用接口:
from transformers import BertTokenizer, AlbertModel
tokenizer = BertTokenizer.from_pretrained("./albert_xlarge")
bert_model = AlbertModel.from_pretrained("./albert_xlarge")
"""下游微调任务"""
  • 模型转换完成之后需要对以下两个文件名进行修改
    • albert_config.json 修改为 config.json
    • vocab_chinese.txt 修改为 vocab.txt

参考文献

[1] Attention Is All You Need
[2] Gaussian Error Linear Units (GELUs)
[3] ALBERT: A Lite BERT for Self-supervised Learning of Language Representations

你可能感兴趣的:(Deep,Learning,自然语言处理,深度学习,pytorch,tensorflow)