问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深度学习文本分类|模型&代码&技巧

创作时间:
作者:
@小白创作中心

深度学习文本分类|模型&代码&技巧

引用
1
来源
1.
https://developer.volcengine.com/articles/7383082504007188517

文本分类是自然语言处理(NLP)领域的基础任务之一,在搜索、推荐、对话系统等多个场景中都有广泛应用。本文将详细介绍深度学习在文本分类中的常用模型及其原理、优缺点,以及一些实用的技巧和建议。

Fasttext

Fasttext是Facebook推出的一个便捷的文本分类工具,它不仅支持文本分类,还具备词向量训练功能。

Fasttext的分类实现相对简单:将输入文本转化为词向量,计算平均值,然后通过线性分类器得到最终类别。输入的词向量可以是预训练好的,也可以随机初始化并随分类任务一起训练。

Fasttext具有以下优点:

  1. 模型复杂度低但效果不错,适合快速建立基准模型
  2. 采用C++实现,计算效率高
  3. 通过char-level的n-gram特征解决长尾词的OOV问题
  4. 支持层次化softmax分类,提升多类别场景的效率

对于文本较长且对速度要求较高的场景,Fasttext是一个很好的基准选择。同时,它在无监督语料上训练词向量进行文本表示的效果也不错。但若要继续提升效果,可能需要更复杂的模型。

TextCNN

TextCNN是Yoon Kim在2014年提出的模型,开创了使用卷积神经网络(CNN)编码n-gram特征的先河。

模型结构如图所示,其中使用了一维卷积,filter的大小为filter_size * embedding_dim。具体前向逻辑如下:

  1. 对词进行embedding,得到[seq_length, embedding_dim]
  2. 使用N个卷积核,得到N个seq_length-filter_size+1长度的一维feature map
  3. 对feature map进行max-pooling(也称max-over-time pooling),得到N个1x1的数值,拼接成一个N维向量作为文本表示
  4. 将N维向量压缩到类目个数的维度,过Softmax

在实践中,TextCNN有很多优化方向:

  1. Filter尺寸:根据数据平均长度选择合适的尺寸
  2. Filter个数:在100-600之间调参
  3. CNN的激活函数:尝试Identity、ReLU、tanh
  4. 正则化:使用dropout或L2
  5. Pooling方法:选择mean、max、k-max pooling
  6. Embedding表:选择char或word级别的输入
  7. 蒸馏BERT的logits
  8. 加深全连接层

TextCNN适合中短文本场景,但不太适合长文本,因为卷积核尺寸通常不会设很大,无法捕获长距离特征。同时max-pooling也会丢掉一些有用特征。本质上,TextCNN和传统的n-gram词袋模型相似,其好效果很大程度上得益于词向量的引入。

DPCNN

DPCNN是腾讯在2017年提出的一种深度CNN模型,解决了TextCNN深度不足和长距离依赖的问题。

DPCNN的核心改进包括:

  1. 在Region embedding时采用pooling后加1x1卷积的方式
  2. 使用1/2池化层,让模型可编码的sequence长度翻倍
  3. 引入残差链接,缓解梯度弥散问题

这些改进使得DPCNN相比TextCNN有1-2个百分点的性能提升。

TextRCNN

TextRCNN通过引入RNN来缓解长距离依赖问题。其前向过程包括:

  1. 得到单词i的表示
  2. 通过RNN得到左右双向的表示
  3. 将表示拼接得到,再经过变换得到
  4. 对多个进行max-pooling,得到句子表示,进行最终分类

通过加入RNN,TextRCNN比纯CNN提升了1-2个百分点。

TextBiLSTM+Attention

这个模型采用先编码token,再pooling出句子表示的框架。在最终池化时,max-pooling通常表现更好,因为文本分类经常是主题上的分类,从句子中一两个主要的词就可以得到结论,其他大多是噪声,对分类没有意义。而到更细粒度的分析时,max-pooling可能又把有用的特征去掉了,这时便可以用attention进行句子表示的融合:

BiLSTM就不解释了,要注意的是,计算attention score时会先进行变换:

其中是context vector,随机初始化并随着训练更新。最后得到句子表示,再进行分类。

这个加attention的套路用到CNN编码器之后代替pooling也是可以的,从实验结果来看attention的加入可以提高2个点。如果是情感分析这种由句子整体决定分类结果的任务首选RNN。

HAN

HAN(Hierarchical Attention Network)针对长文本分类问题,提出了层次注意力分类框架。其结构如下:

先对每个句子用BiGRU+Att编码得到句向量,再对句向量用BiGRU+Att得到doc级别的表示进行分类。

这种方法虽然符合直觉,但实验结果来看比起avg、max池化只高了不到1个点。

BERT

BERT的原理代码就不用放了叭~BERT分类的优化可以尝试:

  1. 多试试不同的预训练模型,比如RoBERT、WWM、ALBERT
  2. 除了[CLS]外还可以用avg、max池化做句表示,甚至可以把不同层组合起来
  3. 在领域数据上增量预训练
  4. 集成蒸馏,训多个大模型集成起来后蒸馏到一个上
  5. 先用多任务训,再迁移到自己的任务

