使用Mask LM预训练任务来预训练Bert模型。训练垂直领域语料的模型表征,提升下游任务的表现。

Overview

Pretrain_Bert_with_MaskLM

Info

使用Mask LM预训练任务来预训练Bert模型。

基于pytorch框架,训练关于垂直领域语料的预训练语言模型,目的是提升下游任务的表现。

Pretraining Task

Mask Language Model,简称Mask LM,即基于Mask机制的预训练语言模型。

同时支持 原生的MaskLM任务和Whole Words Masking任务。默认使用Whole Words Masking

MaskLM

使用来自于Bert的mask机制,即对于每一个句子中的词(token):

  • 85%的概率,保留原词不变
  • 15%的概率,使用以下方式替换
    • 80%的概率,使用字符[MASK],替换当前token。
    • 10%的概率,使用词表随机抽取的token,替换当前token。
    • 10%的概率,保留原词不变。

Whole Words Masking

与MaskLM类似,但是在mask的步骤有些少不同。

在Bert类模型中,考虑到如果单独使用整个词作为词表的话,那词表就太大了。不利于模型对同类词的不同变种的特征学习,故采用了WordPiece的方式进行分词。

Whole Words Masking的方法在于,在进行mask操作时,对象变为分词前的整个词,而非子词。

Model

使用原生的Bert模型作为基准模型。

Datasets

项目里的数据集来自wikitext,分成两个文件训练集(train.txt)和测试集(test.txt)。

数据以行为单位存储。

若想要替换成自己的数据集,可以使用自己的数据集进行替换。(注意:如果是预训练中文模型,需要修改配置文件Config.py中的self.initial_pretrain_modelself.initial_pretrain_tokenizer,将值修改成 bert-base-chinese

自己的数据集不需要做mask机制处理,代码会处理。

Training Target

本项目目的在于基于现有的预训练模型参数,如google开源的bert-base-uncasedbert-base-chinese等,在垂直领域的数据语料上,再次进行预训练任务,由此提升bert的模型表征能力,换句话说,也就是提升下游任务的表现。

Environment

项目主要使用了Huggingface的datasetstransformers模块,支持CPU、单卡单机、单机多卡三种模式。

可通过以下命令安装依赖包

    pip install -r requirement.txt

主要包含的模块如下:

    python3.6
    torch==1.3.0
    tqdm==4.61.2
    transformers==4.6.1
    datasets==1.10.2
    numpy==1.19.5
    pandas==1.1.3

Get Start

单卡模式

直接运行以下命令

    python train.py

或修改Config.py文件中的变量self.cuda_visible_devices为单卡后,运行

    chmod 755 run.sh
    ./run.sh

多卡模式

如果你足够幸运,拥有了多张GPU卡,那么恭喜你,你可以进入起飞模式。 🚀 🚀

(1)使用torch的nn.parallel.DistributedDataParallel模块进行多卡训练。其中config.py文件中参数如下,默认可以不用修改。

  • self.cuda_visible_devices表示程序可见的GPU卡号,示例:1,2→可在GPU卡号为1和2上跑,亦可以改多张,如0,1,2,3
  • self.device在单卡模式,表示程序运行的卡号;在多卡模式下,表示master的主卡,默认会变成你指定卡号的第一张卡。若只有cpu,那么可修改为cpu
  • self.port表示多卡模式下,进程通信占用的端口号。(无需修改)
  • self.init_method表示多卡模式下进程的通讯地址。(无需修改)
  • self.world_size表示启动的进程数量(无需修改)。在torch==1.3.0版本下,只需指定一个进程。在1.9.0以上,需要与GPU数量相同。

(2)运行程序启动命令

    chmod 755 run.sh
    ./run.sh

Experiment

使用交叉熵(cross-entropy)作为损失函数,困惑度(perplexity)和Loss作为评价指标来进行训练,训练过程如下:

Reference

【Bert】https://arxiv.org/pdf/1810.04805.pdf

【transformers】https://github.com/huggingface/transformers

【datasets】https://huggingface.co/docs/datasets/quicktour.html

You might also like...
Comments
  • 金标准有问题

    金标准有问题

    datasets里面train.txt和test.txt里面的文本有UNK标识,导致训练的时候金标准和训练样本一致,结果就是最后训练出来的模型我用来预测[MASK]的时候发现,出来的都是[MASK]。。

    断点打在train.py第70行位置,watch一下list(zip(batch['input_ids'][0].tolist(), batch['labels'][0].tolist())),会发现input_ids和labels是一模一样的。

    opened by jarork 3
  • 请教词嵌入

    请教词嵌入

    您好,最近正在学习词嵌入,看到您的代码,我想请问一下可以预训练自己的语料来做词嵌入吗?我的想法是,用maskLM来训练自己的语料,然后得到的model.bin再用transformer的AutoModel.from_pretrained调用得到词嵌入。请问是这种操作方式吗?这样得到的效果会比原本的bert直接得到的词嵌入效果更好吗?

    opened by hongxiaDu 4
  • 请教wwm的分词问题

    请教wwm的分词问题

    最近我在做一个垂直域预训练的技术储备,看了你DataManager里面的代码,但是没有能够理解wwm的实现方法,比如如何分词确定词语的边界。我以为是先使用分词器做的分词然后做的Masking操作。

    我之前有了解过pkuseg分词器:https://github.com/lancopku/pkuseg-python

    它不光可以确定词边界而且还能给出每个词的词性,感觉做masking的时候如果可以更大概率的去Mask实词,少一些放在虚词上应该效果会更好,欢迎探讨。wechat:yiyaoh

    opened by jarork 2
  • 关于制作预训练数据的时间优化

    关于制作预训练数据的时间优化

    制作bert预训练数据集DataManager的op_mask_wwm和op_mask那里,其实可以使用numpy取一个值域在[0,1]上的维度保持一样的array,然后用numpy来操作,应该会快得多,数据量太大会消耗很多时间。比如可以使用这种写法: random_tensor = torch.rand(inputs['input_ids'].shape) masked_tensor = (random_tensor < 0.15)(inputs['input_ids'] != 101)(inputs['input_ids'] != 102)*(inputs['input_ids'] != 0)

    opened by jarork 1
Owner
Desmond Ng
NLP Engineer
Desmond Ng