本文整理自AI Challenger 2018 第4名PPT分享—细粒度情感分析赛道,仅作个人笔记使用。
总体方案设计
Idea
对问题进行分析可得到以下基本关系:
- 文本序列输入
- 20个粒度,每个粒度有4个类
- 粒度之间有相关性
- 细粒度之间的相关性,如dish_taste与dish_recommendation,price_level与price_cost_effective
- 粗粒度之间的相关性,比如others(overall experience,will to consume again)与其他粗粒度
模型架构
针对序列输入、序列输出以及粒度相关性这几个特性,很容易联想到seq2seq模型。
这个架构来自于论文SGM: Sequence Generation Model for Multi-Label Classification,作者对其进行了一些微小改动,后面我们会详细介绍这篇文章。
各模块介绍
数据处理
数据处理这一部分都很常规,具体分为下面几个部分:
- 分词工具使用了ltp
- 建立词典时,过滤掉出现次数小于5的词:训练集、验证集以及测试集a组成的语料,词典大小为66347
- 训练和预测时,词典中未出现的词用
<unk>
代替
词嵌入层
ELMo模型
词嵌入层使用了Elmo模型。基本结构如下:
从图中可见模型是双向的语言模型,前向的使用很
预测不错
,后向使用很
预测味道
。并且CNN层和输出层是共享参数的。
V
0
V_0
V0只有一个,而
V
1
V_1
V1由
V
1
←
V_1\leftarrow
V1←和
V
1
→
V_1\rightarrow
V1→组成,
V
2
V_2
V2同理。
V
1
V_1
V1、
V
2
V_2
V2、
V
3
V_3
V3可作为针对某一任务模型的词向量的输入。最简单的方法是取最上层的输出作为整个词向量表示,但是效果不是很好,更通常的做法是对几层的输出进行加权平均作为词向量表示。
预训练ELMo
作者指出ELMo模型参数和官方模型参数相同。利用所有评论预料训练词向量,共计约7600万tokens。
首先将训练集、验证集、测试集a整合起来作为语料库,然后对每条评论进行分词。之后统计词频过滤到出现次数小于5次的词并建立词典。再将语料库中出现的但是词典中未出现的词替换为<unk>
并送入ELMo模型中与训练,最后将预训练模型保存下来。
生成词向量
利用预训练好的模型生成词向量,作为模型的输出。这里使用的是几层输出的加权平均,之后再进行降维到300。作者指出ELMo相对于Fasttext生成词向量F1score值可以提升0.013.
这里有一点作者没有说清楚,在训练分类模型的时候是否进行梯度回传更新ELMo模型的参数,如果需要更新,则模型的训练的速度会非常慢。我们假设不需要更新,那么我们可以使语料只进行一次ELMo模型,得到每句话的词向量表示,然后将其保存到硬盘上,之后分类模型每轮迭代我们只需要直接加载这个词向量即可。这样的话,ELMo每层输出的加权系数就是不可学习的了,只能根据经验来设置。
编码层
编码层的设置也比较常规:
- 两层双向LSTM
- 在输入与每层输出应用dropout
- 最大步长设置为600:可覆盖98%的样本点
注意力机制
作者使用了改进的加法注意力机制(BahdanauAttention),所谓改进,仅仅是对每个
q
(
Q
=
{
q
i
}
)
q(Q=\{q_i\})
q(Q={qi})使用不同的参数来获得加权系数。
下面简要介绍一下常见的两种注意力机制:
Bahdanau Attention
该种注意力机制又叫做加法注意力。
对于翻译系统,解码器第
i
i
i个时刻的输出概率分布可以表示为:
p
(
y
i
∣
y
1
,
.
.
.
,
y
i
−
1
,
x
)
=
g
(
y
i
−
1
,
s
i
,
c
i
)
p(y_i|y_1,...,y_{i-1}, x)=g(y_{i-1},s_i,c_i)
p(yi∣y1,...,yi−1,x)=g(yi−1,si,ci)
其中
s
i
s_i
si是第
i
i
i个时刻的隐状态,可以由如下方式求得:
s
i
=
f
(
s
i
−
1
,
y
i
−
1
,
c
i
)
s_i = f(s_{i-1},y_{i-1}, c_i)
si=f(si−1,yi−1,ci)
其中
c
i
c_i
ci是目标词
y
i
y_i
yi的context vector。
c
i
c_i
ci可以表示为
h
i
h_i
hi的加权和:
c
i
=
∑
j
=
1
T
x
α
i
j
h
j
c_i=\sum_{j=1}^{T_x}\alpha_{ij}h_{j}
ci=j=1∑Txαijhj
α
i
j
=
e
x
p
(
e
i
j
)
∑
k
=
1
T
x
e
x
p
(
e
i
k
)
\alpha_{ij}=\frac {exp(e_{ij})}{\sum_{k=1}^{T_x}{exp(e_{ik})}}
αij=∑k=1Txexp(eik)exp(eij)
e
i
j
=
a
(
s
i
−
1
,
h
j
)
e_{ij}=a(s_{i-1}, h_j)
eij=a(si−1,hj)
函数
a
(
)
a()
a()是一个对齐模型,它的值可以用来衡量输入位置
j
j
j附近几个词和输出位置
i
i
i的匹配程度。通常该模型常用一个前馈神经网络来实现。
注意到
e
i
j
e_{ij}
eij的计算方法,
a
a
a是一个前馈神经网络,我们可以将其简化为如下形式:
e
i
j
=
a
(
s
i
−
1
,
h
j
)
=
f
(
W
1
s
i
−
1
+
W
2
h
j
)
e_{ij}=a(s_{i-1},h_j)=f(W_1s_{i-1}+W_2h_j)
eij=a(si−1,hj)=f(W1si−1+W2hj)
可见,
s
i
−
1
s_{i-1}
si−1与
h
j
h_j
hj并没有直接交互,而是通过线性组合的方式,这应该也是其又称为加法注意力的原因。
Luong Attention
该方法又叫作乘法注意力。
该方法与加法注意力相似度很高,仅仅是作了一点点调整,其中Attention计算方法如下:
a
t
(
s
)
=
a
l
i
g
n
(
h
t
,
h
‾
s
)
=
e
x
p
(
s
c
o
r
e
(
h
t
,
h
‾
s
)
)
∑
s
′
e
x
p
(
s
c
o
r
e
(
h
t
,
h
‾
s
′
)
)
a_t(s)=align(h_t,\overline h_s)=\frac {exp(score(h_t, \overline h_s))} {\sum_{s^{'}}exp(score(h_t, \overline h_{s^{'}}))}
at(s)=align(ht,hs)=∑s′exp(score(ht,hs′))exp(score(ht,hs))
其中,
h
‾
s
′
\overline h_{s^{'}}
hs′表示编码器的第
s
′
s^{'}
s′个时刻的隐状态,
h
t
h_t
ht表示解码器第
t
t
t个时刻的隐状态。
context vector计算如下:
c
t
=
∑
s
′
a
t
s
′
h
‾
s
′
c_t=\sum_{s^{'}} a_{ts^{'}} \overline h_{s^{'}}
ct=s′∑ats′hs′
和加法注意力相比,改进了如下几点:
- Bahdanau Attention对Encoder和Decoder的双向的RNN的state拼接起来作为输出,LuongAttention仅使用最上层的RNN输出
- Bahdanau Attention的计算流程为 h t − 1 h_{t−1} ht−1 → a t a_t at → c t c_t ct → h t h_t ht(这里的 h h h对应于第一个图中的 s s s),它使用前一个位置 t − 1 t-1 t−1的state计算t时刻的 h t h_t ht。Luong Attention计算流程为 h t h_t ht → a t a_t at → c t c_t ct → h ^ t \hat h_t h^t使用 t t t位置的state当前位置的 h ^ t \hat h_t h^t
- Bahdanau Attention只在concat对齐函数上进行了实验,LuongAttention在多种对齐函数进行了实验,下面给出LuongAttention设计的三种对齐函数:
y = { h t T h ‾ s d o t h t T W a h ‾ s g e n e r a l v a T t a n h ( W a [ h t ; h ‾ s ] ) c o n c a t y=\begin{cases} h_t^T\overline h_s & dot \\ h_t^TW_a\overline h_s & general \\ v_a^Ttanh(W_a[h_t;\overline h_s]) & concat \end{cases} y=⎩⎪⎨⎪⎧htThshtTWahsvaTtanh(Wa[ht;hs])dotgeneralconcat
可见两种注意力机制最大的不同即在于注意力函数的计算方法,前者是利用 s t − 1 s_{t-1} st−1和 h j h_j hj来计算 s t s_t st;后者是利用 s t s_t st和 h j h_j hj来计算 s ^ t \hat s_t s^t。从直觉上来看后者更合理,但是在实际使用中两者差距并不是很大。
解码器
两层LSTM,每一层的输出应用dropout。解码方法使用了Global Embedding,相对于Beam search,F1提升了0.005.相较于原论文,该方法在此处使用时固定解码步数为20步,对应20个粒度。这20个粒度的顺序需要我们根据相关性来确定。
SGM
原论文为Sequence Generation Model for Multi-Label Classification。源码.
Abstract
这篇文章主要是为了解决多标签的分类问题。该类问题比单标签类别分类更复杂,因为类别之间往往存在相关性,已经存在的方法往往都忽略了这种相关性。该文章提出了将多标签分类问题转换为序列生成问题并利用带有新的解码结构的序列生成模型来解决这个问题。实验证明,该方法不仅能够捕捉不同labels之间的相关性,为且能为预测不同labels时选出贡献最大的词(注意力机制)。
Proposed Method
Overview
我们首先对多标签分类问题下一些定义,给定label space
L
L
L,
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个labels的子集
y
y
y和序列
x
x
x对应起来。从序列生成的角度来看,多标签分类问题可以视为寻找使得条件概率
p
(
y
∣
x
)
p(y|x)
p(y∣x)最大的最优label序列
y
∗
y^*
y∗:
p
(
y
∣
x
)
=
∏
i
=
1
n
p
(
y
i
∣
y
1
,
y
2
,
.
.
.
,
y
i
−
1
,
x
)
p(y|x)=\prod_{i=1}^np(y_i|y_1,y_2,...,y_{i-1},x)
p(y∣x)=i=1∏np(yi∣y1,y2,...,yi−1,x)
模型的整体结构如下:
首先,我们需要根据训练集中标签出现的频率为每个样本的label序列进行排序。高频labels放在前面。除此之外,bos
和eos
分别加到label序列的头部和尾部。
这里的注意力机制使用的是加法注意力,即
c
t
c_t
ct的计算依赖了
s
t
−
1
s_{t-1}
st−1。我们还可以看出
s
t
s_t
st由
c
t
、
s
t
−
1
、
g
(
y
t
−
1
)
c_t、s_{t-1}、g(y_{t-1})
ct、st−1、g(yt−1)计算得到。这里
y
t
−
1
y_{t-1}
yt−1是预测得到的
t
−
1
t-1
t−1步在
L
L
L的概率分布。函数
g
g
g用于产生embedding vector。masked softmax用于输出概率分布
y
t
y_t
yt。
Sequence Generation
Encoder
one-hot编码的token经过embedding层得到词向量,然后输入双向LSTM中。这一步很常规。
Attention
这部分的求解公式跟前面矛盾,这里的
c
t
c_t
ct求解又依赖于
s
t
s_t
st了。
e
t
i
=
v
a
T
t
a
n
h
(
W
a
s
t
+
U
a
h
i
)
e_{ti}=v_a^Ttanh(W_as_t+U_ah_i)
eti=vaTtanh(Wast+Uahi)
α
t
i
=
e
x
p
(
e
t
i
)
∑
j
=
1
m
e
x
p
(
e
t
j
)
\alpha_{ti}=\frac {exp(e_{ti})} {\sum_{j=1}^m exp(e_{tj})}
αti=∑j=1mexp(etj)exp(eti)
c
t
=
∑
i
=
1
m
α
t
i
h
i
c_t = \sum_{i=1}^m \alpha_{ti}h_i
ct=i=1∑mαtihi
Decoder
这部分也是跟前面和图片矛盾:
s
t
=
L
S
T
M
(
s
t
−
1
,
[
g
(
y
t
−
1
)
;
c
t
−
1
]
)
s_t=LSTM(s_{t-1},[g(y_{t-1});c_{t-1}])
st=LSTM(st−1,[g(yt−1);ct−1])
图片中和前文所述都是
s
t
s_t
st是由
c
t
c_t
ct求解得到的。上式中
g
(
y
t
−
1
)
g(y_{t-1})
g(yt−1)是
y
t
−
1
y_{t-1}
yt−1的分布中概率最高的label的embedding。
o
t
=
W
o
f
(
W
d
s
t
+
V
d
c
t
)
o_t = W_of(W_ds_t+V_dc_t)
ot=Wof(Wdst+Vdct)
y
t
=
s
o
f
t
m
a
x
(
o
t
+
I
t
)
y_t=softmax(o_t+I_t)
yt=softmax(ot+It)
其中,
I
t
I_t
It是mask vector用来防止重复预测同一个标签,
f
f
f是一个非线性激活函数。
y
=
{
−
∞
l
i
r
e
p
e
a
t
e
d
w
i
t
h
p
r
e
v
i
o
u
s
0
o
t
h
e
r
w
i
s
e
y=\begin{cases} -\infty & l_i\ repeated\ with\ previous \\ 0 & otherwise \end{cases}
y={−∞0li repeated with previousotherwise
在训练阶段,损失函数是交叉熵损失函数。在预测阶段,我们应用了beam search算法来找到前几个路径。预测路径以eos
结尾并加到候选路径集中。
Global Embedding
上文中embedding vector
g
(
y
t
−
1
)
g(y_{t-1})
g(yt−1)是分布
y
t
−
1
y_{t-1}
yt−1中概率最高的label的embedding。这是一种贪心的做法,会导致前面步骤的误判到后面会越积累越大,这叫做exposure bias。Beam search算法可以在一定程度上缓解这种情况,然而它没有从根本上解决这个问题,因为exposure bias现象很可能出现在所有的候选路径中。
y
t
−
1
y_{t-1}
yt−1表示
t
−
1
t-1
t−1步时预测的概率分布,很明显它的所有信息对于我们下一步的预测都是有帮助的。因此,应当把
y
t
−
1
y_{t-1}
yt−1步中的所有信息都考虑进去来缓解exposure bias问题。
基于上述思路,我们提出global embedding。令
e
e
e表示
y
t
−
1
y_{t-1}
yt−1中概率最大的label的embedding,
e
‾
\overline e
e表示时刻
t
t
t的加权平均embedding:
e
‾
=
∑
i
=
1
L
y
t
−
1
(
i
)
e
i
\overline e=\sum_{i=1}^L y_{t-1}^{(i)}e_i
e=i=1∑Lyt−1(i)ei
其中
y
t
−
1
(
i
)
y_{t-1}^{(i)}
yt−1(i)表示
y
t
−
1
y_{t-1}
yt−1的第
i
i
i个元素,
e
i
e_i
ei表示第
i
i
i个label的embedding。
global计算方法如下:
g
(
y
t
−
1
)
=
(
1
−
H
)
∘
e
+
H
∘
e
‾
g(y_{t-1})=(1-H)\circ e + H \circ\overline e
g(yt−1)=(1−H)∘e+H∘e
其中
H
H
H控制门用来控制加权平均的embedding的比例。
H
=
W
1
e
+
W
2
e
‾
H = W_1e+W_2\overline e
H=W1e+W2e
H
H
H可以自动确定每个维度上的组合因子。通过考虑所有label的概率,模型能够减少由于前面步骤中错误的预测带来的损失。
Experiments and Details
数据集和超参数选取的细节可以参考原论文。
Analysis and Discussion
Global Embedding
g
(
y
t
−
1
)
=
(
1
−
λ
)
∗
e
+
λ
∗
e
‾
g(y_{t-1})=(1-\lambda)*e + \lambda * \overline e
g(yt−1)=(1−λ)∗e+λ∗e
实验证明
λ
\lambda
λ值对结果影响很大,手动选取不如学习得到。下图展示了选取不同的
λ
\lambda
λ对实验结果的影响。
The Impact of Mask and Sorting
结论就是Mask和Sorting都很重要。
Error Analysis
我们还发现随着label序列长度的增加,所有方法的效果都会变差。SGM模型按照顺序生成labels,基于之前的预测的labels来预测下一个label。因此,即使样本包含正确的labels的相关信息很少,该模型仍然能够根据之前预测的相关的labels来实现正确的预测。
损失函数
评价指标为F1,与交叉熵优化目标不一致。因此采用Precision-Recall AUC损失函数,F1提升了0.003.关于该方法更多的信息可以参考这里.
训练策略
超参数
- SGD
- Batch size:64
- Adam optimizer
- Learning rate: 初始值为 1 e − 3 1e-3 1e−3,没完成一个epoch降低为原来的0.8倍,降到 1 e − 4 1e-4 1e−4之后保持不变
训练过程
epoch<=5时,每轮迭代计算一次F1值;epoch>5时,每一百步计算一次F1值。
提分点与tricks
数据增强方法
训练数据分类别样本点统计
数据增强策略
- 上采样
- 样本点特别少
- F1特别低
- 加入随机噪声
- 上采样得到的样本点,随机打乱句子顺序