BERT是谷歌公司于2018年11月发布的一款新模型,它一种预训练语言表示的方法,在大量文本语料(维基百科)上训练了一个通用的“语言理解”模型,然后用这个模型去执行想做的NLP任务。一经公布,它便引爆了整个NLP界,其在11个主流NLP任务中都取得优异的结果,因此成为NLP领域最吸引人的一个模型。简单来说,BERT就是在训练了大量的文本语料(无监督)之后,能够在对英语中的单词(或中文的汉字)给出一个向量表示,使得该单词(或汉字)具有一定的语义表示能力,因此,BERT具有一定的先验知识,在NLP任务中表现十分抢眼。

  在文章利用bert-serving-server搭建bert词向量服务(一) 中,作者简洁明了地介绍了如何利用bert-serving-server来获取中文汉字的词向量,这大大降低了一般从业者使用BERT的门槛。

  结合笔者这段时间的工作体会以及思考,笔者尝试着给出BERT的几个可能的应用,如下:

  • NLP基本任务
  • 查找相似词语
  • 提取文本中的实体
  • 问答中的实体对齐

由于笔者才疏学浅且撰写文章时间仓促,文章中有不足之处,请读者多多批评指正!

NLP基本任务

  BERT公布已经半年多了,现在已经成为NLP中的深度学习模型中必不可少的工具,一般会加载在模型中的Embedding层。由于篇幅原因,笔者不再介绍自己的BERT项目,而是介绍几个BERT在基本任务中的Github项目:

可以看到,BERT已经广泛应用于NLP基本任务中,在开源项目中导出可以见到它的身影,并且这些项目的作者也写了非常细致的代码工程,便于上手。


  在具体讲述下面的三个应用前,我们先了解下BERT应用的项目结构,如下:

其中,bert_client_lmj.py为调用BERT词向量服务,具体可参考文章利用bert-serving-server搭建bert词向量服务(一) ,完整的Python代码如下:

# -*- coding:utf-8 -*-
from bert_serving.client import BertClient
from sklearn.metrics.pairwise import cosine_similarity class Encoding(object):
def __init__(self):
self.server_ip = "127.0.0.1"
self.bert_client = BertClient(ip=self.server_ip) def encode(self, query):
tensor = self.bert_client.encode([query])
return tensor def query_similarity(self, query_list):
tensors = self.bert_client.encode(query_list)
return cosine_similarity(tensors)[0][1] if __name__ == "__main__":
ec = Encoding()
print(ec.encode("中国").shape)
print(ec.encode("美国").shape)
print("中国和美国的向量相似度:", ec.query_similarity(["中国", "美国"]))

查找相似词语

  利用词向量可以查找文章中与指定词语最相近的几个词语。具体的做法为:现将文章分词,对分词后的每个词,查询其与指定词语的相似度,最后按相似度输出词语即可。我们的示例文章为老舍的《养花》,内容如下:

我爱花,所以也爱养花。我可还没成为养花专家,因为没有工夫去研究和试验。我只把养花当做生活中的一种乐趣,花开得大小好坏都不计较,只要开花,我就高兴。在我的小院子里,一到夏天满是花草,小猫只好上房去玩,地上没有它们的运动场。

花虽然多,但是没有奇花异草。珍贵的花草不易养活,看着一棵好花生病要死,是件难过的事。北京的气候,对养花来说不算很好,冬天冷,春天多风,夏天不是干旱就是大雨倾盆,秋天最好,可是会忽然闹霜冻。在这种气候里,想把南方的好花养活,我还没有那么大的本事。因此,我只养些好种易活、自己会奋斗的花草。

不过,尽管花草自己会奋斗,我若是置之不理,任其自生自灭,大半还是会死的。我得天天照管它们,像好朋友似的关心它们。一来二去,我摸着一些门道:有的喜阴,就别放在太阳地里;有的喜干,就别多浇水。摸着门道,花草养活了,而且三年五载老活着、开花,多么有意思啊!不是乱吹,这就是知识呀!多得些知识决不是坏事。

