关系分类泛读系列(三)—— Relation Classification via Multi-Level Attention CNNs论文笔记

一、写在前面的话

这篇论文发表于ACL2016,在SemEval 2010 Task 8 数据集上达到了88%的F1-Score,为目前最高,不过貌似还未有人可以复现。论文使用两层的Attention尽可能应用关系分类任务所特有的信息,损失函数在原有的基础上提出了新的margin function,另外在输入中加入了trigram信息。不过,引入两层Attention导致训练似乎非常困难,加上没有人复现,所以后面文章的对比基本上忽略了这篇文章。

二、论文笔记

1. 论文整体架构

该模型结构主要包含了输入的Attention、卷积层、池化的Attention以及最后的margin function。

2. 输入部分

输入主要分为3部分:

  1. word embedding
  2. position embedding
  3. trigram信息

前两个没什么好说的,就是前两篇笔记里提到的操作,trigram信息是指设置一个滑动窗口k,以每个word 为中心,左右k/2个词作为上下文,将它们拼接起来(这里拼接的不止是词向量,也包括位置向量)。简单来说,其实就是在输入加入了lexical level features,只是一般lexical level features是等深度学习这边操作完成输出句子特征之后拼接这些特征,就像《Relation Classification via Convolutional Deep Neural Network》中的操作一样。

简单来说,现在原来一个词的向量维度变成了:一个词上下文的数量k * (词向量维度 + 位置向量维度*2)

3. 输入的Attention

输入的Attention主要是衡量我们的词与两个实体直接的关系,论文中是引入了两个对角矩阵来分别记录每个词和两个实体之间的attention(不知道这个对角矩阵的意义是什么,其实直接用向量计算似乎就可以了,后面有待研究),计算公式如下,其中A_{i,i}^{j}= f(e_j, w_i)e_j是实体向量,w_i是词向量:

每个词都有对两个entity的权重,论文中提出了如下三种方式融合:

substract
concat
average

4. 卷积层

与其他文章的卷积大致相同:

5. 池化的Attention

这一层Attention其实就是求卷积的输出和relation labels的关系,首先这需要将relation labels也做一个嵌入 W^L,然后使用如下公式获得Attention:

在这个基础上我们再去做pooling:

6. 损失函数

这个损失函数其实建立在relation labels嵌入的基础上,可以看到,这个损失使用了网络最后的输出和relation labels嵌入做distance,最后加上了一个margin,下图中设置margin为1:

7. 实验结果

基本上目前是最优秀的结果,哪怕当前加入了bert之后的最新论文也就达到87%多,但基本没人复现是坑。另外,文章中也详细地做了消去实验,实验也算完备。

三、总结

尽管这篇论文存在不能完整复现的问题,但文章中多层Attention的想法其实是很值得考虑得,从几个维度考虑Attention或者在不同阶段加入Attention都是不错的一个技巧,另外关于损失函数,该论文使用了embedding的逼近来作为距离函数,也有较好地提升,能否在其他任务里加入这样的技巧,也是值得思考的。整体来说,虽然坑很多,但思路很好,值得阅读和尝试复现。

四、代码

运行了https://github.com/FrankWork/acnn,在运行代码上没什么坑,但是效果并不怎么样,下次会重新改到自己的代码上:

输入的Attention实现:

  def _input_attention(self, x, e1, e2, initializer=None):
    bz = self.config.batch_size
    n = self.config.max_len

    with tf.name_scope('input_attention'):
      A1 = tf.matmul(x, tf.expand_dims(e1, -1))# bz, n, 1
      A2 = tf.matmul(x, tf.expand_dims(e2, -1))
      A1 = tf.reshape(A1, [bz, n])
      A2 = tf.reshape(A2, [bz, n])
      alpha1 = tf.nn.softmax(A1)# bz, n
      alpha2 = tf.nn.softmax(A2)# bz, n

      alpha = (alpha1 + alpha2)/2
      
      return alpha

配置如下:

import tensorflow as tf


# Basics
# tf.app.flags.DEFINE_boolean("debug", True,
#                             "run in the debug mode.")
tf.app.flags.DEFINE_boolean("test_only", False,
                            "no need to run training process.")

# Data files
tf.app.flags.DEFINE_string("data_path", "data/", "Data directory")
tf.app.flags.DEFINE_string("embedding_file", "embedding/senna/embeddings.txt", 
                           "embedding file")
tf.app.flags.DEFINE_string("embedding_vocab", "embedding/senna/words.lst", 
                           "embedding vocab file")
tf.app.flags.DEFINE_string("train_file", "train.txt", "training file")
tf.app.flags.DEFINE_string("test_file", "test.txt", "Test file")
# tf.app.flags.DEFINE_string("log_file", 'run/log.txt', "Log file") 
# tf.app.flags.DEFINE_string("save_path", 'run/', "save model here")
tf.app.flags.DEFINE_string("log_file", None, "Log file") 
tf.app.flags.DEFINE_string("save_path", None, "save model here")

tf.app.flags.DEFINE_string("embedding_size",'50' , "pad word")
tf.app.flags.DEFINE_string("max_len",'30' , "pad word")



# Model details
tf.app.flags.DEFINE_integer("pos_embed_num", 123, "position embedding number")
tf.app.flags.DEFINE_integer("pos_embed_size", 5, "position embedding size")
tf.app.flags.DEFINE_integer("slide_window", 3, "Slide window size")
tf.app.flags.DEFINE_integer("num_filters", 100,
                            "How many features a convolution op have to output")
tf.app.flags.DEFINE_integer("classnum", 19, "Number of relations")

# Optimization details
tf.app.flags.DEFINE_integer("batch_size", 100, "Batch size")
tf.app.flags.DEFINE_integer("num_epoches", 100, "Number of epoches")
tf.app.flags.DEFINE_float("keep_prob", 1.0, "Dropout keep prob.")
tf.app.flags.DEFINE_float("learning_rate", 1e-3, "Learning rate.")
tf.app.flags.DEFINE_float("l2_reg_lambda", 1, "regularization parameter")
# tf.app.flags.DEFINE_float("learning_rate2", 1e-3, "learning_rate for regularization")
tf.app.flags.DEFINE_float("margin", 1, "margin based loss function")
tf.app.flags.DEFINE_float("grad_clipping", 10., "Gradient clipping.")


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