BERT实现QA中的问句语义相似度计算

2020 年 6 月 29 日 AINLP

1. BERT 语义相似度

BERT的全称是Bidirectional Encoder Representation from Transformers,是Google2018年提出的预训练模型,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法上,即用了Masked LM和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。

有一个这样的场景,QA对话系统,希望能够在问答库中找到与用户问题相似的句子对,然后把答案返回给用户。这篇就是要解决这个问题的。

关于 BERT 的原理知识请访问: http://mantchs.com/2019/09/28/NLP/BERT/

下面介绍一个封装好的 BERT 工具,利用该工具能够快速的得到词向量表示。该工具的名称叫做: bert-as-service,从名称就可以看出作者是把 BERT 作为一种服务了,只要调用该服务就能够得到我们想要的向量表示,得到向量以后,就可以通过余弦相似度的计算公式计算向量之间的相似度。

bert-as-service 源码详见: https://github.com/hanxiao/bert-as-service

bert-as-service 使用文档: https://bert-as-service.readthedocs.io/en/latest/index.html

步骤如下:

  1. 安装 bert-as-service 的服务端和客户端。
  2. 预训练 BERT 模型。
  3. 客户端编写代码请求服务端得到句向量。
  4. 句子与句子向量之间计算相似度,并返回 top_k 个结果。

2. 安装 bert-as-service

  1. 环境要求:

    Python版本 >= 3.5,Tensorflow版本 >= 1.10

    (本人环境,Python = 3.7    Tensorflow = 1.13.1)

  2. 安装服务端和客户端

    pip install -U bert-serving-server bert-serving-client

3. 启动 BERT 服务

  1. 下载预训练模型

    Google AI发布的经过预训练的BERT模型。这里我们下载 BERT-Base, Chinese,12-layer, 768-hidden, 12-heads, 110M parameters。

    链接:

    https://pan.baidu.com/s/1jJudiTj__vbFb0WkEQUxWw

    密码:mf4p

  2. 启动服务

    解压缩后,运行如下命令进行启动,目录换成解压后的路径。(-num_worker指定使用多少个CPU)

    bert-serving-start -model_dir /Users/mantch/Downloads/chinese_L-12_H-768_A-12 -num_worker=4

    运行后会看到如下结果:

        http_max_connect = 10
    http_port = None
    mask_cls_sep = False
    max_batch_size = 256
    max_seq_len = 25
    model_dir = /Users/mantch/Downloads/chinese_L-12_H-768_A-12
    no_position_embeddings = False
    no_special_token = False
    num_worker = 4
    pooling_layer = [-2]
    pooling_strategy = REDUCE_MEAN
    port = 5555
    port_out = 5556
    prefetch_size = 10
    priority_batch_size = 16
    show_tokens_to_client = False
    tuned_model_dir = None
    verbose = False
    xla = False

    其中就已经显示了port = 5555,port_out = 5556 等端口号信息。

    如果显示以下信息就表示可以使用了

    I:WORKER-0:[__i:gen:559]:ready and listening!
    I:WORKER-3:[__i:gen:559]:ready and listening!
    I:WORKER-1:[__i:gen:559]:ready and listening!
    I:WORKER-2:[__i:gen:559]:ready and listening!
    I:VENTILATOR:[__i:_ru:164]:all set, ready to serve request!

4. 相似度计算

  1. 数据集

    我们使用蚂蚁金服语义相似度比赛的一份数据集,该数据集分为 4 列,第一列是索引,第二列和第三列是句子,第四列中的 1 表示这两个句子是同义句,否则表示为 0。

    数据集下载地址: https://www.lanzous.com/ia9dg8b

  2. 编写代码

    import pandas as pd
    import numpy as np
    from bert_serving.client import BertClient
    from termcolor import colored

    num = 100 # 采样数
    topk = 5 # 返回 topk 个结果

    # 读取数据集
    sentence_csv = pd.read_csv('atec_nlp_sim_train_all.csv', sep='\t', names=['idx', 's1', 's2', 'label'])
    sentences = sentence_csv['s1'].tolist()[:num]
    print('%d questions loaded, avg.len %d' % (len(sentences), np.mean([len(d) for d in sentences])))


    with BertClient(port=5555, port_out=5556) as bc:

    # 获取句子向量编码
    doc_vecs = bc.encode(sentences)

    while True:
    query = input(colored('your question:', 'green'))
    query_vec = bc.encode([query])[0]

    # 余弦相似度 分数计算。
    # np.linalg.norm 是求取向量的二范数,也就是向量长度。
    score = np.sum(query_vec * doc_vecs, axis=1) / np.linalg.norm(doc_vecs, axis=1)

    '''
    argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引)

    [::-1]取从后向前(相反)的元素, 例如[ 1 2 3 4 5 ]
    则输出为[ 5 4 3 2 1 ]
    '''

    topk_idx = np.argsort(score)[::-1][:topk]
    print('top %d questions similar to "%s"' % (topk, colored(query, 'green')))
    for idx in topk_idx:
    print('> %s\t%s' % (colored('%.1f' % score[idx], 'cyan'), colored(sentences[idx], 'yellow')))