我不是有腿病吗,不但不利于行,也不利于久坐。我不知道花草们受我的照顾,感谢我不感谢;我可得感谢它们。我工作的时候,我总是写一会儿就到院中去看看,浇浇这棵,搬搬那盆,然后回到屋里再写一会儿,然后再出去。如此循环,让脑力劳动和体力劳动得到适当的调节,有益身心,胜于吃药。要是赶上狂风暴雨或天气突变,就得全家动员,抢救花草,十分紧张。几百盆花,都要很快地抢到屋里去,使人腰酸腿疼,热汗直流。第二天,天气好了,又得把花都搬出去,就又一次腰酸腿疼,热汗直流。可是,这多么有意思呀!不劳动,连棵花也养不活,这难道不是真理吗?

送牛奶的同志进门就夸“好香”,这使我们全家都感到骄傲。赶到昙花开放的时候,约几位朋友来看看,更有秉烛夜游的味道——昙花总在夜里开放。花分根了,一棵分为几棵,就赠给朋友们一些。看着友人拿走自己的劳动果实,心里自然特别欢喜。

当然,也有伤心的时候,今年夏天就有这么一回。三百棵菊秧还在地上(没到移入盆中的时候),下了暴雨,邻家的墙倒了,菊秧被砸死三十多种,一百多棵。全家人几天都没有笑容。

有喜有忧,有笑有泪,有花有果,有香有色,既须劳动,又长见识,这就是养花的乐趣。

指定词语为“开心”,查询《养花》一文中与“开心”最为接近的5个词语,完整的Python代码如下:(find_similar_words.py)

# -*- coding:utf-8 -*-
import jieba
from bert_client_lmj import Encoding
from operator import itemgetter # 读取文章
with open('./doc.txt', 'r', encoding='utf-8') as f:
content = f.read().replace('\n', '') ec = Encoding()
similar_word_dict = {} # 查找文章中与'开心'的最接近的词语
words = list(jieba.cut(content))
for word in words:
print(word)
if word not in similar_word_dict.keys():
similar_word_dict[word] = ec.query_similarity([word, '开心']) # 按相似度从高到低排序
sorted_dict = sorted(similar_word_dict.items(), key=itemgetter(1), reverse=True) print('与%s最接近的5个词语及相似度如下:' % '开心')
for _ in sorted_dict[:5]:
print(_)

输出的结果如下:

与开心最接近的5个词语及相似度如下:
('难过', 0.9070794)
('高兴', 0.89517105)
('乐趣', 0.89260685)
('骄傲', 0.87363803)
('我爱花', 0.86954254)

提取文本中的实体

  在事件抽取中,我们往往需要抽取一些指定的元素,比如在下面的句子中,

巴基斯坦当地时间2014年12月16日早晨,巴基斯坦塔利班运动武装分子袭击了西北部白沙瓦市一所军人子弟学校,打死141人,其中132人为12岁至16岁的学生。

我们需要抽取袭击者,也就是恐怖组织这个元素。

  直接从句法分析,也许可以得到一定的效果,但由于事件描述方式多变,句法分析会显得比较复杂且效果不一定能保证。这时候,我们尝试BERT词向量,它在一定程度上可以作为补充策略,帮助我们定位到事件的元素。具体的想法如下:

  • 指定事件元素模板
  • 句子分词,对词语做n-gram
  • 查询每个n-gram与模板的相似度
  • 按相似度对n-gram排序,取相似度最高的n-gram

在这里,我们的事件元素为恐怖组织,指定的模板为“伊斯兰组织”,完整的Python程序如下(find_similar_entity_in_sentence.py):

# -*- coding:utf-8 -*-

import jieba
from operator import itemgetter
from bert_client_lmj import Encoding # 创建n-gram
def compute_ngrams(sequence, n):
lst = list(zip(*[sequence[index:] for index in range(n)]))
for i in range(len(lst)):
lst[i] = ''.join(lst[i])
return lst # 模板
template = '伊斯兰组织'
# 示例句子
doc = "巴基斯坦当地时间2014年12月16日早晨,巴基斯坦塔利班运动武装分子袭击了西北部白沙瓦市一所军人子弟学校,打死141人,其中132人为12岁至16岁的学生。" words = list(jieba.cut(doc))
all_lst = []
for j in range(1, 5):
all_lst.extend(compute_ngrams(words, j)) ec = Encoding()
similar_word_dict = {} # 查找文章中与template的最接近的词语
for word in all_lst:
print(word)
if word not in similar_word_dict.keys():
similar_word_dict[word] = ec.query_similarity([word, template]) # 按相似度从高到低排序
sorted_dict = sorted(similar_word_dict.items(), key=itemgetter(1), reverse=True) print('与%s最接近的实体是: %s,相似度为 %s.' %(template, sorted_dict[0][0], sorted_dict[0][1]))

