ERNIE是什么
![a27e4910b147296d89bd962a30cf5660.jpeg](https://i-blog.csdnimg.cn/blog_migrate/11a66c993cdd6bf2fcf46f62204455e0.jpeg)
文心大模型ERNIE是百度发布的产业级知识增强大模型,涵盖了NLP大模型和跨模态大模型。在中文场景下,ERNIE有明显的优势,目前已经发布了一系列模型,包括ERNIE1.0, ERNIE2.0, ERNIE3.0, ERNIE-Gram, ERNIE-Doc等,并且一直在持续更新中。ERNIE官方的代码和模型是PaddlePaddle版本的,具体可以参见:PaddlePaddle/ERNIE 和 PaddlePaddle/PaddleNLP 这两个repo。
在transformers中调用ERNIE
但是目前学术界和工业界在NLP大模型方面一般都会基于 huggingface/transformers 来开展工作。所以就会产生很强烈的动机将ERNIE从PaddlePaddle版本转换到Pytorch版本,这里的转换包括模型的代码和模型的参数。经过漫长的code review,本人提交的ERNIE模型最终合入了transformers中,并在4.22.0版本中可以直接体验了!!
![250faa0135eb5818de55446fe7c5ea47.png](https://i-blog.csdnimg.cn/blog_migrate/8f7122b7a813c8c19e8b01ec854180f8.png)
快速开始
首先将`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://i-blog.csdnimg.cn/blog_migrate/207189179bb2e571c1c20aed4f888d7e.jpeg)
输出验证
为了快速检验我们模型转换的是否正确,我们可以将官方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