推荐阅读

用 SQL 而不是 Python 处理文本数据

学自然语言处理,其实更应该学好英语

这个NLP工具,玩得根本停不下来

文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化

Node2Vec 论文+代码笔记

模型压缩实践收尾篇——模型蒸馏以及其他一些技巧实践小结

中文命名实体识别工具(NER)哪家强?

学自然语言处理,其实更应该学好英语

斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。


阅读至此了,分享、点赞、在看三选一吧🙏

登录查看更多
4

相关内容

BERT全称Bidirectional Encoder Representations from Transformers,是预训练语言表示的方法,可以在大型文本语料库(如维基百科)上训练通用的“语言理解”模型,然后将该模型用于下游NLP任务,比如机器翻译、问答。
【斯坦福CS520】向量空间中嵌入的知识图谱推理,48页ppt
专知会员服务
99+阅读 · 2020年6月11日
ExBert — 可视化分析Transformer学到的表示
专知会员服务
30+阅读 · 2019年10月16日
最新BERT相关论文清单,BERT-related Papers
专知会员服务
52+阅读 · 2019年9月29日
【NLP】文本匹配相关方向打卡点总结
深度学习自然语言处理
21+阅读 · 2019年12月9日
论文浅尝 | 使用孪生BERT网络生成句子的嵌入表示
开放知识图谱
25+阅读 · 2019年10月31日
使用 Bert 预训练模型文本分类(内附源码)
数据库开发
102+阅读 · 2019年3月12日
NLP - 基于 BERT 的中文命名实体识别(NER)
AINLP
466+阅读 · 2019年2月10日
如何匹配两段文本的语义?
黑龙江大学自然语言处理实验室
7+阅读 · 2018年7月21日
论文浅尝 | 基于RNN与相似矩阵CNN的知识库问答
开放知识图谱
8+阅读 · 2018年5月29日
Arxiv
20+阅读 · 2019年9月7日
Arxiv
4+阅读 · 2019年9月5日
Arxiv
5+阅读 · 2019年8月22日
Arxiv
11+阅读 · 2019年6月19日
Arxiv
4+阅读 · 2019年2月18日
VIP会员
相关VIP内容
【斯坦福CS520】向量空间中嵌入的知识图谱推理,48页ppt
专知会员服务
99+阅读 · 2020年6月11日
ExBert — 可视化分析Transformer学到的表示
专知会员服务
30+阅读 · 2019年10月16日
最新BERT相关论文清单,BERT-related Papers
专知会员服务
52+阅读 · 2019年9月29日
相关资讯
【NLP】文本匹配相关方向打卡点总结
深度学习自然语言处理
21+阅读 · 2019年12月9日
论文浅尝 | 使用孪生BERT网络生成句子的嵌入表示
开放知识图谱
25+阅读 · 2019年10月31日
使用 Bert 预训练模型文本分类(内附源码)
数据库开发
102+阅读 · 2019年3月12日
NLP - 基于 BERT 的中文命名实体识别(NER)
AINLP
466+阅读 · 2019年2月10日
如何匹配两段文本的语义?
黑龙江大学自然语言处理实验室
7+阅读 · 2018年7月21日
论文浅尝 | 基于RNN与相似矩阵CNN的知识库问答
开放知识图谱
8+阅读 · 2018年5月29日
Top
微信扫码咨询专知VIP会员