多标签分类问题中,不同标签之间往往存在着一定的相关关系,使得每个标签并不是独立的。而传统的多标签分类中,通常是在最后一层对每个分类标签使用sigmoid_crossentropy_loss来计算损失,然后将损失求和,同时计算每个分类标签的概率,忽略了标签之间的关联性。
通过使用seq2seq的方式能够在一定程度上建模标签之间的关联信息。
给定标签空间 L = { l 1 , l 2 , ⋅ ⋅ ⋅ , l L } L = \{l_1, l_2, · · · , l_L\} L={l1,l2,⋅⋅⋅,lL}, 一段包含 m m m个单词的文本序列 x x x , 任务是将在 L L L中包含 n n n个标签的子集 y y y分配到对应的 x x x上。
任务目标:找到最优的 y ∗ y^* y∗最大化 p ( y ∣ x ) = ∏ i = 1 n p ( y i ∣ y 1 , y 2 , ⋯ , y i − 1 , x ) p(\boldsymbol{y} \mid \boldsymbol{x})=\prod_{i=1}^{n} p\left(y_{i} \mid y_{1}, y_{2}, \cdots, y_{i-1}, \boldsymbol{x}\right) p(y∣x)=∏i=1np(yi∣y1,y2,⋯,yi−1,x)
网络结构主体与经典的带attention的seq2seq是非常相似的。
encoder没有变化,主要改进点在decoder上。
令 ( w 1 , w 2 , ⋯ , w m ) (w_1,w_2,\cdots,w_m) (w1,w2,⋯,wm)为 m m m 个单词的序列, w i w_i wi是第 i i i 个单词的 one-hot 表示。我们首先通过一个embedding matrix把 w i w_i wi嵌入成一个稠密的嵌入向量 x i x_i xi, ∣ V ∣ |V| ∣V∣是词汇表的大小, k k k是嵌入向量的维度。
通过一个Bi-LSTM从两个方向上获取文本序列x每个单词的隐藏状态并拼接两向量作为第 i i i个单词的最终隐藏状态:
h i → = L S T M ‾ ( h i − 1 → , x i ) \overrightarrow{h_{i}}=\overline{L S T M}\left(\overrightarrow{h_{i-1}}, x_{i}\right) hi=LSTM(hi−1,xi); h i ← = L S T M ← ( h i + 1 ← , x i ) \overleftarrow{h_{i}}=\overleftarrow{L S T M} \left(\overleftarrow{h_{i+1}}, x_{i}\right) hi=LSTM(hi+1,xi)
h i = [ h i → , h i ← ] h_i = [\overrightarrow{h_{i}},\overleftarrow{h_{i}}] hi=[hi,hi]
当模型预测不同的标签的时候,并不是所有的单词贡献相同。注意力机制会通过关注文本序列中的不同部分,产生一个上下文向量 (context vector)。如图中红线部分所示。
e t i = v a T tanh ( W a s t + U a h i ) e_{t i}=\boldsymbol{v}_{a}^{T} \tanh \left(\boldsymbol{W}_{a} \boldsymbol{s}_{t}+\boldsymbol{U}_{a} \boldsymbol{h}_{i}\right) eti=vaTtanh(Wast+Uahi)(加性模型的注意力打分函数)
α t i = exp ( e t i ) ∑ j = 1 m exp ( e t j ) \alpha_{t i}=\frac{\exp \left(e_{t i}\right)}{\sum_{j=1}^{m} \exp \left(e_{t j}\right)} αti=∑j=1mexp(etj)exp(eti)
c t = ∑ i = 1 m α t i h i c_{t}=\sum_{i=1}^{m} \alpha_{t i} \boldsymbol{h}_{i} ct=∑i=1mαtihi
由于并没有target文本,我们需要建模的是不同标签之间的关系,因此将所有标签类别作为一个序列,假设有n种标签,那么Decoder就有n个时刻。
Remark:在所有的建模之前,数据预处理工作是将所有的label按照出现频率的大小重新排序,出现较多的标签排在序列的较早时刻。目的主要有两个:1、training过程loss还是使用cross-entropy loss,每个时刻上的标签y都需要给定,因此其顺序也要给定。2、将频率较高的标签放在开头来训练,能够让模型提早学习对数据整体而言最有用的信息,更好地指导整个标签的输出。
t时刻解码器的隐藏层状态:
s t = L S T M ( s t − 1 , [ g ( y t − 1 ) ; c t − 1 ] ) s_{t}=L S T M\left(s_{t-1},\left[g\left(y_{t-1}\right) ; c_{t-1}\right]\right) st=LSTM(st−1,[g(yt−1);ct−1])
[ g ( y t − 1 ) ; c t − 1 ] \left[g\left(y_{t-1}\right) ; c_{t-1}\right] [g(yt−1);ct−1]是指 g ( y t − 1 ) g\left(y_{t-1}\right) g(yt−1)和$ c_{t-1}$的拼接。
Confusion1:
在公式(7)中 s t s_t st是通过前一个时刻 t − 1 t-1 t−1的rnn hidden state s t − 1 s_{t-1} st−1, g ( y t − 1 ) g\left(y_{t-1}\right) g(yt−1)和前一个时刻的上下文向量$ c_{t-1}$,这也符合Attention本身的使用方法。
在模型图中,画出的是每个时刻t,decoder的rnn接收的是当前时刻的 c t c_{t} ct来生成当前的 s t s_t st。
应当是先将前一时刻的attention信息和前一时刻的标签global embedding先拼接,然后在输入到rnn中。这与图上的画法不符,只能认为是作者的图画错了。高亮部分为应当更正后的路线图。
然而在第一版源码中decoder的LSTM输入只有 g ( y t − 1 ) g(y_{t-1}) g(yt−1)没有 c t − 1 c_{t-1} ct−1,github上有人提过这个issues但是也还没回答。
如何计算 g ( y t − 1 ) g(y_{t-1}) g(yt−1)?
1、通过Mask Softmax计算 y t − 1 y_{t-1} yt−1
y t − 1 y_{t-1} yt−1是在 t − 1 t-1 t−1时刻在标签空间 L L L 上的概率分布。
图中绿线的部分,相当于一个全连接层。接收的输入为当前decoder的 s t s_t st以及当前时刻计算得到的 c t c_t ct:
o t = W o f ( W d s t + W c c t ) \boldsymbol{o}_{t}=\boldsymbol{W}_{o} f\left(\boldsymbol{W}_{d} \boldsymbol{s}_{t}+\boldsymbol{W}_{c} \boldsymbol{c}_{t}\right) ot=Wof(Wdst+Wcct)
y t = softmax ( o t + I t ) \boldsymbol{y}_{t}=\operatorname{softmax}\left(\boldsymbol{o}_{t}+\boldsymbol{I}_{t}\right) yt=softmax(ot+It)
W o , W d , W c W_o,W_d,W_c Wo,Wd,Wc都是可学习的权重参数矩阵。
使用mask的方式就是对上一步的输出 o t o_t ot添加一个mask vector I t I_t It
( I t ) i = { − ∞ if the label l i has been predicted at previous t − 1 time steps. 0 otherwise. \left(\boldsymbol{I}_{t}\right)_{i}=\left\{\begin{array}{ll}-\infty & \text { if the label } l_{i} \text { has been predicted at previous } t-1 \text { time steps. } \\ 0 & \text { otherwise. }\end{array}\right. (It)i={−∞0 if the label li has been predicted at previous t−1 time steps. otherwise.
如果当前时刻输出的标签结果在前面t-1时刻中有出现过,则赋予 I t I_t It一个极小值,否则赋予零向量。源代码中 − ∞ = − 9999999999 -\infty =-9999999999 −∞=−9999999999。 I t I_t It的目的也是为了防止解码器预测前面预测过的重复的label。原文做了消融实验来验证mask softmax是不是真有用。
2、计算 g ( y t − 1 ) g(y_{t-1}) g(yt−1)
g ( y t − 1 ) g(y_{t-1}) g(yt−1)是label embedding,这里的label指的是在 y t − 1 y_{t-1} yt−1分布下的最高概率对应的标签。
但是如果只是一味的贪婪地追求最大值,如果在RNN-Decoder中t时刻预测的label是错误的,那么后续的传递也都是错误的,贪心法在decoder部分不合适。为防止exposure bias(错上加错),采用了beam search(术搜索)选取top-ranked K个标签。但不能从根本上解决exposure bias。
Remarks:
实践中防止错误积累传播的一个工具。
beam search是一种常用的减少错误搜索的启发式方法。在每一步的序列生成过程中,生成K个最可能的前缀序列,其中K为束的大小(Beam Size), 是一个超参数。
图源自邱锡鹏2019.《深度学习》P379
在词表 V = { A , B , C } V=\{A,B,C\} V={A,B,C}中,束大小 K = 2 K=2 K=2。
类似于vertibi算法,每一步都有back search。但本质区别是vertibi要求每一步都是条件独立的,只会保留一条路径;
而beam search依赖于前面所有的词,每个节点的分布是一个以之前所有节点为先验信息的条件概率分布,可以为多条路径。所以 y t − 1 y_{t-1} yt−1包含了从初始时刻开始至 t − 1 t-1 t−1所有的信息,要想完全解决exposure bias,必须遍历所有的路径,但时间成本算力成本耗费就太大了。
选出了合适的 y t − 1 y_{t-1} yt−1,继续计算 g ( y t − 1 ) g(y_{t-1}) g(yt−1)。
为了更好地解决错误传递的结果,原文采用了如下的结构计算 g ( y t − 1 ) g(y_{t-1}) g(yt−1):
先为每个标签初始化一个embedding e i e_i ei;
e ˉ = ∑ i = 1 L y t − 1 ( i ) e i \bar{e}=\sum_{i=1}^{L} y_{t-1}^{(i)} e_{i} eˉ=∑i=1Lyt−1(i)ei(根据decoder计算得到的标签的概率分布,以概率为权重,计算所有标签的加权和 e ˉ \bar{e} eˉ);
H = W 1 e + W 2 e ‾ \boldsymbol{H}=\boldsymbol{W}_{1} \boldsymbol{e}+\boldsymbol{W}_{2} \overline{\boldsymbol{e}} H=W1e+W2e(构建门)
g ( y t − 1 ) = ( 1 − H ) ⊙ e + H ⊙ e ‾ g\left(\boldsymbol{y}_{t-1}\right)=(\mathbf{1}-\boldsymbol{H}) \odot \boldsymbol{e}+\boldsymbol{H} \odot \overline{\boldsymbol{e}} g(yt−1)=(1−H)⊙e+H⊙e;
原文是叫借鉴了adaptive gate in highway network这个结构,其实就是借鉴了GRU,通过门的机制,将前面 t − 1 t-1 t−1时刻的所有预测出来的 y y y信息都编码整合。通过对所有信息的加权 e ˉ \bar{e} eˉ和门 H H H,能够学习所有标签label的综合信息,防止错误标签的“发扬光大”。
Confusion2
门构建的作用是控制0-1之间的通路,应当sigmoid一下。源码中其实也用了sigmoid,应该是论文的一个typo。
emb_avg = torch.matmul(probs, self.embedding.weight)
H = torch.sigmoid(self.ge_proj1(embs) + self.ge_proj2(emb_avg))
emb_glb = H * embs + (1 - H) * emb_avg
RCV1-V2&&AAPD
['won million sery moody moody net cost ud percent bond texa system cape sew tax revenu interest waterwork juran royal\n',
'purchas stock complet issu million corp fsb hold shar shar shar tuesday back newsdesk compan compan result fsf fsf fsf chicag buy feder common outstand total financ financ financ repurchas\n']
由于路透社新闻数据版权的问题,所以不能够重建原始数据。因此,作者在数据集删除了所有的停止词,并用词干(比如financ、complet)替换其余的词,并打乱词干的顺序
Hamming-Loss && Micro-F1
####(2)结果分析
1)测试结果
自行复现结果(with Global Embedding && beam K=2):
batchsize | 64 | 128 | 256 | 512 |
---|---|---|---|---|
hamming_loss | 0.00842 | 0.00839 | 0.00836 | 0.0084 |
micro_f1 | 0.8730 | 0.8735 | 0.8738 | 0.8733 |
micro_precision | 0.8844 | 0.8849 | 0.8855 | 0.8850 |
micro_recall | 0.8618 | 0.8623 | 0.8623 | 0.8618 |
instance_f1 | 0.8840 | 0.8843 | 0.8845 | 0.8841 |
instance_precision | 0.9038 | 0.9042 | 0.9045 | 0.9042 |
instance_recall | 0.8880 | 0.8884 | 0.8884 | 0.8879 |
2)Global Embedding的探索
红线表示用了GRU
3)消融实验
without mask和sorting的区别。分别表示不做mask操作,以及随机打乱标签序列以扰乱其原始的顺序。
masking 很关键。
4)注意力可视化
5)案例学习
阅读《A Deep Reinforced Sequence-to-Set Model for Multi-Label Text Classification》
Seq2Seq由于要提前定义label顺序,但其实很多时候多标记数据集本身就是无序的。
Seq2Set则可以在提取label关联度的基础上,降低对标签顺序的依赖。
2、CNN、RNN如何fit multi-label任务 baseline model。基本实现
3、引用该篇比较好的论文有哪些(近两年),新的研究。arXiv
4、Seq2Seq2可拓展性比较强。e.g.事件抽取。