输出的结果如下:

与伊斯兰组织最接近的实体是: 塔利班运动武装分子,相似度为 0.8953854.

可以看到,该算法成功地帮助我们定位到了恐怖组织:塔利班运动武装分子,效果很好,但是由于是无监督产生的词向量,效果不一定可控,而且该算法运行速度较慢,这点可以从工程上加以改进。

问答中的实体对齐

  在智能问答中,我们往往会采用知识图谱或者数据库存储实体,其中一个难点就是实体对齐。举个例子,我们在数据库中储存的实体如下:(entities.txt)

094型/晋级

052C型(旅洋Ⅱ级)

辽宁舰/瓦良格/Varyag

杰拉尔德·R·福特号航空母舰

052D型(旅洋III级)

054A型

CVN-72/林肯号/Lincoln

这样的实体名字很复杂,如果用户想查询实体“辽宁舰”,就会碰到困难,但是由于实体以储存在数据库或知识图谱中,实体不好直接修改。一种办法是通过关键字匹配定位实体,在这里,我们可以借助BERT词向量来实现,完整的Python代码如下:(Entity_Alignment.py)

# -*- coding:utf-8 -*-
from bert_client_lmj import Encoding
from operator import itemgetter with open('entities.txt', 'r', encoding='utf-8') as f:
entities = [_.strip() for _ in f.readlines()] ec = Encoding() def entity_alignment(query): similar_word_dict = {} # 查找已有实体中与query最接近的实体
for entity in entities:
if entity not in similar_word_dict.keys():
similar_word_dict[entity] = ec.query_similarity([entity, query]) # 按相似度从高到低排序
sorted_dict = sorted(similar_word_dict.items(), key=itemgetter(1), reverse=True) return sorted_dict[0] query = '辽宁舰'
result = entity_alignment(query)
print('查询实体:%s,匹配实体:%s 。' %(query, result)) query = '林肯号'
result = entity_alignment(query)
print('查询实体:%s,匹配实体:%s 。' %(query, result))

输出的结果如下:

查询实体:辽宁舰,匹配实体:('辽宁舰/瓦良格/Varyag', 0.8534695) 。
查询实体:林肯号,匹配实体:('CVN-72/林肯号/Lincoln', 0.8389378) 。

  在这里,查询的速度应该不是困难,因为我们可以将已储存的实体以离线的方式查询其词向量并储存,这样进来一个查询到实体,只查询一次词向量,并计算其与离线的词向量的相似度。这种方法也存在缺陷,主要是由于词向量的无监督,实体对齐有时候不会很准,但作为一种补充策略,也许可以考虑。

总结

  本文介绍了笔者这段时间所思考的BERT词向量的几个应用,由于能力有限,文章中会存在考虑不当的地方,还请读者多多批评指正。

  另外,笔者将会持续调研词向量方面的技术,比如腾讯词向量,百度词向量等,欢迎大家关注~

注意:不妨了解下笔者的微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注~

