Skip to content

yzbdt/tianchi_meinian_rank12_1st_season

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 

Repository files navigation

天池美年AI大赛,第一赛季排名12,队伍:利物浦是冠军

github上分享的第一份代码,希望大家多给点星星,谢谢^ ^

我们组有两份代码,虽然都用lgbm模型,但特征工程都是独立实现,b榜最优成绩是各自5+3份结果的求平均的融合,线上分数0.02792,最后排名第12名。这里只是我自己的那份

这份代码提交过b榜单份结果,线上成绩是0.02816,线下分数在0.02758到0.02810之间波动,但后来发现特征选择的代码有点bug,做了些修改,复现时也发现以前做特征工程时莫名其妙地落下了0102这栏文字特征,加上这栏特征后好像线下分数下降了(说明NLP方面还能提高),跑了两份一份0.02809一份0.02824,因此后来先把0102删掉了。

data里的zip文件要手动解压,虽然有a、b榜的vid名单,但官方没有公布答案,只能获得线下分数,若要比较结果,建议从训练集里再划分出训练集、验证集和测试集。

==================================================== 先简要介绍一下清洗特征数据的主要思想,我是从简单入手,先处理能直接float的,然后在剩下的特征中,有些特征的字符没有什么意义,比如单位,可以去掉,提取出数字,剩下的则是字符特征,主要信息都在字符上,交给NLP处理。字符特征中,短字符特征,同时也意味着unique值小,可以直接onehot编码,长字符特征则使用d2v。

预处理的过程:

1、处理标签数据

检测标签是否为可转为浮点数,若是,检测是否过大过小(超过正常范围则为异常值),异常值丢弃。若无法直接转为浮点数,则去掉有关字符串,再检查是否在正常范围,可以先把数据扫描一遍获取这些字符串。(2.2.8这个数据我直接却去掉了) 正常范围可以参考生理指标,但这份数据只需要把超过正常范围几个数量级的以及0去掉就可以了,lgbm对异常值不敏感,影响不大,如果设置的范围过窄,线下分数与线上分数差距会增大,甚至导致线上分数下降。

2、获取纯数值特征

先处理能直接浮点化的特征,其中把缺失值过多的和unique只有一项的特征去掉。

3、清洗混入了少量字符的数值特征

筛选出纯数值特征后,剩下的就是混入字符或者全是字符的特征,这些特征中有些是部分项混入了字符,这些字符有可能是误输入,有可能是附加了单位,如心率72次/分钟,主要信息在数字项上,因此可以提取出数字,把字符直接清洗出去。 我认为如果这个特征中纯数字项大于一定比例(我选50%)则是我想要的特征,纯数字项5%到50%之间的特征,我保留了下来,不过后面就没再使用。纯数字项不到5%,我认为是字符特征,用NLP处理。 扫描这些特征可以知道要如何清洗出数值项,上面提到了,主要是误输入(比如体检时会输入X月X日)和单位,以及表示范围时带入了其他字符,因此我写正则时主要是去掉日期,去掉字符保留数字,然后表示范围的项清洗后会得到多个数值,我保存为list并统一取下界,也就是第一个数字。

4、清洗字符特征

这一步主要是把字符中一些与“正常”同义的词统一设为同一组字符

5、切分为长字符和短字符特征

jieba分词把长字符特征和短字符特征分开,短字符特征接下来将做onehot编码,这一步也可以通过统计特征unique值来判断。

6、编码并生成catogory特征

这一步除了对短字符特征进行编码外,我还手动清洗了特征'30007',因为听说这个特征很重要,但我又一下子想不出完美清洗的方法。

7、生成长字符串特征

长字符特征使用NLP的d2v,时间紧,参数并没有怎么调,而且前面也提到,加入部分文本特征还出现分数下降的情况,说明NLP这部分还可以好好调整。

训练:

我使用了五折交叉验证进行训练,最后得到5个lgbm模型,将这些模型的结果直接做个平均作为最终结果提交上去。

参数方面,考虑到特征筛选之后仍然比较多,因此加大L1正则项系数,同时每次训练使用更少的特征(只取了60%的特征),控制学习率使得每一项迭代在1000次左右(我发现太快收敛分数往往不是最好的,但迭代太多又太耗时)

我加入了特征选择策略,只是最简单的特征选择,每次训练出模型后得到特征重要性排序,剔除重要性最小的一部分,更新特征集后再去训练,直到线下分数开始下降为止,不过不能保证剔除部分特征后比全特征的回归性能好,因此最后还要做个比较,总而言之取线下分数最高的模型

我根据评分标准,选择标签取对数后再做回归,即与评分标准同步,此时分数最高。

总结:

检查特征重要性时,会发现某些男科或者妇科检查比较重要,其实是这些检查蕴涵了性别特征,不过我们组都来不及研究整合这些特征,如果整合了这些特征能降低特征的共线性,应该能提高分数。

我一开始在步骤1把标签范围卡得太窄,所以分数不是很高,在这个前提下,只使用到步骤2的特征,能得到0.035左右的分数,如果加上步骤3,则可以到0.0296左右的分数,如果加上短字符特征,能得到0.0294的分数,加上清洗后的30007特征能摸一摸0.0293,这时候我把标签的正常范围扩大了,分数又提高到了0.0291,最后加上了长字符特征,分数提高到0.0283左右。

这时候已经到了B榜,时间不多,我只好自己多训练几个模型融合,运行10次的结果融合之后大概能提升0.00005,后来我发现特征选择策略有缺陷,没有和全特征的模型做对比,做了改进之后提交了B榜第二次评分,也就是开头提到的0.02816,最后一次评分我拿自己的5个模型和队友的模型进行了融合,分数时0.02792

(ryzen1700超3.4果然不稳定,半夜重启结果最后也没训练出几份结果,现在我只敢OC 3.20hz了)

比赛刚开始的时候分数很低,0.06,后来我自己的训练代码给队友,用他们的特征能达到0.03+,于是我仔细检查了所有的数据,发现是在合并测试结果时没保留test表的VID顺序(a.merge(b),b.merge(a)这两个一个是按a表顺序合并一个按b表顺序合并,这是我开始没注意到的),而线上评分时只看test表的顺序而不管vid,因此有些在平均分0.05上下的选手可以检查一下是不是也遇到了这个问题。由于我是第一次参加数据挖掘的比赛,pandas使用不太熟练,有些坑必须要自己去踩踩orz

除此之外,我的python也学得一般般,现在才开始看fluent Python,有些地方写得丑或者不完善请大佬轻拍。

这份成绩是合作的结果,特别是NLP部分,我们都没什么经验,因为一开始没料到要做NLP也没做准备,因此只能临阵磨枪,每个人各自探索NLP的部分领域,我主要折腾tf-idf和word2vec,但一直没什么idea,直到队友发现d2v有效果。

可惜五月下旬实验室有事,无法继续参加复赛。

====================================================

硬件及环境: 操作系统 Windows10 |Python 3.6.1 |Anaconda 4.4.0 (64-bit)|

使用的package

jieba version = '0.39'

gensim version = '3.4.0'

numpy version ='1.14.2'

pandas version ='0.20.1'

sklearn version = '0.18.1'

lightgbm version = '2.1.0'

内存16G应该足够了,预处理大概要3小时和训练需要2小时左右(CPU:ryzen-1700 OC 3.40hz)

我在pycharm上把project建在主目录下,直接运行main.py即可,也可以在命令行下运行main.py

_

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages