2017知乎看山杯总结(多标签文本分类)

http://blog.csdn.net/jerr__y/article/details/77751885

关于比赛详情,请戳:2017 知乎看山杯机器学习挑战赛

代码:https://github.com/yongyehuang/zhihu-text-classification 
基于:python 2.7, TensorFlow 1.2.1

任务描述:参赛者需要根据知乎给出的问题及话题标签的绑定关系的训练数据,训练出对未标注数据自动标注的模型。

标注数据中包含 300 万个问题,每个问题有 1 个或多个标签,共计1999 个标签。每个标签对应知乎上的一个「话题」,话题之间存在父子关系,并通过父子关系组织成一张有向无环图(DAG)。

由于涉及到用户隐私及数据安全等问题,本次比赛不提供问题、话题描述的原始文本,而是使用字符编号及切词后的词语编号来表示文本信息。同时,鉴于词向量技术在自然语言处理领域的广泛应用,比赛还提供字符级别的 embedding 向量和词语级别的 embedding 向量,这些 embedding 向量利用知乎上的海量文本语料,使用 google word2vec 训练得到。

简单来说,这是一个多标签文本分类问题,基本上都是使用深度学习方法。

结果:在public board 上排名第五,private board 上排名第六。

图1 public board 图2 private board

我是从7月1号开始报名比赛,一直到8月16日早上结束,一共一个半月时间,除了开始三周有些其他事情,后面差不多一个月时间基本上都在做比赛。之前也做过一个文本的比赛(命名实体识别+分类),但是之前积累不够,有没有找到合适的队友,所以那个比赛最后成绩很差,后期基本上就放弃了。这次还是一个人参赛(一个人打比赛好累…)这一个半月确实很累,经常写代码写到半夜,然后一大早又起来看模型跑的结果,发现出错了赶紧改过来;跟同学抢机器;各种想法没提升;有一次把验证集写成训练集来用结果过拟合白白高兴了…和我一个实验室的还有两组同学参加了,他们分别拿了第一和第二…唉唉,自己还是太菜了。不过在这次比赛中,确实学习了好多,这里写下比赛中的一些经验,希望对大家特别是对于竞赛入门者能有所帮助。下面的相关经验主要是和深度学习相关。

硬件准备

在这次比赛中,训练集有300万个问题;测试集有21.7万个问题。赛方提供了预训练好的词向量矩阵,一共有40+万个词。所以数据量还是非常大的,如果没有服务器,基本上没法做。我们组一共就一台服务器,一块显卡titan X,64G内存,CPU12进程。但是,我们有十几个同学呀,虽然平时主要就三四个人用,但是和其他大佬们多卡多机相比,这配置确实寒酸。跑一个模型几个小时到二三十个小时,所以,没有机器,根本别想取得好成绩。

此外,一定要准备充足的硬盘空间,最好能有500G, 1T或者更多。因为在这次比赛中,我就因为硬盘满了,只能把数据放在两个分区进行操作,可能是前期没有注意管理,导致后来文件组织非常混乱。

文件管理

所有的比赛都应该一样, 就是“不择手段”地达到更好的成绩,而要取得较好的成绩,不可避免地会用到集成学习,所以你不可能靠一两个模型就能够取得很好的结果。在这次比赛中最后获奖的所有队伍都用了模型融合,模型数量少的有十几个,多个两百多个,我最后提交的结果用了37个模型。所以从一开始,你就应该管理好模型和文件的命名,这样才不至于后期命名混乱,因为缺乏经验,所以我也在这上面吃了不少亏。

模型保存

因为词向量非常大,所以每个模型保存下来都非常大(1G+),这样就非常占空间。所以应该怎么保存模型也是有讲究的,我的经验大概如下:

  • 设置一个最低 f1值(last_f1, 这次比赛评价函数是 f1,如果是准确率的话应该设置一个最低的准确率);每迭代 valid_step 步,就预测整个验证集,计算f1值,如果高于last_f1, 则保存模型。
  • 每个网络保存最好的模型即可,也就是说设置 max_keep=1

具体代码可以参照这份代码中的 train_epoch() 函数

