试试在transformers中调用ERNIE

ERNIE是什么

a27e4910b147296d89bd962a30cf5660.jpeg
ERNIE发展路径

文心大模型ERNIE是百度发布的产业级知识增强大模型,涵盖了NLP大模型和跨模态大模型。在中文场景下,ERNIE有明显的优势,目前已经发布了一系列模型,包括ERNIE1.0, ERNIE2.0, ERNIE3.0, ERNIE-Gram, ERNIE-Doc等,并且一直在持续更新中。ERNIE官方的代码和模型是PaddlePaddle版本的,具体可以参见:PaddlePaddle/ERNIEPaddlePaddle/PaddleNLP 这两个repo。

在transformers中调用ERNIE

但是目前学术界和工业界在NLP大模型方面一般都会基于 huggingface/transformers 来开展工作。所以就会产生很强烈的动机将ERNIE从PaddlePaddle版本转换到Pytorch版本,这里的转换包括模型的代码和模型的参数。经过漫长的code review,本人提交的ERNIE模型最终合入了transformers中,并在4.22.0版本中可以直接体验了!!

250faa0135eb5818de55446fe7c5ea47.png
https://github.com/huggingface/transformers/releases/tag/v4.22.0

快速开始

首先将`transformers`升级到4.22.0版本及以上

pip install --upgrade transformers

仅需3行代码即可快速调用ERNIE模型(以ernie1.0为例):

from transformers import BertTokenizer, ErnieModel
tokenizer = BertTokenizer.from_pretrained("nghuyong/ernie-1.0-base-zh")
model = ErnieModel.from_pretrained("nghuyong/ernie-1.0-base-zh")

目前已经支持模型,包括ERNIE1.0,ERNIE2.0,ERNIE3.0,ERNIE-gram,ERNIE-health在内的10个模型:

c168d4a00d87d56f6731bbd0c13a7cc0.jpeg
https://huggingface.co/nghuyong

输出验证

为了快速检验我们模型转换的是否正确,我们可以将官方PaddlePaddle版本的结果与我们转换后Pytorch版本的结果做一个对比验证。均对`welcome to ernie pytorch project`进行编码,并打印最后的pooled层

import paddle
import transformers

# huggingface/transformers
tokenizer = transformers.BertTokenizer.from_pretrained('nghuyong/ernie-1.0-base-zh')
model = transformers.ErnieModel.from_pretrained('nghuyong/ernie-1.0-base-zh')
input_ids = torch.tensor([tokenizer.encode(text="welcome to ernie pytorch project", add_special_tokens=True)])
model.eval()
with torch.no_grad():
    pooled_output = model(input_ids)[0]
print('huggingface result')
print('pool output:', pooled_output.numpy())

# paddlepaddle
tokenizer = paddlenlp.transformers.AutoTokenizer.from_pretrained("ernie-1.0-base-zh")
model = paddlenlp.transformers.AutoModel.from_pretrained("ernie-1.0-base-zh")
inputs = tokenizer("welcome to ernie pytorch project")
inputs = {k: paddle.to_tensor([v]) for (k, v) in inputs.items()}
model.eval()
with paddle.no_grad():
    pooled_output = model(**inputs)
print('paddle result')
print('pool output:', pooled_output[0].numpy())

下面是计算的结果

huggingface result
pool output: [-1.         -1.          0.9981035  -0.9996652  -0.78173476 -1.          -0.9994901   0.97012603  0.85954666  0.9854131 ]

paddle result
pool output: [-0.99999976 -0.99999976  0.9981028  -0.9996651  -0.7815545  -0.99999976  -0.9994898   0.97014064  0.8594844   0.985419  ]

可以看到转后前后两者计算的结果保持一致(精确度为0.0001)

论文复现

我们知道ERNIE1.0的特点是融入了实体的信息。现在可以基于转换后的代码和模型,快速验证论文中的例子。

import transformers

