许久未更博了,在前段时间测试了用seq2seq做ner任务,可以参考之前的文章《RNN的Seq2Seq模型做命名实体识别》 ,之后通过NER做NLU,再加上RL尝试多轮对话,结果达到了期望,但是还有很多工作需要去做,多轮语料采集、句子相似度、句向量,在多轮对话中,我没有尝试将每句话进行分类,我认为句子本身表意就非常清晰,标注反而画蛇添足,特别是上下文中的句子,其意思根据上下文而变化。那么对话中去匹配距离最近的句子,并且人为的反馈,可能是一个多轮对话的主要方式。
这篇文章将简单介绍seq2seq模型+attention机制,以及在这个模型下,字符级逐字的输入和输出任务产生的句向量的特性。
句子相似度,可以计算两个向量的空间距离得出,句子的向量表示来自seq2seq模型的encoder最后输出的state,它具有句子的语意信息,在论文中常常用context表示,如下图。在神经机器翻译机中,就是通过把context放入decoder,实现自动翻译。
Seq2Seq的基本模型,采用了一个单向的RNN做Encoder,最后一个State来表示全文的内容,若将整个句子放入到一个固定长度的向量中后,这个向量对最后输入到RNN的数据表现更友好,引起最终解码效果欠佳。
目前,主流都采用双向RNNs(BidirectionalRNN,一个向左,一个向右),可以更好的记录输入的信息。
这个模型可以较好的存储全文的内容,但是对长句子,用全文信息去解码还是不能很好的抓住重点,因此引入注意力机制(arXiv:1409.0473),通过计算encoder每个时刻隐层及权重(a)点乘,得到对应的标量,再将这些标量合成一个向量,最后通过映射层输出decoder的结果。这可以减小长文本中,encoder的句向量效果减弱问题。
模型参数:
字符级的句向量处理,整个模型逐字输入,逐字输出,单层的Bidirectional-GRU+注意力机制,字符向量128,RNN大小128,字符数量8000,学习率0.8,学习率衰退0.99,每批输入样本64。
输入语料,未做任何标注,是一个大杂烩,包含了:
- 歌手名:王力宏、孙燕姿等等
- 歌曲名:少年游、匆匆那年、唯一等等
- 不同类型的请求指令
- 听歌曲名:听匆匆那年,听青花瓷等等
- 播放歌曲名:播放匆匆那年,播放青花瓷等
- 播放歌手名的歌曲名:播放王力宏的唯一,播放周杰伦的青花瓷等
- 其他类似的句子
输出结果:
逐字输入/逐字输出这种方式的句向量:
- 长度敏感,输出结果长度和原句最多相差长度1。
- 字符敏感,有点类似编辑距离,也就是说匹配字符及位置。
- 能基于文字的上下文,区别其中文字的类别,虽然没有标注。表现在输入歌手“韩红、孙燕姿”的时候,返回相似度高的都是其他的歌手名[图1、2];输入首曲名“三人游”的时候,返回相似度高的都是其他的歌曲名[图3];同样对整句也能支持,[图4、5]返回的相似度高的,都基本是一样的句式;[图5],还存在一些误差。
下一步,更详细的看看语料向量化后的分布,这里采用t-SNE将向量映射到2维空间。t-SNE是一个非常好用的工具,可以将高纬降维到二维或三维,也可以将相邻的向量映射到一块。由于语料比较大,无法全部映射,因此我选取一个中心词——“王力宏”,通过欧式距离(t-SNE默认算法)截取最相似的100, 200, 500, 1000个数据,并做映射。
上图是100个样本的数据图,能看到“王力宏”周围最靠近的以及左侧都属于歌手名,右下角的那个簇群,是句式“首歌名的歌”和“歌手名的歌曲名”这类句式的集群,而且在数据不多的请宽下,这里主要表现的是歌手名带“王”字的歌手为主。正上方的有俩个样本,是句式“歌手名的歌曲名”样本,很特别,需要扩大样本数量来看看具体表现。
在样本数量到达200个以后,上面的俩个特例就被很好的解释了,全都出现在蓝色方框中,这时候又出现了新的情况,在灰色椭圆中的3个样本属于歌曲名。另外还有两个双字的歌手名未圈出。这俩类是否会像前面一样100样本中的特例在样本增多后增加呢?
200样本中的“歌曲名特例”在样本增加到500个以后还是不明显,我们放大了“500样本-图1”中的紫色位置及其附近,在“500样本-图2”中看到,歌曲名有所增加,但是不明显。不过“两字歌手名特例”却有了很大的增加,在“500样本-图1”的绿色圈内。由于语料的增加,也出现了“500样本-图1”蓝色圈类别——“放歌曲名”。
1000个样本中,“歌曲名特例”的增长也不是特别明显(样本1000-绿色方框),而“听歌曲名”增加了不少(样本1000-紫色方框),也增加了另外一类“听歌手名的歌曲名”(样本1000-绿色椭圆)。
在500样本和1000样本中,未圈出部分属于“歌手名的歌曲”和“歌手名的歌”俩主要类别,由于样本增加幅度很大,数据比较多,就没做进一步解释。
定了一个中心点,再慢慢增加样本,我们发现,“三字歌手名”和“两字歌手名”被区分成了俩类,我将这点理解为字符级别的模型,对长度比较敏感;而在每一个类别中,文字重复率高的,越相近,这属于字符敏感;模型能够从未标注语句找出文本的类别,比如“歌手名”和“歌曲名”俩类相差甚远,我认为模型能够结合上下文理解来区分文字,这点十分的符合人类学习语言的习惯,就像我们学习方言一样。
最后,基于模型能学习上下文的句式,我尝试了词向量的经典玩法,虽然是字符级组成的句向量,也是把一个词,如“刘德华”当成一个句子,那么它们之间就可以任意的计算了,这和Quoc Le &Tomas Mikolov(点击阅读)的文档向量的概念相似。中间这幅图表示出如果“播放刘德华的歌”减去”刘德华“,但是还是和播放XXX的歌相似,这里也验证了这个模型学会了句式,不过我们对于这个操作,也会有一种理解是“播放刘德华的歌-刘德华=播放歌”。右边这幅图表示机器还无法理解隐藏在文字后的常识,通过Mikolov句向量的理论,如果加入更多的语料,比如百科的语料,也许能学习到这个常识。
总结:
这次实验,做了一个单层的双向+注意力机制的RNN模型,主要测试了字符级的处理在这个模型下产生的效果,长度敏感、字符敏感、会学会句式、取名习惯,还可以实现句子和词的加减,其实都属于文本的加减。这次任务无法获取更多的语义,也许和语料有关系,也许和解码任务有关,后续的工作,做seq2seq的多任务实验,此前,[Dongetal.2015]做了多语言翻译的seq2seq模型,将一个语言翻译成多个语言的任务,取得了很好的效果,而我打算将这个方法应用在将一句话做多个任务的理解,以此加大句向量的信息量,机器若要理解人类语言,就需要对所处环境、社会文化有所了解,对于一句话的不同解读方式,会是机器理解人类语言的重要一步。
发表回复