Quora Question Pairs 思路记录

本文记录了作者在Quora Question Pairs比赛中的思路和学习过程,从自然语言处理的角度出发,探讨了如何用RNN、LSTM和Siamese Nets构建模型来判断句子相似性。作者首先介绍了从词向量到句子向量的转换思路,然后提出了使用L1 norm计算向量相似度并以Logistic Regression学习阈值的方法。在实践中遇到了训练集loss下降快但测试集loss较高的问题,以及词向量训练和模型过拟合的挑战。
摘要由CSDN通过智能技术生成
  • Quora Question Pairs

    Quora Question Pairs 退出小组

    33个成员  2个话题  创建时间:2017-11-30

    Quora Question Pairs比赛思路记录和交流 置顶 精华

    发表于12-06  1409次查看

    此贴用于对学习过程中遇到的问题、学习到的东西做一下小结,群主会根据小结的内容给予相应的建议。

    25回复
    • 2楼 旷野的季节   12-25

      今天是2017年12月24号,平安夜:)18天前进入的这个项目,两周多的时间,还挺快。

             之前学过解惑者学院的《垃圾短信识别小试牛刀》课程,有学过词向量,因此对于这个判断两句话意思是不是相同的问题,自然想到的就是把“词”-> 向量 的方法进行推广,扩展成 “句子”-> 向量。但是至于怎么扩展,怎么用向量表达一句话的意思,感觉还没有什么思路。另外就算知道了怎么表达成向量了,还有一个问题是两个向量到底有多“相似”才是意思一样,也不是很好判断的问题。还没有太多思路。

            在这两个问题都不是特别清楚的情况下,面临的一个问题,是到底要不要直接去kaggle上找现成的解决方案来利用。但是仔细想了下,想找个方案是很容易的,但是如果只是把方案拿过来实现一下,甚至是有现成的代码拿来RUN一下,似乎学不到太多的东西。于是就想先自己思考一下。

           不过既然是自然语言处理的项目,老师也说了是很常见的问题,就想先学学自然语言处理。忘了是怎么找到了斯坦福大学的CS224N( Deep learning in NLP)这门课了,就先看了大约两周的时间。里面开始讲的是word2vec,又跟着看了一遍,有了更多的理解。然后提到了Glove,讲义里说这种向量表示会包含更多的语义信息,估计Quora项目能用的上。就先记下了。至于说这个向量是怎么训练的,暂且没有太管。

          然后又看了几天,里面开始提到了神经网络,RNN, CNN, LSTM,有讲到用RNN实现语言模型(什么是语言模型就不说了),这个时候就感觉到可以用RNN做Quora项目。因为想想其实本质是一样的; 都是记录历史信息。当然也可以用LSTM,因为LSTM和RNN没有本质上的区别。LSTM对于长期的序列学习会更好。

          此时一开始的疑问之一就解决了。先暂时用RNN(or LSTM)来做。那是不是这样就是最好的表达向量的方式呢? CS224N后面会提到,基于Tree-LSTM(可以说成是 Recursive CNN吗)。 这个方法的动机是说:一句话的意思,由二方面决定,一是句子的组成结构、二是句子中词的含义。224N举的例子是说,语言学领域(包括其它任何领域),递归是一种特别常用的现象。比如" the dog walked into the house"。(随意编的一句话)。the dog 是主语从句?? walked into the house是谓语(从句?),这二者合并成了完整的这句话。the dog 也可以再递归地向下拆分结构。但是这种方法需要parser,来把句子的结构分析出来。看了看这个另外的任务也可以用神经网络去做。 不过这种方法会比较麻烦,暂时先不准备用这种方案。毕竟还是先做个简单的版本出来吧:)

           刚开始说的一个疑问(怎么用向量表达话的意思就明白了),然后是另外一个问题——怎么衡量向量的相似度。恰好还是看CS22N,里面提到了下面的这种结构,觉得可以用在此项目上。叫Siamese Nets。

      x1,x2就可以是RNN(LSTM)送出来的句子向量。

       

      然后就百度了一下这种网络,恰好又找到了一篇论文,

      Siamese Recurrent Architectures for learning sentence similarity.

      里面提到了下面的架构:

       

      我感觉这个架构可以直接做为参考使用。

      下面把这个思路整理一下:

      1. 用Glove表示词向量;

      2. 用线性LSTM表示句子

      3. 用Siamese Nets 做成判断网络使用

      不过还有一些细节可以思考:

      词向量需不需要更新(重新学习)?

      例如最简单的情况,如果 有一些词如果在Glove里面没有,怎么办? 比如下面的话,注意这个样本的label是1

      How do we prepare for UPSC?

      How do I prepare for civil service?

      可以推测出来,UPSC应该是 civil service 的意思。

      所以说,对于样本的label=1 的样本,我们是不是可以利用一下来优化词向量?


      想问一下,这个架构可以吗?

      如有问题或者建议请老师提出。

        回复
    • 3楼 Ryan   12-29

      网络结构不小心被我删掉了,能重新发一下么?

       

      这个是非常常用的网络结构,尤其是需要处理两个事物之间关系的时候。他是一个通用的结构,你可以替换成你想要的任何方法

        回复
    • 4楼 Ryan   12-29

      @旷野的季节 在做事情之前做了这么多且细致的工作,大赞一个!

       

      首先不透露更多的可能解决问题的思路了,等你做到一定的深度的时候,再来细说一下这个。个人建议在做一个项目的时候不要参考别人的做法,尤其是刚开始的时候。机器学习是数据为基础的领域,不同的数据具有不同的特点,不存在一种方法能解决所有的问题。参考别人的做法,就丧失了自我分析数据的过程,这也是机器学习过程中最重要的活动,也是体现水平的时候。其实模型在实际的工程项目中的工作量很小。

       

      你的思路可以尝试,当然还有很多问题等待着你去解决。例如,是使用现成的vector还是直接通过训练数据去训练,亦或是两者结合;是使用RNN还是CNN;多层是否必要;训练速度太慢怎么办;效果不如预期,比排行榜上的得分差的太多,原因在哪儿;是否需要引入更多的特征,例如文本类特征;可以做多个模型融合吗 等等

       

      可以多尝试做一下数据分析和深度研究,可以用一些小模型研究看看情况

        回复
    • 5楼 旷野的季节   01-01

      先重新把图发一下,下面这个图是 Siamese Nets, 一种通用的架构。

      另外,和垃圾短信类似的做法,是不是也可以先预处理一下、比如先把停用词给去掉。或者按照老师上次回复说的,用一些文本类特征。这么做肯定是可以的,至于怎么利用日后慢慢细想。

      下面这个图是初步准备使用的架构图。单层的LSTM网络,把两个句子的最后一级的state(t) 拿出来,后面可以是按照图中这么做求欧式距离,也可以是再进入一个MLP神经网络。然后再求欧式距离。如果两个句子意思相同,则欧式距离应该尽量小; 如果两个句子意思不相同,欧式距离应该尽量大。然后采用stochastic 梯度下降法做训练。

       

        回复
    • 6楼 旷野的季节   01-02

      2017.12.26-2018.1.1  周总结

      (1) 目前打算先按照这个架构做。 这周主要学习了一下tensorflow工具。先看了看最基本的、什么是tensor, 什么是node;  cost 函数怎么描述,placeholder, optimizer ……

      看的是下面这篇文章:感觉写的比较详细

      http://jorditorres.org/research-teaching/tensorflow/first-contact-with-tensorflow-book/first-contact-with-tensorflow/

       

      (2)看懂了上面的文章后,仔细阅读了下面这篇文章,该文章通过一个toy project ,即利用RNN解决01二元序列的预测问题。

      https://r2rt.com/recurrent-neural-networks-in-tensorflow-i.html

      把里面的代码仔细看了看,有下面的收获:

      First, RNN抓住的是 X 在“历史上”的信息,通过inner state 内部反馈实现

      Second,  这篇文章的tensorflow程序架构、可以分为“数据发生器”“计算图模型”“把数据送进计算图”“  run session”这么几部分,结构还是比较清楚了。 自己写程序时也要注意一下组织程序的问题。有空时可以读一下《小试牛刀》里面推荐的那篇 怎么组织tensorflow程序的文章。

       

      Third,  Quora Question问题,不同的话的长度是不相同的。即如果用LSTM的话,输入序列个数(num_steps)是变化的。 调研了一下Dynamic RNN的问题。即通过tensorflow中的Dynamic RNN,可以不用做padding。

       

      Forth,还有一个细节需要思考。 如果用欧式距离做判决的话,这个最终的阈值是怎么确定的。 是否作为参数之一自动学习出来呢? 还是在模型训练的时候,就只是尽量优化出一个结果、即相同意思的句子欧式距离尽可能小,不同意思的话欧式距离尽可能大。最终加一个处理流程,比如统计一下所有的意思相同的话里面,欧式距离最大的值是多少,以此值来作为阈值??这个细节还没有想好应该怎么弄。

       

      下一步工作:

      1. 先尽快写出来一个base 版本的程序,用 Train split出来的test集测试一下看看情况

      2. 对数据进行更深入的研究。 想想是不是有更好的思路。

       

        收起
      • Ryan  01-02
        整个思路没啥问题,可以先做base版本的尝试。 关于阈值的部分,项目是以logloss为优化目标,因此从这个角度上来看阈值不重要,重要的是预测的分布要与实际的分布尽可能的相近。
  • 7楼 旷野的季节   01-12

    基于RNN的一种实现方式

     

    RNN可以捕捉X序列的信息。比如在下面这个例子里面:

     

    https://r2rt.com/recurrent-neural-networks-in-tensorflow-i.html

     

    X是一个随机产生出来的01序列,0/1的概率各是0.5 Y序列的产生与X序列有关系。 规则是下面这几条:Y[t]=”1”的基础概率是0.5 如果X[t-3] = 1 Y[t] =’1’的概率提高50%; 如果X[t-8]=1¸y[t]=’1’的概率降低25%; 如果X[t-3]X[t-8]同时为1y[t]=1 的概率是0.5+0.5-0.25=0.75

    可以把X序列拆分成一个个小的序列,送到RNN模型里面去学习。最终,RNN可以学出来这两个规律。(X[t-3]X[t-8]对于 y[t]的影响)

    虽然这只是一个简单的例子,但是从这个例子可以体会到RNN的作用。

    对于Quora项目,也可以使用类似的思路。用两个相同的RNNor LSTM or GRU,下同)网络,分别处理s1,s2两句话。如下图所示。

     

    S1,s2中的每一个单词都先转化成glove向量、 然后送入RNN网络。第一句话是”He  is smart” ; 第二句话是”A truly wise man”。在这种encoder架构下,我们认为h3(a)h4(b)分别代表了两句话的意思。

    那么怎么比较h3(a) h4(b)呢? 目前我准备使用的是L1 norm(h3a- h4b)

    比如,

    h3(a) = [ 0.123, -0.343, 0.287]

    h4(b) = [ -0.38, -0.165, 0.403]

    h3(a) - h4(b) = [0.503, -0.178, -0.116]

    || h3(a) - h4(b)||= abs(0.503) + abs(-0.178) + abs(-0.116) = 0.797

     

    那么在做预测的时候,这个L1 norm(RNN(s1)- RNN(s2) ) 多近s1,s2算是意思相同,多远算是s1,s2 意思不同呢? 关于这个阈值目前我的想法是当成一个参数来学习出来。如下图所示,横轴是L1 norm(encoder(s1) – encoder(s2))  其中横轴 0<=x < +INF

    纵轴是exp(-横轴) 将横轴压缩成了(0,1) exp(-横轴)中加了一个负号的目的,是为了与label中的含义(1表示两句话意思相同,0表示两句话意思不同)保持一致。

     

     

    我期望的结果,是意思相同的pair(label=1) exp(-L1 norm(encoder(s1) – encoder(s2))) 应该会比较大(图中靠近上面的部分);而意思不同的pair(label=0) exp(-L1 norm(encoder(s1) – encoder(s2)))应该会比较小(图中靠近下面的部分)。而threshold就是区别两者的界限。为了下面描述方便,定义:

    similarity(s1,s2) = exp(- L1 norm(encoder(s1) – encoder(s2))).  ————公式(1

    作为相似度度量的指标,这个指标越大,相似度越高。

    关于上面提到的阈值,目前我准备采用(一维的)Logistic Regression学习出来两个参数: w  b b 就是上面提到的thresholdw的含义目前还没有想好,先暂时这么定。即:

    Probability(s1,s2 has the same meaning)= 1/ (1+exp(-  (w*similarity(s1,s2)+b)   )) –公式(2

     

    这个函数把 similarity从度量距离的空间映射到“概率空间”。这样以batch 为单位训练的时候,batch内所有样本出来的概率各个样本出现的概率的连乘。然后取其 负对数(-log)作为损失函数,各个样本的损失函数相加作为一个batch的损失函数而成为优化目标。

    losses = - [  y * tf.log(probability) + (1-y) * tf.log(1- probability) ]    --------公式3

    注:y,probability是一个batch的数据

     

    程序的架构:

    1. RNN_model.py

    定义模型(计算图), 损失函数

    模型的超参数:

     

    Hyper-Parameters

    Value Space

    Notes:

    Rnn_type

    “rnn” , “lstm”, “gru”

    Encoder里面的记忆单元采用RNN 还是LSTM 还是GRU

    Nonlinear_type

    “sigmoid” or “ReLU”??

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值