这一章我们来聊聊在中文领域都有哪些预训练模型的改良方案。Bert-WWM,MacBert,ChineseBert主要从3个方向在预训练中补充中文文本的信息:词粒度信息,中文笔画信息,拼音信息。与其说是推荐帖,可能更多需要客观看待以下'中文'改良的在实际应用中的效果~
- Take Away: Whole Word Masking全词掩码
- Paper:Bert-WWM,Pre-Training with Whole Word Masking for Chinese BERT
- Github:https://github.com/ymcui/Chinese-BERT-wwm
全词掩码并不是中文的专属,而是google最早在英文预训练任务中提出的。在英文中的使用方式是当word piece tokenizer把一个单词分割成几个部分时,在MASK阶段只要一个部分被掩码,一个单词的其他部分也会被MASK。google提供的英文全词掩码的处理方式如下,很直观就是把所有'##'的部分都补充进掩码
def create_masked_lm_predictions(tokens, masked_lm_prob,
max_predictions_per_seq, vocab_words, rng):
"""Creates the predictions for the masked LM objective."""
cand_indexes = []
for (i, token) in enumerate(tokens):
if token == "[CLS]" or token == "[SEP]":
continue
if (FLAGS.do_whole_word_mask and len(cand_indexes) >= 1 and
token.startswith("##")):
cand_indexes[-1].append(i)
else:
cand_indexes.append([i])
...
而在中文使用中,并不存在字被拆分的情况,因此中文全词是指对词粒度进行掩码。在哈工大开源的Bert/Roberta-WWM系列中,以LTP分词结果作为掩码的最小粒度如下
实现方案其实可以借鉴上面的英文代码,只需要根据分词结果对字符加上'##'前缀,例如'语言模型',正常tokenize会得到['语','言','模','型'], 基于LTP的分词结果['语言','模型'], 只需要把tokenizer调整为['语','##言','模,'##型'],就可以和英文用相同的处理方式了~
这里的全词掩码只影响MLM预训练任务,和下游微调以及模型自身结构无关,因此可以迁移到任意的预训练模型框架和下游任务中。全词掩码有两个优点
但是WWM是否在所有中文任务中都比字符粒度的模型更好呢?在使用过程中感觉也不尽然,例如在做一些信息抽取任务时会发现当抽取信息的粒度和词粒度存在一定不一致时,字符BERT的效果是要显著由于WWM的。猜测是WWM引入了部分词边界信息,和下游任务抽取的边界存在一定冲突。
简单说就是中文词本身的粒度在不同上下文语境中是存在差异的,这是和英文单词最大的差异,而这个差异并不能通过LTP单一的分词器来引入。Ref3的论文也指出在中文字符纠错任务中对WWM的效果并没有BERT好,不过论文只给出了字符+WWM的混合掩码方案,感觉。。。如果预训练模型都需要因地制宜的话,那只能说我们还没找到合适的预训练方案。。。
- Take Away: MLM->纠错任务,解决MASK在预训练和微调的不一致性
- Paper:MacBert, Pre-Training with Whole Word Masking for Chinese BERT
- Github:https://github.com/ymcui/MacBERT
MacBert可能放在中文这里并不太十分合适,其实是针对MASK在预训练和微调中的不一致问题进行的改良。在Bert不完全手册4. 绕开BERT的MASK策略?XLNET & ELECTRA中聊到Electra和XLNET也分别通过生成-判别器,以及乱序语言模型的方案绕开MASK学习双向上下文信息,MacBert给出了另一种方案。
MacBert对原始的MLM任务做了如下调整
在抽取式阅读理解上,MacBert略有提升,其他任务感觉提升不太明显。整体改良非常简单易懂,但是逻辑上其实有一点存疑,就是基于word2vec的相似词替换作为掩码,真的不会导致模型在训练过程中出现信息泄露的问题么?因为部分相似词替换例如高兴->快乐, 下雨->降雨,其实是提供了近乎一样的文本信息的,这种情况下模型其实不需要依赖上下文,直接通过替换后的文本也能进行预测。这里其实和Electra的生成器部分不能太强是有些相似的问题。N-gram的掩码可能一定程度上缓解了这个信息泄露的问题,但感觉这个问题还是存在的~
- Take Away: 引入拼音和笔画信息
- paper: ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information
- Github: https://github.com/ShannonAI/ChineseBert
最后这个模型是有一些起名nb症在的,虽然整体效果提升只能说比随机波动要更显著一些。不过改良的方向,包括拼音和笔画信息的引入比较有意思,相似的方案在一些文本纠错,风控文本变形之类的领域也看到过有类似的应用,所以还是来简单聊聊
相同汉字在不同的场景下会存在发音不同的情况,例如音乐和快乐中,yue发音对应的是乐曲,le对应的发音是喜悦,因此发音和汉字交互后也会提供一定的共享信息。不过一字多音的情况相对少,所以感觉拼音层能提供的信息比较有限。不过类似的方案之前有想在风控领域去做尝试,因为风控中经常会出现同音字的变形,例如把佳琪改写成嘉琪,加7等形式去绕过违禁词封禁。如果使用这里已经与训练好的拼音embedding去在下游进行迁移可能效果会有提升~
这里用了pypinyin来生成文字对应的拼音和声调,例如猫->mao1。拼音复用原始的token,4个声调额外用4个特殊token来表征,拼音部分用特殊字符'-'pad到等长。提取信息这里用了width=2的CNN+max pooling来生成每个字符最终的拼音embedding
笔画信息一定程度给字之间增加了共享信息,例如'江','河','湖','泊'都三点水的偏旁部首,他们存在的上下文也会有一定相似性,因此可以有一部分信息迁移,算是变相增加了上下文信息的丰富程度。不过ChineseBert使用的方式并没有用五笔,而是用了图像信息。使用了仿宋,隶书,行楷三种字体的图片向量化(24243),对3种字体的图片输入进行拼接,然后过全连接层得到每个字符的笔画embedding
在原始Bert token embedding的基础上,加入了拼音和笔画embedding层。特征融合层,简单使用了3个embedding拼接,过全连接层的方式得到融合后的输入embedding,之后的模型结构就和BERT一致了。
BERT手册相关论文和博客详见BertManual
Reference
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