无监督语义相似度匹配之Bert抽取文本特征实战

今天记一次采用bert抽取句子向量的实战过程,主要是想感受一下bert抽取出来的句子特征向量是否真的具有不错的语义表达。

在此之前,我们来回顾一下,如果我们想拿到一个句子的特征向量可以采用什么样的方式(ps 这些下方总结只是笔者在工作中学到的一些文本向量抽取方式,可能并未收集齐全):

基于词袋模型(Bag of Words)
  • Bag of Words : 主要思想是基于对句子中字出现的次数来构建句子向量,向量大小即为词表大小。可以采用的工具是gensim中的doc2bow
  • TF-IDF:在BOW的基础上,考虑到每个字的重要程度,向量大小依然等于词表大小。可以采用的工具是gensim中的TfidfModel
基于无监督神经网络模型
  • 词向量的平均(mean):直观理解就是将句子中每个词的词向量求平均,向量维度等于词向量维度。可以使用工具是gensim中的word2vec。
  • Doc2Vec:主要借鉴了word2vec思想去训练句子向量,向量维度可以自己设置。可以使用工具是gensim中的doc2vec。
  • Bert 生成的句子向量:BERT的每一层的输出其实都可以看作句子的向量,你可以有很多种方式去抽取文本向量,比如官方给出的取最后四层的句子向量拼接(输出维度:[maxlen,768*4])或者求平均(输出维度:[maxlen,768]。后续也许你需要在对句子向量求一下平均,这样文本向量的维度就为768。 可以采用的工具是官方开源的代码中的extract_features.py,当然也可以采用一些其他方式,我在实战部分会介绍另外一种。
基于文本主题的模型(这个词不是很严谨)
  • LDA 主题模型:在词袋模型的基础上通过文本中主题的分布去表示文本向量,向量维度等于预设主题的个数。可以采用工具是gensim中的LdaModel
  • LSI 隐语义模型:也是需要预设文本主题的个数,在词袋模型的基础上采用矩阵分解的方式去表示句子向量,向量维度等于预设主题的个数。可以采用工具是gensim中的LSI

行文至此突然发现gensim真是文本处理这块不可不学习的python包,但更重要的是需要掌握每种方法的原理以及使用场景。由于笔者也在学习过程当中,实战经验也不是很足,还不能够很好的描述各方法的原理和以及了解各方法的适用场景,就不在这误人子弟了。

当然你也可以针对有监督的任务去训练一个词向量,但是由于在工业界,有监督的数据通常很难获取。所以词袋模型,无监督的神经网络模型还有LDA等是经常被采用的文本向量化技术。接下来进入实战部分。

实战部分

准备工作:

import numpy as np
from bert4keras.bert import build_bert_model
from bert4keras.tokenizer import Tokenizer, load_vocab

接下来定义四个函数:

  • build_tokenizer : 加载bert的tokenizer,主要是产生句子bert的输入向量。
  • build_model:加载预训练的bert模型。
  • generate_mask:将句子padding为0的的部分mask掉。
  • extract_emb_feature:抽取句子向量,这里笔者实现的是直接将bert最后一层的句子向量取平均。
###加载tokenizer
def build_tokenizer(dict_path):
    token_dict = load_vocab(dict_path)
    tokenizer = Tokenizer(token_dict, do_lower_case=True)  
    return tokenizer

###加载 bert 模型
def build_model(config_path,checkpoint_path):
    bert_model = build_bert_model(config_path,checkpoint_path)
    return bert_model

###生成mask矩阵
def generate_mask(sen_list,max_len):
    len_list = [len(i) if len(i)<=max_len else max_len for i in sen_list]
    array_mask = np.array([np.hstack((np.ones(j),np.zeros(max_len-j))) for j in len_list])
    return np.expand_dims(array_mask,axis=2)

###生成句子向量特征
def extract_emb_feature(model,tokenizer,sentences,max_len,mask_if=False):
    mask = generate_mask(sentences,max_len)
    token_ids_list = []
    segment_ids_list = []
    for sen in sentences:
        token_ids, segment_ids = tokenizer.encode(sen,first_length=max_len)
        token_ids_list.append(token_ids)
        segment_ids_list.append(segment_ids)
    result = model.predict([np.array(token_ids_list), np.array(segment_ids_list)])
    if mask_if:
        result = result * mask
    return np.mean(result,axis=1)

你需要定义好预训练模型的词库文件,配置文件,模型参数地址,然后加载bert的tokenizer和模型。

"""
chinese_wwm_L-12_H-768_A-12.zip
    |- bert_model.ckpt      # 模型权重
    |- bert_model.meta      # 模型meta信息
    |- bert_model.index     # 模型index信息
    |- bert_config.json     # 模型参数
    |- vocab.txt            # 词表
"""
dict_path = "./chinese_wwm_L-12_H-768_A-12/ bert_model"
config_path = "./chinese_wwm_L-12_H-768_A-12/bert_config.json"
checkpoint_path = "./chinese_wwm_L-12_H-768_A-12/vocab.txt"

tokenizer = build_tokenizer(dict_path)
model = build_model(config_path,checkpoint_path)

然后笔者用bert提取了"这台苹果真是好用","这颗苹果真是好吃","苹果电脑很好","这台小米真是好用",四句话的文本向量,计算了一下两两句子间的cosine相似度。

sentences = ["这台苹果真是好用","这颗苹果真是好吃","苹果电脑很好","这台小米真是好用"]
sentence_emb = extract_emb_feature(model,tokenizer,sentences,200)
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(sentence_emb)

结果如下:我们发现"这台苹果真是好用""这颗苹果真是好吃"的相似度(0.92)就比和"苹果电脑很好"的相似度(0.96)要低。这充分显示出bert对 水果“苹果” 和电脑“苹果”还是做了比较好的区别。

无mask

笔者用mask了padding为0的地方后,句子相识度结果排序变化不大,但是相似度数值之间的差距变大了(方差变大),这说明mask还是对文本向量的提取有比较正向的作用。

sentences = ["这台苹果真是好用","这颗苹果真好吃","苹果电脑很好","这台小米真是好用"]
sentence_emb = extract_emb_feature(model,tokenizer,sentences,200,mask_if=True)
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(sentence_emb)
含mask

结语

如果熟悉bert的同学会知道,如下图所示:其实句子向量的第一个token[CLS] 的向量经常代表句子向量取做下游分类任务的finetune,这里为啥笔者未直接使用[CLS]的向量呢,这就是深度学习玄学的部分:具笔者了解[CLS]向量在下游任务做finetuning的时候会比较好的文本向量表示。而直接采用bert做特征抽取时[CLS]向量的威力就没那么强了。至于到底采用何种方式用bert抽取文本句子向量是最好的方式,我也不知道,还是留给大家探索去吧。

bert

参考文献

https://www.lizenghai.com/archives/28761.html
https://github.com/bojone/bert4keras

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 文章写得比较长,先列出大纲,以便读者直取重点。 “文本分类对抗攻击”是清华大学和阿里安全2020年2月举办的一场A...
    xieyan0811阅读 2,560评论 1 2
  • 论文解读:Bert原理深入浅出 Bert 自 Google 于 2018 年发表至今,一直给人们带来惊喜,期间也陆...
    随时学丫阅读 12,110评论 0 8
  • 前面的文章主要从理论的角度介绍了自然语言人机对话系统所可能涉及到的多个领域的经典模型和基础知识。这篇文章,甚至之后...
    我偏笑_NSNirvana阅读 13,805评论 2 64
  • 阴天 空气中带烦躁忧伤的味道 像打了麻药无处可逃 争吵,谩骂,泪水,脾气暴躁 像失去方向盘的捷豹 你说我不知恩图报...
    孙小小小小妞阅读 184评论 0 1
  • 拯救 作者: 月满船 1 min read 0人收录 当你处在一段艰难的时光里,漫漫长夜无疑需要你孤身一人泅渡...
    巴山夜雨十年灯阅读 139评论 0 0