为什么只保存最好的一个就好了?我尝试过保存最好的三个模型,假设为m1, m2, m3 然后把这三个模型以平均加权的方式融合得到 M,这样M的结果要比最好模型 m1 的结果好(在这次比赛中,能高2.5个千分点左右,这已经很好了),但是,但是,但是,在后面和其他结构的模型再次融合,M的效果不如直接使用 m1。我觉得可能是与 M 相比,对于每个样本的预测概率,m1 的方差更大些。比如对于样本a和b,m1预测分别属于类别1的概率是0.9 和 0.1; M预测分别属于类别1的概率是0.7和0.3。这种情况下和其他模型融合,m1的作用会更大一些,因为它对正样本的确定性很高,决定性更大。在其他数据或者比赛中,我觉得应该也是一样的。所以,只需要保存最好的一个模型,这样能节省不少硬盘空间。

使用 tensorboard

tensorboard 很好用,通过 tensorboard 查看损失变化能够很好地帮助我们进行调参,当然同时也可以看看模型结构有没有写错了… 但是有一点需要注意,如果你的模型很大,那么tensorboard中保存的数据也会非常大,所以还是很占空间的。

 
图3 网络结构

 
图4 损失变化

模型构造与调参

在这次比赛中,主要使用的基本模型有 TextCNN, BiGRU, HAN(Hierarchical Attention Networks ), FastText, RNN+CNN(区别与RCNN)。然后各种结构拼接,修改。比赛的目的很明确,就是取得更好的分数。所以我们的目的并不只是把原论文的结构套过来看看结果,而是要在给定的数据集上不断改进,不断调整参数。同样的一个模型,可能就是某个地方有一点小小的差别,或者学习率没调好结果就会差很多。这些都是需要自己不断积累,在实验过程中不断总结出来的。但是在大体上,有些问题还是需要注意的。

  • 关于学习率和学习率衰减。学习率非常重要,一般都会使用自适应的优化器,比如 adam, 但是还是需要严谨地选择初始学习率。至于学习率衰减,TensorFlow 中提供了tf.train.exponential_decay()函数,这函数有个参数staircase,我的经验是一定要设为staircase=True,也就是迭代好多步以后再跳一次,而不是没迭代一次都调整学习率。你会在tensorboard中看到,学习率衰减的那一瞬间,loss都会迅速地下降一次。在TextCNN中特别明显。我看到有些人用adam优化器的时候并没有使用 decay,而是只提供了一个初始学习率,但是我在实验中发现,使用Exponential Decay效果明显要比没用好。而且decay_rate 和 decay_step 的选择也很关键。但是有些队伍根本就没做这个效果却非常好,所以现在我还是比较疑惑。之后弄清楚了再来补充。相关讨论可参考下面:

Tensorflow: Adam Optimizer with Exponential Decay 这里有讨论但是不是很明确。 
Mixing learning rate decay and Adam, is it possible? 
Should we do learningrate decay for adam optimizer 里边下面这个说法我比较认同。

It depends. ADAM updates any parameter with an individual learning rate. This means that every parameter in the network have a specific learning rate associated.

But the single learning rate for parameter is computed using lambda (the initial learning rate) as upper limit. This means that every single learning rate can vary from 0 (no update) to lambda (maximum update).

The learning rates adapt themselves during train steps, it’s true, but if you want to be sure that every update step do not exceed lambda you can than lower lambda using exponential decay or whatever. It can help to reduce loss during the latest step of training, when the computed loss with the previously associated lambda parameter has stopped to decrease.

