Keras蚂蚁金服大赛实战——自然语言处理技术(4)

之前在自然语言处理技术系列的第一篇NER实战的结语中介绍过:序列标注(分词,NER),文本分类(情感分析),句子关系判断(语意相似判断),句子生成(机器翻译)是NLP领域的四大任务,之后我又陆续简单介绍了情感分析实战,和Seq2Seq生成对联。今天我们来到这个系列的终章篇——语义相似判断。语义相似判断就是判断两个句子是否具有相同的语义,其应用场景多用于问答系统:

  • 判断两个问句是否具有相同的语义。
  • 判断问题和检索出的答案是否匹配。

当然也可以用于其他场景比如判断两幅图片是否是一样——人脸识别,所以从广义上来说,就是语义相识判断就是判断两个东西是否具有某种相似度的任务。

语义相似判断任务简介

语义相似可以转化为一个分类问题。给模型输入两个句子,然后希望模型判断出两个句子语义是否相似。具体输入输出细节如下:
输入:

  • 1.为何我无法申请开通花呗信用卡收款
  • 2.支付宝开通信用卡花呗收款不符合条件怎么回事

输出:1
如果输出0表示不相似,输出1表示相似。

语义相似判断算法简介

语义相似还是NLP中的老问题,如何将句子映射到到向量空间中同时保持语义,然后我们就可以通过各种距离去衡量句子的相似程度。

  • 上古时期的方式是通过bag of words,tf-idf这种词袋模型去映射句子。
  • 之后出现了word2vector技术,我们就可以将一句话中每个词的的词向量求平均来表示句子向量,后面又出现了借用word2vector的思路实现的sen2vector技术。
  • 最近比较火的当然就是使用深度学习技术将句子映射到向量空间。
    这里我简要的介绍一下我在实战中使用的深度学习模型Siamese Network架构。
    Siamese在英语中是“孪生”、“连体”的意思,而Siamese Network,如下图所示就是两个共享参数的神经网络,其中神经网络部分可以任意构建,使用CNN,RNN之类的都可以。通过同一网络将两个输入映射到向量空间,然后在去计算它们的相似性,相似性度量可以通过:
  • 欧式距离,
  • 余弦距离,
  • 或者给数据打上标签,通过神经网络去判断相似性等。


    Siamese Network

    本次实战就是采用的Siamese-BiLSTM,意思就是用双向的LSTM做共享参数的network部分。

蚂蚁金服大赛实战

读入数据

数据格式如下,每条数据都是两个句子和一个标签。


data

执行下方代码读入数据。

import pandas as pd
train_data = pd.read_csv("./huabei/train.csv",encoding="utf-8",header=None,sep="\t")
val_data = pd.read_csv("./huabei/val.csv",encoding="utf-8",header=None,sep="\t")
train_data[1] = train_data[1].apply(lambda x : [char for char in x])
train_data[2] = train_data[2].apply(lambda x : [char for char in x])
train_data

生成字典

执行下方代码,为后续的文本转ID构建一个字典。

from itertools import chain
train_data_1 = list(chain.from_iterable(train_data[1]))
train_data_2 = list(chain.from_iterable(train_data[2]))
all_words = set(train_data_1 + train_data_2)
print(len(all_words))
vocab = { j:i+1 for i, j in enumerate(all_words)}
vocab["unk"] = 0

数据预处理

做一些简单的文本转ID,然后padding,之后方便喂给模型。

from keras.preprocessing.sequence import pad_sequences
import numpy as np
train_data[1] = train_data[1].apply(lambda x:[vocab.get(i,0) for i in x])
train_data[2] = train_data[2].apply(lambda x:[vocab.get(i,0) for i in x])
Sens_1 = pad_sequences(train_data[1],maxlen=100)
Sens_2 = pad_sequences(train_data[2],maxlen=100)
labels = np.array(train_data[3])
labels = labels.reshape(*labels.shape,1)

构建模型

下面定义了一个构建模型的function。

def SiameseBiLSTM(vocab,max_length):
    K.clear_session()
    embedding = Embedding(input_dim = len(vocab),output_dim = 200, input_length=max_length)
    bilstm = Bidirectional(LSTM(128))

    sequence_input1 = Input(shape=(max_length,))
    embedded_sequences_1 = embedding(sequence_input1)
    x1 = bilstm(embedded_sequences_1)

    sequence_input2 = Input(shape=(max_length,))
    embedded_sequences_2 = embedding(sequence_input2)
    x2 = bilstm(embedded_sequences_2)

    merged = concatenate([x1, x2])
    merged = BatchNormalization()(merged)
    merged = Dropout(0.5)(merged)
    merged = Dense(100, activation="relu")(merged)
    merged = BatchNormalization()(merged)
    merged = Dropout(0.5)(merged)
    preds = Dense(1, activation='sigmoid')(merged)
    model = Model(inputs=[sequence_input1,sequence_input2], outputs=preds)
    model.compile(loss='binary_crossentropy', optimizer='adam')
    model.summary()
    return model

model = SiameseBiLSTM(vocab,100)

执行上方代码,从Keras的模型架构可视化输出可以清楚的看到embedding_1和bidirectional_1这辆层会被两个输入共享。


keras模型可视化

其架构示意图如下,两个输入通过BiLSTM编码成两个向量之后,直接将他们拼接一下,喂给下游的全连结层去做相识度判断。


Siamese BiLSTM Network

训练模型

model.fit([Sens_1,Sens_2],labels,batch_size=32,epochs=5,validation_split=0.2)

构建完模型后,将要判断相似度的句子,和标签喂给模型,定义好,batch_size,和训练轮数epoch,就让它跑起来,其模型训练过程如下图。


train

模型预测

model.predict([sen_pre_1,sen_pre_2])

通过上述代码就可以进行预测了,sen_pre_1和sen_pre_2是经过数据预处理,padding后的100维向量,模型会输出一个(0,1)之间的值,你可以定义一个阈值将这个值转换为[0,1]标签。

结语

至此,四大任务的自然语言处理(NLP)技术实战全部完结。任务看起来都很有趣,keras用起来也简单易上手,baseline的构建也不是很难。但是想要做好,还有大量工作要做。
这四个任务,还有很多可以优化的地方,比如

  • 在输入部分,我很少预训练词向量(除了情感分析实战),对于模型的输入我也是以字为单位,要知道中文以词为单位时其表达才准确;
  • 在模型上的使用,我基本上全用的LSTM或者GRU,没有加任何attention,也没使用更复杂的网络;(需要扎实的领域知识和脑洞)
  • 模型训练部分,超参数的调优和模型的evaluation我基本上没做。(极其耗时耗力)

四个任务的flow都不是特别完美。笔者希望通过这个系列让大家感受到深度学习做NLP的乐趣。若想成为大神,从好奇,喜爱开始,然后苦读论文,多思考,勤做实验,多创新,这个过程就很枯燥了,坚持下去,才能有所建树。(后会有期)

参考:
https://github.com/amansrivastava17/lstm-siamese-text-similarity
https://www.jianshu.com/p/92d7f6eaacf5

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

推荐阅读更多精彩内容