使用CNN+ Auto-Encoder 实现无监督Sentence Embedding (代码基于Tensorflow)

1前言

这篇文章会利用到上一篇: 基于Spark /Tensorflow使用CNN处理NLP的尝试的数据预处理部分,也就是如何将任意一段长度的话表征为一个2维数组。

本文完整的代码在这: autoencoder-sentence-similarity.py(https://gist.github.com/allwefantasy/51275cb5c649e4a69b33131e967e2af9#file-autoencoder-sentence-similarity-py)

基本思路是,通过编码解码网络(有点类似微软之前提出的对偶学习),先对句子进行编码,然后进行解码,解码后的语句要和原来的句子尽可能的接近。训练完成后,我们就可以将任意一个句子进行编码为一个向量,这算是Sentence Embedding的一种新的实现。最大的好处是,整个过程无需标注语料,属于无监督类学习。这次我还在编码前引入卷积网络,不过效果有待验证。

2准备工作

我们假设大家已经准备了两个数据集,具体可以参考上一篇文章的Spark预处理部分:

  • 已经分好词的语句
  • 词到vector的字典

然后我们使用如下函数来进行处理:

def next_batch(batch_num, batch_size, word_vec_dict):    
 with open(WORD_FILE) as wf:        
 line_num = 0        
 start_line_num = batch_num * batch_size         
batch_counter = 0        
result = []        
 for words in wf:            
 result1 = []             
line_num += 1             
 if line_num > start_line_num:                 
batch_counter += 1                
 for word in words.split(" "):                    
 if word in word_vec_dict:                        
 result1.append(word_vec_dict[word])                
 if len(result1) < SEQUENCE_LENGTH:                    
 for i in range(SEQUENCE_LENGTH - len(result1)):                         result1.append(np.zeros(shape=(VOCAB_SIZE, 1)).tolist())                
 result.append([str(line_num), result1[0:SEQUENCE_LENGTH]])                 
if batch_counter == batch_size:                    
 return result

字典的格式是: word + 空格 + 100个逗号分隔的数字

文本内容格式是: 通过空格分隔的已经分好词的句子

因为这次测试数据集有点大,所以没办法一次性载入到内存,只能分批了。缺点是,每一次都需要重新打开文件,为了减少打开文件次数,程序后半部分做了一些优化处理,基本方式为,一次性从文件里取batch_size 条数据,然后让Tensorflow 再分 batch_size / mini_train_batch_size 次进行迭代。每次迭代给的样本量还是比较影响效果的,4000和200比,有20%左右的差异。

3构建模型

我尝试了如下两个拓扑,第一个是带卷积的:

Input(段落) -> 卷积 -> 池化 -> 卷积 -> 池化 -> encoder -> encoder -> decoder -> decoder -> lost function (consine夹角)

第二个则是不带卷积:

Input(段落) -> encoder -> encoder -> decoder -> decoder -> lost function (consine夹角)

基本上是两层卷积,两层编解码器。

训练完成后,就获得编码器的所有参数,利用encoder_op 对所有的语句进行编码,从而实现所有语句得到一个唯一的向量(128维)表示。

大概准备了 60多万条语句进行训练,经历了50*60轮迭代后,不带卷积最后loss 大概是从1.1 下降到0.94的样子。如果进行更多迭代,提供更多训练数据,应该可以进一步降低。

带卷积的收敛较快,loss 从0.5 经过3000轮迭代,可以下降到0.1 左右。

因为语料比较隐私,无法提供,但是可以描述下大致的结论,随机找一段话,然后寻找相似的,目前来看,不带卷积的效果非常好,带卷积的因为卷积后信息损失太大,在encoder-decoder阶段感觉无法训练了,最后趋同,因此需要对卷积进行较大调整。关于NLP的卷积,其实我们不一定要保证卷积核的宽度或者高度保持和word embedding的size一样,因为对两个word截取其一般,我认为应该还是有一定的相似度的。

在训练过程中,损失函数我尝试了:

xent =tf.reduce_mean(tf.pow([y_true, y_pred],2), name="xent")

以及

consine = tf.div(tf.reduce_sum(tf.multiply(y_pred, y_true)),                
          tf.multiply(tf.sqrt(tf.reduce_sum(tf.multiply(y_pred, y_pred))),                                      tf.sqrt(tf.reduce_sum(tf.multiply(y_true, y_true)))))         xent = tf.reduce_sum(tf.subtract(tf.constant(1.0), consine))

因为采用欧式距离,我们难以确定相似度的阈值,而cosine是一个比较容易衡量的值。所以这里选择了consine作为损失函数。我没有找到Tensorflow的实现,所以完全根据consine公式自己实现了一个。

对于Optimizer,我尝试了

train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(xent) train_step = tf.train.RMSPropOptimizer(learning_rate).minimize(xent)

目前来看,RMSPropOptimizer效果好很多。

4总结

现阶段大量优秀的人才都投入到了深度学习上,所以深度学习也取得了越来越多的进展,用法也越来越多,尤其是对抗学习,加强学习,对偶学习的发展让深度学习可以做的事情越来越多。深度学习在NLP文本分类,特征抽取方面,我觉得还是有潜力可挖的。不过,我觉得深度学习其实是把机器学习的门槛提的更高了,虽然越来越多的工具(比如Tensorflow)和已知的各种实践似乎在降低某些门槛。

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-09-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

AOGNet:基于深度 AND-OR 语法网络的目标识别方法

这是 PaperDaily 的第28篇文章 本期推荐的论文笔记来自 PaperWeekly 社区用户@duinodu。本文研究的问题是深度学习中的网络工程问题。...

2157
来自专栏互联网大杂烩

逻辑斯蒂回归(Logistic Regression)

定义x=<x1,x2,...xn>来表示n维特征向量,权重为w=<w1,w2,...wn>,同时,截距(Intercept)为b。则这种线性关系为: f(w,...

662
来自专栏王小雷

Spark学习之基于MLlib的机器学习

Spark学习之基于MLlib的机器学习 1. 机器学习算法尝试根据训练数据(training data)使得表示算法行为的数学目标最大化,并以此来进行预测或作...

2295
来自专栏专知

【深度干货】专知主题链路知识推荐#5-机器学习中似懂非懂的马尔科夫链蒙特卡洛采样(MCMC)入门教程01

【导读】主题链路知识是我们专知的核心功能之一,为用户提供AI领域系统性的知识学习服务,一站式学习人工智能的知识,包含人工智能( 机器学习、自然语言处理、计算机视...

3477
来自专栏机器之心

教程 | 一文简述如何使用嵌套交叉验证方法处理时序数据

1743
来自专栏AI科技评论

干货 | 孙启超:卷积神经网络在人脸识别技术中的应用

AI 科技评论按:随着 iPhone X 的发布,Face ID 人脸识别技术开始进入人们的日常生活中,当我们拿起手机并看着它的时候就可以实现手机解锁的功能。而...

723
来自专栏机器学习算法与Python学习

Machine Learning -- Naive Bayes(朴素贝叶斯)

1.1、摘要 贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。将首先介绍分类问题,对分类问题进行一个正式的定义。然后,介...

3135
来自专栏大数据挖掘DT机器学习

网络挖掘技术——微博文本特征提取

文本特征向量 经典的向量空间模型(VSM: Vector Space Model)由Salton等人于60年代提出,并成功地应用于著名的SMART文本检索系统。...

2876
来自专栏大数据文摘

识辨 | 什么是分类?什么是聚类?

1374
来自专栏新工科课程建设探讨——以能源与动力工程专业为例

4.3 差分与简单常微分方程初值问题

什么是差分运算?如下图,数值计算过程我们计算函数上某点的导数时,可以选择某点附近(可以包含该点)的两个点,取这两个点的斜率来近似表示该点的导数。一阶导数...

550

扫描关注云+社区