adam对于每个参数都会自动调整学习率,但是我们传进去的学习率是进行适应学习率计算的基础。所以加上decay还是会有作用的,不过具体问题具体尝试才能知道有没有用。

  • 关于模型大小。这个其实很关键,首先要看数据量,像知乎的这次比赛数据量还是非常大的,所以模型也是应该比较大的。就这个数据集,相同结构,大一点的模型可能比小一点的模型更加节省时间。因为模型参数多了,迭代一次学习到的信息要比模型多,所以收敛的速度可能比小模型更加快。所以,在比赛初期,你可以先用小模型把一个结构跑通,然后开始可以尝试改进结构,加深模型,加宽模型。在这次比赛中,第三名的队伍他们的模型比我的基本大了5,6倍,他们最好的CNN模型训了一周,但是对于我来说这是绝对不允许的,因为就一台机器,如果一个模型训上一周意味着我都不用做了,万一效果还不好呢。所以,硬件非常非常关键。
  • 关于 batch_size。一般来说,几十到几百的batch_size都是可以接受的,那么选择大batch_size 还是小的batch_size呢?我认为,在这么大的一个数据集下,尽量把GPU撑满是个不错的选择,但是也不能太大,最好别超过1000。batch_size 大些,收敛速度相对来说应该会快些。batch_size越大,那么梯度的方向相对会更贴合“全局梯度”,更加“准确”。这样的话,我觉得学习率也可以稍微调大一点。但是,因为有很多很多的局部最优点,我们不能把 batch_size 设得太大,这样每个batch 的梯度才会带有一些“噪声”来帮助我们跳出这些局部最优点。具体的大小当然还是要根据数据集,通过实验来选择,还有你的显存大小来选择。
  • 因为赛方提供了预训练好的词向量和字向量,而且都是在更大的数据集上训练的,所以肯定会比自己训练的要好。但是,embedding 可以在迭代一定轮次(epoch)以后再进行fine-tune,这样有两个好处:一是embedding非常大,如果不对embedding计算梯度的话能减少不少计算,节省时间;二是一开始就是用大学习率优化embedding,容易把原本预训练学习到的信息丢失。在TensorFlow中要想先固定embedding,在一定轮次以后再优化的话,可以通过定义两个优化器来实现。可以参考这个代码中main()部分。对于知乎的这个数据集,这样做对于RNN效果比较好,但是对于TextCNN似乎帮助不大。
  • 关于融合。一定要从一开始就为最后模型融合做好准备。模型融合的方法有很多,最常见的比如bagging, stacking 等。在这次比赛中,由于数据量太大,而且计算时间非常长,所以对于我来说,基本上没有办法做stacking,所以最后使用了线性加权。好而不同,这是模型融合最最关键的地方。所以BIGRU与TextCNN融合要比BIGRU与HAN效果好很多,因为TextCNN与BIGRU结构相差非常大,而HAN里边就是用了 BIGRU。所以在训练不同模型时,一定尽量增加模型之间的差异性。在这个比赛中,使用字向量训练的模型要比词向量训练的模型差很多(1个百分点以上),但是在模型融合中,一个好的字向量模型带来的提升非常大。

在这次比赛中,主要使用的模型结构如下:

 

其他

比赛结束后,学习其他组的参赛方案,确实有很多值得学习的地方。非常感谢知乎组织的这次比赛,最后他们还公布了所有获奖队伍的参赛方案,详细见:「2017 知乎 · 看山杯机器学习挑战赛」结束,谁获奖了?知乎还会做什么?

原文地址:https://www.cnblogs.com/DjangoBlog/p/8280387.html

时间: 2024-10-28 20:27:10

2017知乎看山杯总结(多标签文本分类)的相关文章

2017年必看的免费linux视频及python视频资源合集

2017年必看的linux直播课程与linux在线课程汇总   腾讯课堂: Linux课程: 系列直播课程: [免费]零基础Linux入门系统课程1(持续更新) https://ke.qq.com/course/202854 [免费]零基础linux入门课程2 https://ke.qq.com/course/213426 Linux 高薪进阶课程 https://ke.qq.com/course/210074     Python课程: 系列直播课程: [免费]Python全栈开发小白必备入门

2017暑假就看了这几本书

写在前面 高效能人士的七个习惯:精华版.第2版 / (美) 史蒂芬·柯维著 心智时间:意识中的时间因素:the temporal factor in consciousness / (美) 本杰明·里贝特著 谈判力 / (美)罗杰·费希尔,(美)威廉·尤里,(美)布鲁斯·巴顿著影响力心理学 / (美)菲利普·津巴多,(美)迈克尔·利佩著[未完成]来源:长清图书馆 阅读用时:2017.7.7-2017.8.28共52天,书的容量并不是很大,看上去看的挺多,其实并没有,最后一本是很早之前就借了的,觉

