文本分类的一些思考

前言

是这样的,最近业务同学有一个视频标题分类的需求,理论上成熟方案有很多:

  • 词嵌入向量化:word2vec,tfidf,glove,sent2vec,QT,FastText等等
  • 卷积神经网络特征提取:TextCNN,CharCNN等等
  • 上下文机制:TextRNN,BiLstm,RCNN等等
  • Attention机制:EntNet,DMN, HAN等等
  • 预训练机制:Bert,XLNet等等

但是业务同学提了两个要求,要一周效果达到可上线标准且线上预测耗时不能超过10ms,所以直接排除3,4,5项。就让组里面的同学用词嵌入向量化或者卷积神经网络特征提取去解决一下,这边整理了我们在做的过程中的一些事情。

词嵌入向量化就不说了,tfidf+svm确定了baseline准确率在0.7,因为我们是40分类,所以在实际做的过程中我们用了oneVsOthers,怼了N层的二分,整个工程代码极其丑陋,这边主要说我们做TextCnn过程的一些记录。

数据处理

我们第一轮的准确率做出来在65%,所有在场的小伙伴都惊呆了,做出来的效果比baseline还低,第一反应就是数据没有进行合理预处理。后面我们发现,存在以下的问题:

  • 分词后的数据存在同样的分词结果对应不同的label
  • 因为是短文本,部分分词后长度不足3
  • 部分数据异常,存在几条数据切词后有100多个词,导致整体的padding规模过大,大多数都padding了几十个这个存疑,我觉得没影响,组里的同学表示改了有1个点的提升
  • 部分垂类的数据不平衡,比如运势在300多万的训练数据中只有不到1万条
  • 在剔除高频词的时候剔除不少实体词,而这些实体词恰好完全对应一个专有垂类,比如新冠—>健康,特普朗—>时政

没错,其实看到这里,我们主要提升的模块讲完了,事情就是这么残酷,把上面的都改了之后,准确达到了75%,已经达到上线标准了。
实际上,如果能把数据清洗到一个比较干净的程度,带来的提升远远比做各种花里胡哨的算法要更有性价比,但是我们没有停止,因为根据之前的经验,简单做一下,79~81%的准确率还是很容易的。

模型优化

当我们数据处理完之后,我们就去看了这些短文本,我们发现了几个问题:

  • textCNN对3-4词的文本预测,和10个词以上文本预测的效果不好
  • 很容易把绝大多数的词相似的句子预测成同一种,比如《南京是中国经济的卓越成就贡献者》和《南京是中国抗战的卓越成就贡献者》,都会预测为历史
  • textCNN得到了word Embedding不太相似,历史的相似词居然是时光,时间,未来,明鉴
  • 视频内容分布时效性很关键,很多新词,OOV的情况在校验集比较严重

针对每个问题,我做了一些有优化,这边记录其中有效的:

1.textCNN对3-4词的文本预测,和10个词以上文本预测的效果不好

我们做了ensemble,训练过程中3-4词样本剔除,10个词以上的数据上(占比25%)我们用了fasttext,5-10个词的数据,我们用了textcnn,提升了0.5点左右

2.很容易把绝大多数的词相似的句子预测成同一种

meta-feature的使用,我们引入了词性作为另外一个textCNN的embedding层,在最后conv-maxPooling-fc后进行concat,举个例子,[今天,天气,真好]作为input的同时,也将其对应的词性[‘TIME’, ‘n’, ‘a’]也做了另一路的input,相当于告诉了分类器,虽然词都一样,但是不同词在不同的语境下不完全一致,提升了1.8%左右

3.textCNN得到了word Embedding不太相似

分别引入了预训练好的glove,word2vec和sent2vec的词向量,及做了多个向量的拼接,且实现了同时召回多个,最后发现,单独用word2vec的embedding结果就完全够了。这边word2vec训练数据是1.2亿条资讯文本,词库大小是1000千万,提升了1.2%左右

4.视频内容分布时效性很关键,很多新词,OOV的情况在校验集比较严重

我们构造了原始数据集合,我们的逻辑如下:

  • 只存在一个指定词性(‘nw’,’PER’,’ORG’,’nz’,’LOC’)的句子不变
  • 存在2个以上指定词性(‘nw’,’PER’,’ORG’,’nz’,’LOC’)的句子,随机替换指定词性个数//2个指定词性词
  • 替换的句子只用在训练集合

这个在离线测试上没有带来任何效果提升,在线上abtest带来了0.2pp的点检准确率的提升。

就这样,通过以上的方案我们把准确率提高到了78.7%。当然我们也做了很多其他尝试,但是都没有什么好结果,比如改大filtersize,降低learningrate,提高epoch,把网络变得更深更宽。

一些不稳定的现象

以下策略,我们做了之后发现结果会震荡,对结果和基线相比会一天好一天坏,可能是还没有找到合适的用法方式:

  • 在word embedding look_up结果后进行dropout,这个训练的结果一次好一次坏
  • 在机器可接受的范围下狂怼batch_size和filter个数,每个filter下的size个数,这个导致部分情况下不容易收敛,loss一直在震荡
  • 把多分类问题变成多个二分类问题,离线评估有收益,线上ab效果不明显

总结

以上测试了很多方案,不管数据预处理还是模型优化,对短文本分类这个问题,能带来提升比较大的是扩充了原始数据信息的行为,比如meta-feature,pretrained embedding,清除异常点数据(运势);无效的操作通常是去改改网络结构,换个激活函数,加个新的网络结构之类,梯度放缩,focal loss。收益折中的通常是,数据量足够的情况下,强行破坏分布的行为,都是薛定谔的调参。

另外,在短文本文本分类,如果不考虑预测耗时的情况下,理论上双向gru专治各种花里胡哨的structure,之后有机会可以和大家讨论下这个方法的调参。

打赏的大佬可以联系我,赠送超赞的算法资料