也来玩玩目前最大的中文GPT2模型(bert4keras)

断了今生、忘了曾经 提交于 2020-11-27 20:50:27

©PaperWeekly 原创 · 作者|苏剑林

单位|追一科技

研究方向|NLP、神经网络

相信不少读者这几天都看到了清华大学与智源人工智能研究院一起搞的“清源计划”(相关链接《中文版GPT-3来了?智源研究院发布清源 CPM —— 以中文为核心的大规模预训练模型》),里边开源了目前最大的中文 GPT2 模型 CPM-LM(26 亿参数),据说未来还会开源 200 亿甚至 1000 亿参数的模型,要打造“中文界的 GPT3”。

▲ 官方给出的CPM-LM的Few Shot效果演示图

我们知道,GPT3 不需要 finetune 就可以实现 Few Shot,而目前 CPM-LM 的演示例子中,Few Shot 的效果也是相当不错的,让人跃跃欲试,笔者也不例外。既然要尝试,肯定要将它适配到自己的 bert4keras 中才顺手,于是适配工作便开始了。本以为这是一件很轻松的事情,谁知道踩坑踩了快 3 天才把它搞好,在此把踩坑与测试的过程稍微记录一下。

模型介绍

该计划发布的第一个模型称为 CPM-LM,参数大约为 26 亿,预训练中文数据规模 100GB,是一个单向的语言模型,其他细节大家自行到下面的链接阅读就好。这么大的参数量,一般我们都是直接使用而不考虑去 finetune 它的了,它所具备的能力就是无条件地随机生成文本,当然我们也可以实现给它一些引导,然后用它来实现文本续写,至于 Few Shot 之类的应用,本质上也都是文本续写的变式。

主页:

https://cpm.baai.ac.cn/

GitHub:

https://github.com/TsinghuaAI/CPM-Generate

公众号:

中文版GPT-3来了?智源研究院发布清源 CPM —— 以中文为核心的大规模预训练模型

这里说一下模型结构的问题,也是笔者在适配过程中踩的第一个坑。CPM-LM 的模型架构跟 OpenAI 的 GPT2 是一样的,所以说白了这就是一个 26 亿参数的中文 GPT2 模型。

开始笔者没认真看,然后又被 CPM-LM-TF2 项目 [1] 稍微误导了一下,导致在前期以为它的结构跟 GPT2_ML [2] 一样(GPT2_ML 既不是 GPT,也不是 GPT2,它介乎两者之间),很久都没调出合理的结果。

而意识到这个问题后,重新搭建 GPT2 模型并且适配对应的权重,也不是什么难事了,包括权重转换到 tf 格式,有了 CPM-LM-TF2 项目 [1] 的参照,也不算困难。

Tokenizer

在适配过程中踩到的第二个,是关于 tokenizer 的。不得不说,CPM-LM 所写的 tokenizer,在笔者看来实在是难登大雅之堂,至今仍然我耿耿于怀。

该 tokenizer 实际上就是在 Google 的 sentencepiece 的基础上包装了一下,但是又包得特别不优雅,简直是强迫症患者的噩梦。

具体来说,像 BERT 的 tokenizer 或者 sentencepiece 这类分词工具,都会默认去掉空格、换行符等分隔符,但是 CPM-LM 想要将空格和换行符保留,所以在送入 tokenizer 之前将它们替换为了别的符号(目前是空格替换为“▂”、换行符替换为“▃”),最后输出之前再替换回来。

这是一种常见的做法,是可以理解的,但我最不能理解的是换行符的替代符号“▃”居然不在它的 sentencepiece 模型的词表中!为了避免“▃”变成,CPM-LM 又将它替换为,也就是做了二次替换,才得到换行符的 id...

笔者第一次看到这样的设计时,内心是简直要崩溃的:往 sentencepiece 里边多加入个字符有这么难吗,何至于写成这样...没办法,开源模型的才是大佬,只能想办法适配它了。笔者想了很久很久,对 bert4keras 原有的 SpTokenizer 修修补补了一番,总算勉强把它搞好了。

使用测试

吐槽就到这里吧,总之,经过笔者两天多的折腾,从 0.9.3 版本开始, bert4keras 就可以加载 CPM-LM 模型了,单跑预测估计需要 16G 以上的显存(我自己是 22G 的 RTX)。模型权重的转换过程与基本的加载方案可见:

GitHub:https://github.com/bojone/CPM_LM_bert4keras

一些 Few Shot 效果(输出结果会有一定的随机性,如果只关心 Few Shot 效果,可以考虑将解码方式换为 beam search):

# 常识推理
# 本例输出:北京
query = u"""
美国的首都是华盛顿
法国的首都是巴黎
日本的首都是东京
中国的首都是
"""
print(text_expansion.generate(query[1:-1], 1)[0])

# 单词翻译
# 本例输出:bird
query = u"""
狗 dog
猫 cat
猪 pig
鸟 
"""
print(text_expansion.generate(query[1:-1], 1)[0])

# 主语抽取
# 本例输出:杨振宁
query = u"""
从1931年起,华罗庚在清华大学边学习边工作 华罗庚
在一间简陋的房间里,陈景润攻克了“哥德巴赫猜想” 陈景润
在这里,丘成桐得到IBM奖学金 丘成桐
杨振宁在粒子物理学、统计力学和凝聚态物理等领域作出里程碑性贡献 
"""
print(text_expansion.generate(query[1:-1], 1)[0])

# 三元组抽取
# 本例输出:张红,体重,140斤
query = u"""
姚明的身高是211cm,是很多人心目中的偶像。 ->姚明,身高,211cm
虽然周杰伦在欧洲办的婚礼,但是他是土生土长的中国人->周杰伦,国籍,中国
小明出生于武汉,但是却不喜欢在武汉生成,长大后去了北京。->小明,出生地,武汉
吴亦凡是很多人的偶像,但是他却是加拿大人,另很多人失望->吴亦凡,国籍,加拿大
武耀的生日在5月8号,这一天,大家都为他庆祝了生日->武耀,生日,5月8号
《青花瓷》是周杰伦最得意的一首歌。->周杰伦,作品,《青花瓷》
北京是中国的首都。->中国,首都,北京
蒋碧的家乡在盘龙城,毕业后去了深圳工作。->蒋碧,籍贯,盘龙城
上周我们和王立一起去了他的家乡云南玩昨天才回到了武汉。->王立,籍贯,云南
昨天11月17号,我和朋友一起去了海底捞,期间服务员为我的朋友刘章庆祝了生日。->刘章,生日,11月17号
张红的体重达到了140斤,她很苦恼。->
"""
print(text_expansion.generate(query[1:-1], 1)[0])

文章小结

文章简单介绍了一个清华大学新开源的 26 亿参数的 GPT2 模型 CPM-LM,并将它适配到了 bert4keras 框架内,稍微吐槽了一下转换过程中遇到的坑,最后演示了一下 CPM-LM 还不错的 Few Shot 效果。

参考文献

[1] https://github.com/qhduan/CPM-LM-TF2/

[2] https://github.com/imcaspar/gpt2-ml

更多阅读

#投 稿 通 道#

 让你的论文被更多人看到 

如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。

总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。 

PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得技术干货。我们的目的只有一个,让知识真正流动起来。

???? 来稿标准:

• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向) 

• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接 

• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志

???? 投稿邮箱:

• 投稿邮箱:hr@paperweekly.site 

• 所有文章配图,请单独在附件中发送 

• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通

????

现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧

关于PaperWeekly

PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!