2017 ACM-ICPC ECFINAL过山车体验

这次采用domjudge判题,算是比较好玩的啦.外榜地址:http://board.acmicpc.cn/ 然后我们很可惜地止步于192名QAQ,没看出C是个傻逼题,没读懂B..我得背锅,亏我还打了那么久CF.. 周五我们从宣城过来票买错时间了QAQ,买成第二天的了(因为是晚上11点多的票当时脑子抽风感觉是第二天于是emmm).买票的是我,第一次买错票贼尴尬....而且是晚上11点过来,12306不能买了.还好火车可以在车上补卧铺票,有惊无险.安安稳稳地从宣城去上海了~. 周六早上8点多我们到的

从ThoughtWorks 2017技术雷达看微软技术

ThoughtWorks在每年都会出品两期技术雷达,这是一份关于技术趋势的报告,它比起一些我们能在市面上见到的其他各种技术行情和预测报告,更加具体,更具可操作性,因为它不仅涉及到新技术大趋势,比如云平台和大数据,更有细致到类库和工具的推介和评论,从而更容易落地. Thoughtworks技术雷达 Thoughtworks技术雷达是以独特的形式记录ThoughtWorks技术顾问委员会的讨论结果,为从首席信息官到开发人员在内的各路利益相关方提供价值.这些内容只是简要的总结,但建议您探究这些技术以了

2017.9.23 NOIP2017 金秋杯系列模拟赛 day1 T1

回形遍历( calc .cpp/c/pas) 时间限制:1s内存 限制: 256MB [问题 描 述]给出一个 n*m 的棋盘,按如下方式遍历,请问(x,y)往后 z 步走到的是哪个格子. [输入]输入文件名为 calc.in.一行,包含五个整数:n,m,x,y,z[输出]输出文件名为 calc.out.输出一行,包含两个整数,表示所在格子的横纵坐标[输入输出样例] calc .in calc .out 4 5 3 0 5 2 4 [ 样例解释 ] [数据说明]对于 70%的数据,1<=n,m,

【转-知乎】有监督 无监督 标签的解释,对我自己而言,比较容易懂(收藏)

作者:赵杨链接:https://www.zhihu.com/question/23194489/answer/75555668来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 机器(计算机)学习分为有监督和无监督两个类,基本上可以从他们会不会得到一个特定的标签(label)输出来区分.这里标签指的是用来描述某一个物体属性的话语.比如人类有两种,我们要区分这两种人,就根据生理特征,分别对两种人打上标签,一种是[男人],另一种是[女人].有监督学习(Supervised

fasttext的基本使用 java 、python为例子

fasttext的基本使用 java .python为例子 今天早上在地铁上看到知乎上看到有人使用fasttext进行文本分类,到公司试了下情况在GitHub上找了下,最开始是c++版本的实现,不过有Java.Python版本的实现了,正好拿下来试试手, python情况: python版本参考,作者提供了详细的实现,并且提供了中文分词之后的数据,正好拿下来用用,感谢作者,代码提供的数据作者都提供了,点后链接在上面有百度盘,可下载,java接口用到的数据也一样: [html] view plai

盘点当下大热的 7 大 Github 机器学习『创新』项目

最顶尖的Github机器学习项目 1. PyTorch-Transformers(NLP) 传送门:https://github.com/huggingface/pytorch-transformers 自然语言处理(NLP)的力量令人叹服.NLP改变了文本的处理方式,几乎到了无法用语言描述的程度. 在最先进的一系列NLP库中,PyTorch-Transformers出现最晚,却已打破各种NLP任务中已有的一切基准.它最吸引人的地方在于涵盖了PyTorch实现.预训练模型权重及其他重要元素,可以

delphi Caption 垂直显示标签文本

//垂直显示标签文本 Label1.Caption:='垂'+#13+'直'+#13+'显'+#13+'示'; //使用相同的方法,我们也可以制作垂直显示的提示(Hint):button1.Hint:='垂'+#13+'直'+#13+'显'+#13+'示'; 来自为知笔记(Wiz) delphi Caption 垂直显示标签文本,布布扣,bubuko.com