其他模型

除了上述常用模型之外,还有Capsule Network、TextGCN等红极一时的模型,因为涉及的背景知识较多,本文就暂不介绍了(嘻嘻)。虽然实际的落地应用中比较少见,但在机器学习比赛中还是可以用的。Capsule Network被证明在多标签迁移的任务上性能远超CNN和LSTM,但这方面的研究在18年以后就很少了。TextGCN则可以学到更多的global信息,用在半监督场景中,但碰到较长的需要序列信息的文本表现就会差些。

技巧

模型说得差不多了,下面介绍一些自己的数据处理血泪经验,如有不同意见欢迎讨论~

数据集构建

首先是标签体系的构建,拿到任务时自己先试标一两百条,看有多少是难确定(思考1s以上)的,如果占比太多,那这个任务的定义就有问题。可能是标签体系不清晰,或者是要分的类目太难了,这时候就要找项目owner去反馈而不是继续往下做。

其次是训练评估集的构建,可以构建两个评估集,一个是贴合真实数据分布的线上评估集,反映线上效果,另一个是用规则去重后均匀采样的随机评估集,反映模型的真实能力。训练集则尽可能和评估集分布一致,有时候我们会去相近的领域拿现成的有标注训练数据,这时就要注意调整分布,比如句子长度、标点、干净程度等,尽可能做到自己分不出这个句子是本任务的还是从别人那里借来的。

最后是数据清洗:

  1. 去掉文本强pattern:比如做新闻主题分类,一些爬下来的数据中带有的XX报道、XX编辑高频字段就没有用,可以对语料的片段或词进行统计,把很高频的无用元素去掉。还有一些会明显影响模型的判断,比如之前我在判断句子是否为无意义的闲聊时,发现加个句号就会让样本由正转负,因为训练预料中的闲聊很少带句号(跟大家的打字习惯有关),于是去掉这个pattern就好了不少
  2. 纠正标注错误:这个我真的屡试不爽,生生把自己从一个算法变成了标注人员。简单的说就是把训练集和评估集拼起来,用该数据集训练模型两三个epoch(防止过拟合),再去预测这个数据集,把模型判错的拿出来按abs(label-prob)排序,少的话就自己看,多的话就反馈给标注人员,把数据质量搞上去了提升好几个点都是可能的

长文本

任务简单的话(比如新闻分类),直接用fasttext就可以达到不错的效果。

想要用BERT的话,最简单的方法是粗暴截断,比如只取句首+句尾、句首+tfidf筛几个词出来;或者每句都预测,最后对结果综合。

另外还有一些魔改的模型可以尝试,比如XLNet、Reformer、Longformer。如果是离线任务且来得及的话还是建议跑全部,让我们相信模型的编码能力。

少样本

自从用了BERT之后,很少受到数据不均衡或者过少的困扰,先无脑训一版。

如果样本在几百条,可以先把分类问题转化成匹配问题,或者用这种思想再去标一些高置信度的数据,或者用自监督、半监督的方法。

鲁棒性

在实际的应用中,鲁棒性是个很重要的问题,否则在面对badcase时会很尴尬,怎么明明那样就分对了,加一个字就错了呢?

这里可以直接使用一些粗暴的数据增强,加停用词加标点、删词、同义词替换等,如果效果下降就把增强后的训练数据洗一下。

当然也可以用对抗学习、对比学习这样的高阶技巧来提升,一般可以提1个点左右,但不一定能避免上面那种尴尬的情况。

总结

文本分类是工业界最常用的任务,同时也是大多数NLPer入门做的第一个任务,我当年就是啥都不会,从训练到部署地实践了文本分类后就顺畅了。上文给出了不少模型,但实际任务中常用的也就那几个,下面是快速选型的建议:

实际上,落地时主要还是和数据的博弈。数据决定模型的上限,大多数人工标注的准确率达到95%以上就很好了,而文本分类通常会对准确率的要求更高一些,与其苦苦调参想fancy的结构,不如好好看看badcase,做一些数据增强提升模型鲁棒性更实用。

参考资料
[1] A Sensitivity Analysis of (and Practitioners' Guide to) Convolutional Neural Networks for Sentence Classification:https://arxiv.org/pdf/1510.03820.pdf
[2] 卷积层和分类层,哪个更重要?:https://www.zhihu.com/question/270245936
[3] 从经典文本分类模型TextCNN到深度模型DPCNN:https://zhuanlan.zhihu.com/p/35457093
[4] 揭开迷雾,来一顿美味的Capsule盛宴:https://kexue.fm/archives/4819
[5] Graph Convolutional Networks for Text Classification:https://arxiv.org/abs/1809.05679
[6] 胶囊网络(Capsule Network)在文本分类中的探索:https://zhuanlan.zhihu.com/p/35409788
[7] 怎么看待最近比较火的 GNN?:https://www.zhihu.com/question/307086081/answer/717456124

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号