Skip to content

IceFlameWorm/ai_challenger_sentiment

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Challenger Sentiment

因为想要学习一下深度学习+NLP,所以最近就抽空参加了一下“细粒度用户评论情感分析”这个比赛。但是平时还要工作、带娃,没有太多精力打比赛,最终只有两周多的时间参加了A榜的比赛,成绩也马马虎虎,只能排到A榜top13%左右。

比赛简介

比赛链接为:https://challenger.ai/competition/fsauor2018。

该比赛所处理的"细粒度用户评论情感分析“属于多标签-多分类问题。

模型框架

针对“多标签-多分类”问题,分别尝试了“单模型”和“多模型”两种不同类型的架构。由于没有太多的时间尝试,只采用了textcnn和单/双层的rnn作为基础网络。

单模型

所谓单模型,即单输入-多输出模型, 也可称之为多任务模型, 只接收一个输入,每个标签都对应一个输出。在这种架构下,由于不同的输出之间需要共享低层的网络层,因此不同的共享方式,会对模型的效率和分数产生不同的影响。

在本次比赛中,我尝试了两种不同的共享策略:1. 所有的输出共享相同的低层网络层,2. 根据每个细粒度所属于的大类分组,同一组的输出共享相同的低层网络层, 不同组的输出之间不共享低层网络层。试验对比下来,在训练和预测效率上,第一种策略优于第二种,但是在模型分数上,第二种策略往往要好于第一种。具体实现可以参考 models/own.py

多模型

所谓多模型,即单输入-单输出模型, 为每一个粒度各构建一个模型。为了方便,每个粒度都使用相同的模型架构,但分开训练。相较于单模型架构,这种方式建模相对简单,不涉及低层网络层的共享问题,调参难度相对小一些。在执行效率上,当模型比较简单时,单模型的效率要远好于多模型,但当模型比较复杂,参数量较多时, 单模型和多模型在执行效率上差距缩小的比较大。在模型分数上,当用相同的基础模型时, 多模型上的分数基本上都好于单模型,猜测可能的原因是没有对单模型的参数进行细致的调整,而且每个粒度可能需要不同的迭代次数才能达到最优的分数。多模型的实现可以参考 models/textrnn.py

代码结构

本次比赛使用的深度学习框架是keras,后端tensorflow,python环境3.5, 下面是代码的组织结构(本来想好好整理的,但是有些懒散,望见谅):

ai_challenger_sentiment/
|-- README.md
|-- __pycache__
|   `-- env.cpython-35.pyc
|-- data # 用于保存各种数据处理结果
|   |-- caches
|   |-- dataset
|   |-- features
|   |-- interresults
|   |-- results
|   |-- saved_models
|   `-- stopwords
|-- env.py # 项目相关的路径信息
|-- models # 模型文件
|   |-- __init__.py
|   |-- __pycache__
|   |-- base.py # 模型基类, 定义了最基本的接口
|   |-- fasttext.py # FastText模型
|   |-- linxi.py # 前期尝试,并未继承基类
|   |-- own.py # 单模型框架类, 利用粗粒度对细粒度进行了分组,继承该类,重写相应接口,可以 1)实现不同的网络层共享方式,2)采用不同的基础网络架构,比如textcnn,textrnn等, 比赛时为了方便,虽然写了这个框架,但是直接在框架里改了,没派生子类。。。  但是通过继承的方式更有利于后期维护和复用。
|   |-- sentiment_base.py # (单/多)模型基类,继承自base.py,封装实现了单模型和多模型框架的训练和预测逻辑等,派生的子类可以直接复用相应方法。
|   |-- textcnnpy # TextCNN模型
|   `-- textrnn.py # TextRNN模型, 继承BaseRNN模型,改写_rnn接口可以实现不同的rnn结构。
|-- notebooks
|   |-- eda
|   |-- test
|   |-- train
|   `-- transform
|-- requirements.txt
|-- scripts # 数据处理相关的脚本
|   |-- segment_chars.py # 字符级,由于时间原因,最终并没有尝试字符级的特征。
|   `-- segment_words.py # 词语级, 去除特殊字符,繁简体转换,停用词,分词等等。
`-- utils
    |-- __init__.py
    |-- __pycache__
    |-- augment.py # 数据增强,时间原因,比赛中并未应用。
    |-- callbacks.py # 自定义的keras callback,其中CyclicLR, 引自他处,可用于实现周期性学习率;CustomModelCheckPoint, 自己编写的callback,根据macro-f1来保存最优的模型。
    |-- dataset.py # 数据集类,用来管理数据集
    |-- metrics.py # 自己实现的batch-wise的micro,macro f1
    `-- transform.py # 数据处理用到的api

比赛体会

  1. 合适的数据预处理对模型提升有很大的增益,比如句子最大长度、停用词等参数的设置等。
  2. 词向量使用方式(静态,动态,随机初始化等)会对结果有一定影响。
  3. 词向量的维数不能太小,适当取大一些会有比较好的效果。
  4. 当模型效果难以提升,或者是收敛缓慢,可以尝试使用更深更宽的模型。
  5. 当出现过拟合时,更深更宽的模型+dropout等,比浅层模型或小学习率更好。
  6. 模型深度两层基本就可以了,更深也不一定带来更好的效果。
  7. 随着模型复杂度的增加,模型之间效果的差异不在明显。
  8. 集成大法往往可以带来不错的提升。(比赛中,我只用4个模型的输出做了简单的平均)

如有新体会,后续再补充。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published