本文同步发布知乎:HFT-CNN:层级多标签分类,让你的模型多学习几次知乎主页lynne阿黎请大家不吝关注~
长文本由于自身的特点和信息量,一段文本会描述一个特定的主题。短文本由于其自身长度的原因是缺少这种特征的。一般对于短文本的处理会借鉴上下文的语料或者同义词来扩充短文本的含义。但是由于文本的领域相关性,上下文的语料和同义词的分布未必和原始语料一致。由于以上原因短文本分类一直受到人们的关注。
在深度学习领域,对于短文本分类CNN是一种常见的方法,但是这种方法通常需要大规模的语料。文中认为短文本的多标签分类任务所面临的的问题主要是由多标签带来的数据稀疏的问题。在多标签分类中,我们会遇到标签是平行和具有层级结构的情况,例如我们看新闻的时候有生活类,科技类,娱乐类,而娱乐类又会分为电影频道,电视剧频道等等。对于标签有层级关系的问题,文中提出了Hierarchical CNN结构。
文中文本分类的CNN模型类似于Text-CNN,输入是短文本sentence,sentence由词向量拼接而成,文中使用的是fasttext,接着使用卷积核为w的卷积层提取sentence的特征,然后添加max-pooling层,将这些池化层的的结果拼接然后经过全连接层和dropout得到上层标签[A,B,...]的概率,loss采用交叉熵。这是一个非常经典的CNN结构。
对于下层标签的预测文中的思路是在上层标签的预测中模型已经学到了通用的特征,但是深层layer应该去学习原始数据集中比较详细的信息。因此文中对embedding和卷积层参数保持不变,在这个基础上进行微调学习,这一步标签也由[A,B]变为[A1,A2,B1,B2]。
对于最终文本分类的结果判断文章采用了两种得分方式:
BSF(Boolean Scoring Function)
MSF(Multiplicative Scoring Function)
两种方法都是设置一个阈值,文本在某个分类的得分超过阈值则认为是该分类的。区别是BSF只有在文本被分到一级分类的情况下才会认为分类的二级分类是正确的,MSF没有这项限制。
其实说到这里大家应该明白了文章的基本思路,就我个人来说感觉是比较原始但又水到渠成。因此这里的代码感觉也没有什么好讲的,就是Finetune的思路,在原始模型上加了一层全连接层。需要注意的是作者使用的是chainer实现的,相比于torch和tensorflow比较小众。
# Network definition for HFT model
# =========================================================
if self.mode == "fine-tuning":
parameters = np.load('./CNN/PARAMS/parameters_for_multi_label_model_' + self.load_param_node_name + '.npz')
super(CNN, self).__init__()
set_seed_random(0)
with self.init_scope():
self.lookup = L.EmbedID(in_size = parameters['lookup/W'].shape[0], out_size = parameters['lookup/W'].shape[1], initialW = parameters['lookup/W'], ignore_label = -1)
self.conv1 = L.Convolution2D(self.in_channels,self.out_channels,(2, self.row_dim),stride=1,initialW=parameters['conv1/W'],initial_bias=parameters['conv1/b'])
self.conv2 = L.Convolution2D(self.in_channels,self.out_channels,(3, self.row_dim),stride=1,initialW=parameters['conv2/W'],initial_bias=parameters['conv2/b'])
self.conv3 = L.Convolution2D(self.in_channels,self.out_channels,(4, self.row_dim),stride=1,initialW=parameters['conv3/W'],initial_bias=parameters['conv3/b'])
self.l1=L.Linear(in_size = None, out_size = self.hidden_dim, initialW=self.initializer)
self.l2=L.Linear(in_size = self.hidden_dim, out_size = self.n_classes, initialW=self.initializer)
文中数据集采用RCV1和Amazon 670K,相关链接可以见相关资料部分。数据集的基本情况如下,L表示数据集标签的层级深度,TrTe表示训练数据和测试数据,C表示标签整体的量。分类的效果采用F1值进行衡量,此外还采用了P@k和NDCG@k标准。
文中将HFT-CNN和没有经过微调的CNN模型(WoFT-CNN)和没有经过层级结构标签处理的模型(Flat Model)进行对比,实验效果如下,其中B表示BSF,M表示MSF。
我们看到表格中有Micro和Macro这是什么意思呢?这是F1值得两种计算方式,对于单个分类来说在多分类的情况下计算F1值有两种方式,Micro和Macro。
Micro是不管类别,直接计算
Macro是将各个类别的F1计算之后然后进行平均
可以看出在效果上RCV1和Amazon 670K,HFT-CNN的效果都是优于其他模型的,但是在使用MSF得分和Micro F1值时WoFT的效果和HFT相同,但是在Macro F1的得分缺逊于HFT-CNN。这个我们猜测是因为WoFT整体效果比较好,但是在某一类上的分类效果差于HFT-CNN所以导致Macro F1值比较低,这也证明了HFT-CNN的初衷:对标签分类,模型先学习比较通用的知识,然后进行细分。
STOA效果文中主要对比了XML-CNN,实验效果如下,可以看到在两个数据集上,HFT-CNN的效果超越了目前的STOA的效果。
层级分类效果
文中统计了多个层级的文本分类效果,可以看出标签层级越深,分类效果越差,但是HFT-CNN的效果依然优于XML。
多标签数量
文中对于每个短文本的有多个分类的情况下对分类的数量的准确率进行了统计,可以看到分类越多识别的准确率越低。
训练数据规模
文中也讨论了训练数据的规模对实验结果的影响,可以看到训练数据越多实验效果越好。但是需要注意的是随着训练数据规模的降低,HFT-CNN的效果下降的较XML比较平缓。这表示经过多轮学习,HFT-CNN学到的语料内容更多一点。
相比于Bert和其他文章,这篇文章的模型结构是比较简单而且原始的,思路也感觉是Bert玩剩下的。预训练+Finetune已经是非常流行的手段了,所以我个人对这篇文章的定位应该是术而不是道。文中对于标签层级结构的理解是非常具有启发性的,如果大家要用Bert的话也可以据此设计一些相关的预训练任务,比如让模型去学习二级标签或二级标签是否正确等,这样模型可以有针对性的学习。
但是文中的思想同样存在一个问题就是标签层级的划分,以及不同标签的不相关性。如果标签层级本身就划分不清楚,或标签自身有重叠,那么这样模型可能依旧无法准确的对文本进行判断。同时文章中提到了数据稀疏的问题,随着层级结构的划分,低级标签的训练文本应该比较少,那么模型是否可以如我们所想学到预期的知识这也是值得探索的。那么这时候或许我们就应该使用一些方法进行数据增强了。