tokenizer = transformers.BertTokenizer.from_pretrained('nghuyong/ernie-1.0-base-zh')
model = transformers.ErnieForMaskedLM.from_pretrained('nghuyong/ernie-1.0-base-zh')
input_ids = torch.tensor([tokenizer.encode(text="[MASK][MASK][MASK]是中国神魔小说的经典之作,与《三国演义》《水浒传》《红楼梦》并称为中国古典四大名著。",
                                            add_special_tokens=True)])
model.eval()
with torch.no_grad():
    predictions = model(input_ids)[0][0]
predicted_index = [torch.argmax(predictions[i]).item() for i in range(predictions.shape[0])]
predicted_token = [tokenizer._convert_id_to_token(predicted_index[i]) for i in
                    range(1, (predictions.shape[0] - 1))]
print('predict result:\t', predicted_token)

预测的结果为:

predict result:	 ['西', '游', '记', '是', '中', '国', '神', '魔', '小', '说', '的', '经', '典', '之', '作', ',', '与', '《', '三', '国', '演', '义', '》', '《', '水', '浒', '传', '》', '《', '红', '楼', '梦', '》', '并', '称', '为', '中', '国', '古', '典', '四', '大', '名', '著', '。']

进一步对比其他的中文预训练模型:

input:
[MASK] [MASK] [MASK] 是中国神魔小说的经典之作,与《三国演义》《水浒传》《红楼梦》并称为中国古典四大名著。
output:
{
    "bert-base-chinese": "《 神 》",
    "hfl/chinese-bert-wwm": "天 神 奇",
    "nghuyong/ernie-1.0-base-zh": "西 游 记"
}

可以看到ERNIE模型能准确预测出「西游记」,在实体理解场景下ERNIE确实具备显著的优势!


最后放一下模型转换和测试的代码,欢迎star :)

GitHub - nghuyong/ERNIE-Pytorch: ERNIE Pytorch Version

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
`transformers` 是一个基于 PyTorch 和 TensorFlow 的自然语言处理模型库,它提供了丰富的函数和类,可以用于构建、训练和使用各种预训练的语言模型。下面列举一些常用的函数: - `AutoTokenizer.from_pretrained(model_name_or_path, *args, **kwargs)`: 根据模型名称或路径创建一个 tokenizer 对象,用于将文本转换为模型可以处理的输入格式。 - `AutoModel.from_pretrained(model_name_or_path, *args, **kwargs)`: 根据模型名称或路径创建一个模型对象,用于进行文本的编码、解码和生成等操作。 - `AutoConfig.from_pretrained(model_name_or_path, *args, **kwargs)`: 根据模型名称或路径创建一个配置对象,用于配置模型的参数和超参数。 - `Trainer(model, args, train_dataset, eval_dataset=None, data_collator=None, tokenizer=None, compute_metrics=None, callbacks=None, optimizers=None, lr_scheduler=None, model_init=None, **kwargs)`: 创建一个训练器对象,用于对模型进行训练、评估和预测等操作。 - `pipeline(task, model=None, tokenizer=None, framework='pt', **kwargs)`: 创建一个管道对象,用于对输入文本进行特定任务的处理,例如文本分类、实体识别、问答等。 - `set_seed(seed)`: 设置随机数种子,用于确保实验的可重复性。 - `get_linear_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, last_epoch=-1)`: 创建一个学习率调度器对象,用于在训练过程动态调整学习率。 - `AdamW(params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.0, correct_bias=True)`: 创建一个 AdamW 优化器对象,用于优化模型的参数。 - `get_cosine_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, num_cycles=0.5, last_epoch=-1)`: 创建一个余弦退火学习率调度器对象,用于在训练过程动态调整学习率。 - `get_polynomial_decay_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, lr_end=0.0, power=1.0, last_epoch=-1)`: 创建一个多项式衰减学习率调度器对象,用于在训练过程动态调整学习率。 这些函数只是 `transformers` 提供的众多函数的几个常用函数,具体使用方式和参数可以参考 `transformers` 的文档。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nghuyong

您的鼓励是我创作的最大动力~

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

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

打赏作者

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

抵扣说明:

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

余额充值