【Whole Word Mask】中文 bert wwm 预训练代码,预训练你自己的模型

基于 transformers 来进行 bert 的 wwm (全词掩码)预训练,让你的模型可以领域适配

提示:文章偏向于NLP进阶,大佬请绕路……



前言

最近看了很多关于预训练的文章和论文,最近的工作也是需要一个垂直领域的预训练模型来进行领域适配的任务,博主现在是做关于NLP医学相关领域的工作,但是现在比较适合的预训练模型又太少了,找来找去就哪些(mc bert, plc-medbert-base, med-bert, 这些更多偏向于QA,而且训练数据咱也看不到),都不怎么合适(效果不怎么好)就想着索性自己就训练一个预训练模型吧,


提示:能够找到的比较多的预训练代码(基于pytorch)都是 mlm 的, wwm 的太少了或者根本没找到,所有自己根据huggingface的API顺藤摸瓜,找到了DataCollatorForWholeWordMask这个类,可以进行全词掩码的操作,但是基于分词工具的,由于本人是医学领域的,所以觉得 pkuseg 这个工具不错,大家可以根据自己的需求来选择,jieba啊,哈工大的pyltp啊 什么的。。。

一、WWM(全词掩码)和 MLM 的区别是什么?

在这里插入图片描述大家可以根据这个图来自行揣摩。

二、预训练代码

代码如下:

# coding=utf-8
'''
    Whole word mask for bert
'''
import pkuseg
from transformers import BertConfig, BertForMaskedLM, DataCollatorForWholeWordMask,\
    BertTokenizer, TrainingArguments, Trainer
from torch.utils.data import Dataset
from tqdm import tqdm
import torch

class My_wwm_pretrain_dataset(Dataset):

    def __init__(self, path, tokenizer, dup_factor=5,max_length=512): # dup_factor : dynamic mask for 5 times
        self.examples = []
        with open(path,'r',encoding='utf-8') as f:
            total_data = f.readlines()
            with tqdm(total_data * dup_factor) as loader:
                for data in loader:
                    # clean data
                    data = data.replace('\n', '').replace('\r', '').replace('\t','').replace(' ','').replace(' ', '')
                    chinese_ref = self.get_new_segment(data)
                    input_ids = tokenizer.encode_plus(data,truncation=True,max_length=max_length).input_ids
                    dict_data = {'input_ids' : input_ids, 'chinese_ref' : chinese_ref}
                    self.examples.append(dict_data)
                    loader.set_description(f'loading data')

    def get_new_segment(self,segment):
        """
            使用分词工具获取 whole word mask
            e.g [喜,欢]-> [喜,##欢]
        """
        seq_cws = seg.cut("".join(segment))  # 利用 pkuseg 进行医学领域分词
        chinese_ref = []
        index = 1
        for seq in seq_cws:
            for i, word in enumerate(seq):
                if i>0:
                    chinese_ref.append(index)
                index +=1
        return chinese_ref

    def __getitem__(self, index):
        return self.examples[index]

    def __len__(self):
        return len(self.examples)


if __name__ == '__main__':
    # configuration
    epoch = 100
    batch_size = 1
    pretrian_model = 'mc-bert-base'
    train_file = 'data/train.txt'
    save_epoch = 10 # every 10 epoch save checkpoint
    bert_file = '../../pretrained_models/' + pretrian_model
    tokenizer_model_path='../../pretrained_models/pkuseg_medical'
    #
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    seg = pkuseg.pkuseg(model_name=tokenizer_model_path)
    config = BertConfig.from_pretrained(bert_file)
    tokenizer = BertTokenizer.from_pretrained(bert_file)
    train_dataset = My_wwm_pretrain_dataset(train_file,tokenizer)
    model = BertForMaskedLM.from_pretrained(bert_file).to(device)
    print('No of parameters: ', model.num_parameters())
    data_collator = DataCollatorForWholeWordMask(
        tokenizer=tokenizer, mlm=True, mlm_probability=0.15
    )
    print('No. of lines: ', len(train_dataset))
    save_step = len(train_dataset) * save_epoch
    tot_step = int(len(train_dataset)/batch_size *  epoch)
    print(f'\n\t***** Running training *****\n'
          f'\tNum examples = {len(train_dataset)}\n'
          f'\tNum Epochs = {epoch}\n'
          f'\tBatch size = {batch_size}\n'
          f'\tTotal optimization steps = {tot_step}\n')

    # official training
    training_args = TrainingArguments(
        output_dir='./outputs/',
        overwrite_output_dir=True,
        num_train_epochs=epoch,
        per_device_train_batch_size=batch_size,
        save_steps=save_step,
    )
    trainer = Trainer(
        model=model,
        args=training_args,
        data_collator=data_collator,
        train_dataset=train_dataset,
    )

    trainer.train()
    trainer.save_model('pretrain_outputs/wwm/')


这里我们自己写了一个Dataset对数据进行分词,并封装,调用 transformers 的 DataCollatorForWholeWordMask API 帮我们进行后续 mask 的处理,利用 BertForMaskedLM 这个API 进行模型架构的生成和预训练,代码不是很多啦,也比较简单了,其中的原理和API源码后续可能会讲,小伙伴们也可以自行多多阅读。


总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了如何基于transformer进行bert的全词掩码预训练,帮助小伙伴们进行领域适配的工作,后续有时间会简单讲一下 DataCollatorForWholeWordMask 这个API 的源码和原理,以及BertForMaskedLM 这个模型工作流程。

喜欢的朋友可以给我点点关注,你的支持是我持续更新的动力!感谢!!
想要数据和模型的童鞋可以私信我。

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Bert预训练模型是一种基于Transformer架构的自然语言处理模型,它在大规模的无标签文本数据上进行预训练,然后可以通过微调来适应各种下游任务,如文本分类、命名实体识别等。 在介绍Bert预训练模型代码之前,需要说明Bert模型的实现通常依赖于深度学习框架,如TensorFlow或PyTorch。这里以PyTorch为例,介绍一下Bert预训练模型代码。 首先,你需要安装PyTorch和transformers库。transformers库是一个用于自然语言处理任务的库,其中包含了Bert模型的实现。 接下来,你可以使用以下代码加载Bert预训练模型: ```python from transformers import BertModel, BertTokenizer # 加载Bert预训练模型 model = BertModel.from_pretrained('bert-base-uncased') tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') # 输入文本 text = "Hello, how are you?" # 对文本进行分词和编码 input_ids = tokenizer.encode(text, add_special_tokens=True) input_ids = torch.tensor([input_ids]) # 获取Bert模型的输出 outputs = model(input_ids) # 输出Bert模型的隐藏状态 hidden_states = outputs[0] ``` 上述代码中,我们首先使用`from_pretrained`方法加载了一个预训练Bert模型和对应的分词器。然后,我们将输入文本进行分词和编码,得到输入的token ids。接着,我们将token ids传入Bert模型,得到模型的输出。其中,`outputs`表示Bert模型的隐藏状态。 这只是Bert预训练模型代码的一个简单示例,实际应用中可能还需要进行更多的处理和调整,具体的代码实现会根据具体的任务和需求而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sito_zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值