BERT的几个可能的应用的更多相关文章

  1. BERT模型在多类别文本分类时的precision, recall, f1值的计算

    BERT预训练模型在诸多NLP任务中都取得最优的结果.在处理文本分类问题时,即可以直接用BERT模型作为文本分类的模型,也可以将BERT模型的最后层输出的结果作为word embedding导入到我们 ...

  2. NLP句子表征,NLP 的巨人肩膀(下):从 CoVe 到 BERT (转载)

    深度长文:NLP的巨人肩膀(上):https://www.jiqizhixin.com/articles/2018-12-10-17 NLP 的巨人肩膀(下):从 CoVe 到 BERT: https ...

  3. 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史(转载)

    转载 https://zhuanlan.zhihu.com/p/49271699 首发于深度学习前沿笔记 写文章   从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 张 ...

  4. 【算法】Bert预训练源码阅读

    Bert预训练源码 主要代码 地址:https://github.com/google-research/bert create_pretraning_data.py:原始文件转换为训练数据格式 to ...

  5. 文本分类实战(十)—— BERT 预训练模型

    1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...

  6. 【译】BERT表示的可解释性分析

    目录 从词袋模型到BERT 分析BERT表示 不考虑上下文的方法 考虑语境的方法 结论 本文翻译自Are BERT Features InterBERTible? 从词袋模型到BERT ​ Mikol ...

  7. 【译】为什么BERT有3个嵌入层,它们都是如何实现的

    目录 引言 概览 Token Embeddings 作用 实现 Segment Embeddings 作用 实现 Position Embeddings 作用 实现 合成表示 结论 参考文献 本文翻译 ...

  8. 【译】深度双向Transformer预训练【BERT第一作者分享】

    目录 NLP中的预训练 语境表示 语境表示相关研究 存在的问题 BERT的解决方案 任务一:Masked LM 任务二:预测下一句 BERT 输入表示 模型结构--Transformer编码器 Tra ...

  9. 图解BERT(NLP中的迁移学习)

    目录 一.例子:句子分类 二.模型架构 模型的输入 模型的输出 三.与卷积网络并行 四.嵌入表示的新时代 回顾一下词嵌入 ELMo: 语境的重要性 五.ULM-FiT:搞懂NLP中的迁移学习 六.Tr ...

  10. 深入理解BERT Transformer ,不仅仅是注意力机制

    来源商业新知网,原标题:深入理解BERT Transformer ,不仅仅是注意力机制 BERT是google最近提出的一个自然语言处理模型,它在许多任务 检测上表现非常好. 如:问答.自然语言推断和 ...

随机推荐

  1. odoo写邮件添加收件人

    在任何可以写消息的地方点击鼠标     或者回复消息     写消息的框会聚焦并变大             点击撰写框右上角的弹出窗图标     弹出完整的撰写消息窗口     在红色的地方添加收件 ...

  2. LeetCode——Reverse Integer

    Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 Have you ...

  3. 【转载】C#中的泛型

    1.1 C#中的泛型 .Net 1.1版本最受诟病的一个缺陷就是没有提供对泛型的支持.通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱.拆箱,在一定程度上提升 ...

  4. chrome.declarativeWebRequest

    chrome.declarativeWebRequest 清单文件 规则 条件与操作的求值 使用优先级覆盖规则 类型 HeaderFilter RequestMatcher CancelRequest ...

  5. openwrt gstreamer实例学习笔记(三.深入了解gstreamer 的 Element)

    在前面的部分,我们简要介绍过 GstElementFactory 可以用来创建一个element的实例,但是GstElementFactory不仅仅只能做这件事,GstElementFactory作为 ...

  6. 1449: [JSOI2009]球队收益

    1449: [JSOI2009]球队收益 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 757  Solved: 437[Submit][Status][ ...

  7. Mac版idea使用总结

    1.设置文档注释快捷键:快捷键设置里搜索 Fix doc comment 2.IDEA不显示项目project视图(转载于 https://blog.csdn.net/oyimiyangguang12 ...

  8. diamond简介和使用

    简介 diamond是淘宝内部使用的一个管理持久配置的系统,它的特点是简单.可靠.易用,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理. diamond为应用系统提供了获取配置的服务, ...

  9. Java中的文件上传和下载

    文件上传原理: 早期的文件上传机制: 在TCP/IP中.最早出现的文件上传机制是FTP.他是将文件由客户端发送到服务器的标准机制. jsp中的文件上传机制: 在jsp编程中不能使用FTP的方法来上传文 ...

  10. CH 5402 选课(分组背包+树形DP)

    CH 5402 选课 \(solution:\) 很有讨论套路的一道题,利用树的结构来表示出不同课程之间的包含关系(这里还要建一个虚点将森林变成一颗打大树).然后用子树这个概念巧妙的消除了因为这些包含 ...