Recording︱有价值的各类AI、机器学习比赛心得、经验抄录
今年kaggle华人优胜团队很多,所以经验、心得不少,都是干货慢慢收集。
一、【干货】Kaggle 数据挖掘比赛经验分享
github:https://github.com/ChenglongChen/Kaggle_HomeDepot
1、了解数据分布
◆ 分析特征变量的分布
◇ 特征变量为连续值:如果为长尾分布并且考虑使用线性模型,可以对变量进行幂变换或者对数变换。
◇ 特征变量为离散值:观察每个离散值的频率分布,对于频次较低的特征,可以考虑统一编码为“其他”类别。
◆ 分析目标变量的分布
◇ 目标变量为连续值:查看其值域范围是否较大,如果较大,可以考虑对其进行对数变换,并以变换后的值作为新的目标变量进行建模(在这种情况下,需要对预测结果进行逆变换)。一般情况下,可以对连续变量进行Box-Cox变换。通过变换可以使得模型更好的优化,通常也会带来效果上的提升。
◇ 目标变量为离散值:如果数据分布不平衡,考虑是否需要上采样/下采样;如果目标变量在某个ID上面分布不平衡,在划分本地训练集和验证集的时候,需要考虑分层采样(Stratified Sampling)。
◆ 分析变量之间两两的分布和相关度
◇ 可以用于发现高相关和共线性的特征。
2、数据清洗
◆ 特征缺失值的处理
◇ 特征值为连续值:按不同的分布类型对缺失值进行补全:偏正态分布,使用均值代替,可以保持数据的均值;偏长尾分布,使用中值代替,避免受 outlier 的影响;
◇ 特征值为离散值:使用众数代替。
◆ 文本数据的清洗
◇ 在比赛当中,如果数据包含文本,往往需要进行大量的数据清洗工作。如去除HTML 标签,分词,拼写纠正, 同义词替换,去除停词,抽词干,数字和单位格式统一等。
3、特征工程
- 特征变换
主要针对一些长尾分布的特征,需要进行幂变换或者对数变换,使得模型(LR或者DNN)能更好的优化。需要注意的是,Random Forest 和 GBDT 等模型对单调的函数变换不敏感。其原因在于树模型在求解分裂点的时候,只考虑排序分位点。
- 特征编码
对于离散的类别特征,往往需要进行必要的特征转换/编码才能将其作为特征输入到模型中。常用的编码方式有 LabelEncoder,OneHotEncoder(sklearn里面的接口)。譬如对于”性别”这个特征(取值为男性和女性),使用这两种方式可以分别编码为{0,1}和{[1,0], [0,1]}。
对于取值较多(如几十万)的类别特征(ID特征),直接进行OneHotEncoder编码会导致特征矩阵非常巨大,影响模型效果。可以使用如下的方式进行处理:
◆ 统计每个取值在样本中出现的频率,取 Top N 的取值进行 One-hot 编码,剩下的类别分到“其他“类目下,其中 N 需要根据模型效果进行调优;
◆ 统计每个 ID 特征的一些统计量(譬如历史平均点击率,历史平均浏览率)等代替该 ID 取值作为特征,具体可以参考 Avazu 点击率预估比赛第二名的获奖方案;
◆ 参考 word2vec 的方式,将每个类别特征的取值映射到一个连续的向量,对这个向量进行初始化,跟模型一起训练。训练结束后,可以同时得到每个ID的Embedding。具体的使用方式,可以参考 Rossmann 销量预估竞赛第三名的获奖方案,https://github.com/entron/entity-embedding-rossmann。
对于 Random Forest 和 GBDT 等模型,如果类别特征存在较多的取值,可以直接使用 LabelEncoder 后的结果作为特征。
4、模型选择和验证
- 对于稀疏型特征(如文本特征,One-hot的ID类特征),我们一般使用线性模型,譬如 Linear Regression 或者
Logistic Regression。Random Forest 和 GBDT
等树模型不太适用于稀疏的特征,但可以先对特征进行降维(如PCA,SVD/LSA等),再使用这些特征。稀疏特征直接输入 DNN 会导致网络
weight 较多,不利于优化,也可以考虑先降维,或者对 ID 类特征使用 Embedding 的方式 - ◆ 对于稠密型特征,推荐使用 XGBoost 进行建模,简单易用效果好;
- ◆ 数据中既有稀疏特征,又有稠密特征,可以考虑使用线性模型对稀疏特征进行建模,将其输出与稠密特征一起再输入 XGBoost/DNN
建模,具体可以参考2.5.2节 Stacking 部分
5、模型参数常规设置
DNN或者XGBoost中学习率这个参数,一般就选 0.01 左右就 OK 了(太大可能会导致优化算法错过最优化点,太小导致优化收敛过慢)
Random Forest,一般设定树的棵数范围为 100~200 就能有不错的效果,当然也有人固定数棵数为 500,然后只调整其他的超参数
.
二、阿里天池IJCAI17大赛第四名方案全解析(附代码)
github:https://github.com/Jessicamidi/Solution-to-IJCAI17-Sales-Volume-Prediction-on-Koubei-Platform
阿里天池IJCAI17:https://tianchi.aliyun.com/competition/introduction.htm?spm=5176.100067.5678.1.amifQx&raceId=231591
- 赛题目标:通过阿里支付宝口碑平台2000个商户从2015.07.01到2016.10.31的商家数据,用户在支付宝端的支付和浏览日志,预测商家在未来14天(2016.11.01-2016.11.14)的客户流量。
- 外部数据:天气数据(提供了世界各地在机场附近检测到的气象信息,包含气温,露点,湿度,气压,能见度,风速,瞬时风速,降水量,天气状况等信息。历史气象信息的采样间隔为30分钟。测试集首日,北京首都国际机场2016年11月1日气象条件)、节假日信息(节假日信息 HOLI.csv,将日期类型简单分为三个类别,其中工作日标签为0,周末标签为1,假期标签为2。)
1、数据清洗
数据清洗包含三部分,通过规则清除,通过模型预训练清除及仅保留销量统计信息。
规则清除:原始数据中,存在单用户某小时内大量购买的现象,如userID为9594359用户在2016年1月30日在shopID为878的商家累计购买了209次。针对此类现象,对于单个用户单小时内的购买数量x,采用以下公式处理消除异常消费
模型预训练清除:商家日销量,可能存在一些难以预计的大幅波动,如促销,商家停业等。对于这些规则难以清除的异常值,采用预训练的方式清除。
2、仅保留销量统计信息
由于只需要预测商家的日销量,无需识别单个用户的行为,按照大数定理,可以只针对分时段的浏览与购买总数进行预测。因而在数据清洗后,保留的数据仅按小时统计商户总销量,在这一步剔除了用户ID,使得数据量仅为原始的约1/10.
3、常规销量预测模型
3.1 特征与标签
3.2 训练方式
采用滑窗对于2000个商家日销量的时间序列生成481143条有效训练样本,清除间断前后及异常值后保留468535条样本。
采用2次训练的方法,第一次采用最大深度为3欠拟合模型进一步清洗脏数据。采用了xgboost与sklearn的GBDT模型训练,具体参数如下:
XGBoost-Round_1: 日销量仅作log处理,预训练后样本保留量为90%。
XGBoost-Round_2: 日销量仅作log处理后,采用过去三周的中位数作无量纲,预训练后样本保留量为75%。
4、 历史均值模型
输入:过去21天的历史销量,过去三周的销量相关度矩阵。
输出:未来2周的销量及其对应在模型融合中置信度。
方法:过去21天的按工作日平均,得到按工作日平均的均值销量。通过过去三周按周统计的销量中位数及平均值,做线性拟合得到销量增量。将历史均值销量叠加销量增量即得到未来2周预测销量。
由于方法本质上寻找历史上相似的(过去三周相关度较高)销量曲线作为未来预测,本质上为均值模型与KNN方法的结合。
置信度即为融合系数,仅当三周相关系数或后两周相关系数的最小值大于0.7时有效。均值模型的融合比例最大为0.75。
5、双11销量修正模型
模型概述:需要预测的时间段(11月1日到11月14日范围内)包含双11节日。从诸多商家的销量图上能明显看到在双11当天存在较大波动,可能的原因为网商促销对实体店的冲击,双11作为光棍节对于餐饮业的促进。然而仅有约1/3的商家存在2015年双11的销量记录,需要通过这部分商家去年双11信息,预测其余商家双11销量表现。
特征描述:仅包含商家特征,包含平均View/Pay比值,平均每天开店时间,关店时间,开店总时长;首次营业日期,非节假日销量中位数,节假日销量中位数,节假日/非节假日销量比值;商家类别,人均消费,评分,评论数,门店等级。
6、模型融合
多套gradient boosting的结果间的融合
xgboost1,xgboost2, GBDT三份结果按0.47, 0.34, 0.19 比例融合。
gradient boosting与均值模型融合
将均值模型结果与步骤1 gradient boosting 的结果融合,均值模型的融合系数为通过相关度得到的置信度。
双11系数进行销量调制
双11当天销量乘以双11销量修正模型得到的销量增量,11-12, 11-13由于为周六周日,有理由相信其销量与11-11(周五)的表现存在相似性, 因而乘以0.2及0.1倍的销量增量系数。
.
三、第一次参加Kaggle拿银总结——特征工程(FE)
截取特征工程部分,来源:http://scarletpan.github.io/summary-of-get-a-silver-medal-in-kaggle/
在对一些基础的特征进行生成之后,我开始了漫长地测试特征的长征路,测试的思路我后来发现并不是很好,因为是通过新增加一个或几个feature,如果cv分数上去了,就增加这个feature,如果cv分数没有上去,就舍弃这个feature,也就是相当于贪心验证。这样做的弊处在于,如果之前被舍弃的feature和之后被舍弃的feature联合在一起才会有正面影响,就相当于你错过了两个比较好的feature。因此特征的选择和联合显得非常关键。
数值型feature的简单加减乘除
这个乍一看仿佛没有道理可言,但是事实上却能挖掘出几个feature之间的内在联系,比如这场比赛中提供了bathrooms和bedrooms的数量,以及价格price,合租用户可能会更关心每个卧室的价格,即bathrooms / price,也会关心是不是每个房间都会有一个卫生间bathrooms / price,这些数值型feature之间通过算数的手段建立了联系,从而挖掘出了feature内部的一些价值,分数也就相应地上去了。
高势集类别(High Categorical)进行经验贝叶斯转换成数值feature
什么是High Categorical的特征呢?一个简单的例子就是邮编,有100个城市就会有好几百个邮编,有些房子坐落在同一个邮编下面。很显然随着邮编的数量增多,如果用简单的one-hot编码显然效果不太好,因此有人就用一些统计学思想(经验贝叶斯)将这些类别数据进行一个map,得到的结果是数值数据。在这场比赛中有人分享了一篇paper里面就提到了具体的算法。详细就不仔细讲了,用了这个encoding之后,的确效果提升了很多。那么这场比赛中哪些数据可以进行这样的encoding呢,只要满足下面几点:1. 会重复,2. 根据相同的值分组会分出超过一定数量(比如100)的组。也就是说building_id, manager_id, street_address, display_address都能进行这样的encoding,而取舍就由最后的实验来决定了。
时间特征
针对于时间数据来讲,提取年、月、日、星期等可能还是不够的,有另外一些points可以去思考,用户的兴趣跟发布时间的久远是否有关系?可以构造如下的feature来进行测试: python data[“latest”] = (data[“created”]- data[“created”].min()) python data[“passed”] = (data[“created”].max()- data[“created”])
可以看到latest指的是从有数据开始到该房创建为止一共过去了多少时间,而passed则是该房记录创建为止到最后有记录的时候一共过去了多少时间。
另外针对于时间特征还可以用可视化的方式来与其他特征建立联系,比如我们观察listing_id与时间变化到底有怎样的联系,能够绘制出如下的图来:
可能简单的相除就能获得很好的结果
地理位置特征
想到地理位置,就会想到聚类,一个简单的方式将每个房子划分到同一块区域中去;除了聚类以外,算出几个中心点坐标,计算曼哈顿距离或者欧式距离可能都会有神奇的效果。
文本特征
实话说自己是看中这次比赛中有文本数据才参加的,因此在文本挖掘中做了很大的努力,比如提取关键词、情感分析、word embedding聚类之类都尝试过,但效果都不是很好, 对于文本的特征的建议还是去找出一些除了停用词以外的高频词汇,寻找与这个房屋分类问题的具体联系。
图片特征
除了最后爆料出来的magic feature(后文会提到)以外,我只用了一个房子有几个照片这个信息。讨论区中都说对于图片特征用CNN提取、简单特征提取之类的效果都不是很好。
稀疏特征集
其实就相当于一系列标签,不同标签的个数也是挺多的,本次比赛我只是简单地采用了counterEncoding的方式进行one-hot编码。值得一提的是,有些标签是可以合并的,比如cat allowed 和 dog allowed可以合并成为 pet allowed,我在这场比赛中手工地合并了一些feature数据,最终结果略微有所提升。
特征重要程度(feature importance)
在树结构的分类器比如randomforest、xgboost中最后能够对每个特征在分类上面的重要程度进行一个评估。这时候如果已经选定了一些feature进行训练了之后,查看feature importance的反馈是非常重要的,比如本场比赛制胜的关键是运用manager_id这个feature,而它的feature importance反馈结果也是非常高。通过对重要特征的重新再提取特征,能够发现很多有意思的新特征,这才是用FE打好一场比赛的关键所在。
模型融合
如果你没有idea了的话,就模型融合吧!模型融合是能够快速提高比赛成绩的捷径,现在的比赛几乎没有人不用到这个技巧,通常获胜者会对很多很多模型进行融合,并且会选择不同的模型融合的方式。这里有一篇非常好的模型融合解析 博文 ,相信每个看过它的人都会对模型融合有一个清楚的了解
本次比赛中我使用了两种模型融合方式,一种是Averaging,一种是Stacking。
先来说说Stacking,因为这场比赛一名贡献比较大的选手分享了一个叫StackNet的库,作为新手我就直接用了。首先我用我的xgboost cv集交叉预测出结果作为feature的一部分放到train data中,再对test data进行预测的结果作为feature的一部分放到test data中,再在第二层上选择了Logistic Classifer,GradientBoostingClassifer,AdaBoostClassifer,NNSoftemaxClassfier,RandomForestClassifer等进行交叉预测,第三层选取了一个randomForest作为最后的结果训练和预测。Stacking主要增多了模型的diversity,使我的成绩上升了至少0.003的量级,
然后是Averaging,之前提到过Stacking需要交叉预测,我就选取了10组随机种子分别对训练集进行10-kfold交叉预测取平均,以及每个flod训练预测的时候我都对我的xgboost选取5个随机种子取平均。也就是说,在第一层Stacking的CV集交叉预测时我总共训练了500个模型进行平均。分数的提升大约在0.002左右。
直到比赛结束看了排名靠前的选手的模型融合后,才发现自己对于模型融合只是做了一点微小的工作,提升空间还非常大。详情可以看FE部分分享的solution链接。
.
四、推荐|分分钟带你杀入Kaggle Top 1%
比较新奇的几个心得记录如下:
.
1、错误分析
人无完人,每个模型不可能都是完美的,它总会犯一些错误。为了解某个模型在犯什么错误,我们可以观察被模型误判的样本,总结它们的共同特征,我们就可以再训练一个效果更好的模型。这种做法有点像后面Ensemble时提到的Boosting,但是我们是人为地观察错误样本,而Boosting是交给了机器。通过错误分析->发现新特征->训练新模型->错误分析,可以不断地迭代出更好的效果,并且这种方式还可以培养我们对数据的嗅觉。
举个例子,这次比赛中,我们在错误分析时发现,某些样本的两个问句表面上很相似,但是句子最后提到的地点不一样,所以其实它们是语义不相似的,但我们的模型却把它误判为相似的。比如这个样本:
Question1: Which is the best digital marketing institution in banglore?
Question2: Which is the best digital marketing institute in Pune?
为了让模型可以处理这种样本,我们将两个问句的最长公共子串(Longest Common Sequence)去掉,用剩余部分训练一个新的深度学习模型,相当于告诉模型看到这种情况的时候就不要判断为相似的了。因此,在加入这个特征后,我们的效果得到了一些提升。
.
2、特征工程
总结一下,我们抽取的手工特征可以分为以下4种:
Text Mining Feature,比如句子长度;两个句子的文本相似度,如N-gram的编辑距离,Jaccard距离等;两个句子共同的名词,动词,疑问词等。
Embedding Feature,预训练好的词向量相加求出句子向量,然后求两个句子向量的距离,比如余弦相似度、欧式距离等等。
Vector Space Feature,用TF-IDF矩阵来表示句子,求相似度。
Magic Feature,是Forum上一些选手通过思考数据集构造过程而发现的Feature,这种Feature往往与Label有强相关性,可以大大提高预测效果。
.
3、深度学习的不足与传统方法的优势
通过对深度学习产生的结果进行错误分析,并且参考论坛上别人的想法,我们发现深度学习没办法学到的特征大概可以分为两类:
对于一些数据的Pattern,在Train Data中出现的频数不足以让深度学习学到对应的特征,所以我们需要通过手工提取这些特征。
由于Deep Learning对样本做了独立同分布假设(iid),一般只能学习到每个样本的特征,而学习到数据的全局特征,比如TF-IDF这一类需要统计全局词频才能获取的特征,因此也需要手工提取这些特征。
传统的机器学习模型和深度学习模型之间也存在表达形式上的不同。虽然传统模型的表现未必比深度学习好,但它们学到的Pattern可能不同,通过Ensemble来取长补短,也能带来性能上的提升。因此,同时使用传统模型也是很有必要的。
Recording︱有价值的各类AI、机器学习比赛心得、经验抄录的更多相关文章
- Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量
Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量 from:https://www.leiphone.com/news/201712/zbX22Ye5wD6CiwCJ.html 导语 ...
- Sublime Text的心得经验。 全面
Sublime Text的心得经验.jikeytang/sublime-text · GitHub
- 认识:人工智能AI 机器学习 ML 深度学习DL
人工智能 人工智能(Artificial Intelligence),英文缩写为AI.它是研究.开发用于模拟.延伸和扩展人的智能的理论.方法.技术及应用系统的一门新的技术科学. 人工智能是对人的意识. ...
- 关于参加AWD攻防比赛心得体会
今天只是简单写下心得和体会 平时工作很忙 留给学习的时间更加珍少宝贵. 重点说下第二天的攻防比赛吧 . 三波web题 .涉及jsp,php,py. 前期我们打的很猛.第一波jsp的题看到有首页预留后 ...
- 曼孚科技:AI机器学习领域常用的15个术语
机器学习是人工智能(AI)的核心,是使计算机具有智能的根本途径. 本文整理了一下机器学习领域常用的15个术语,希望可以帮助大家更好的理解这门涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多个领 ...
- Google机器学习教程心得(二)决策树与可视化
Visualizing a Decision Tree Google Machine Learning Recipes 2 官方中文博客 http://chinagdg.org/2016/03/mac ...
- Google机器学习教程心得(一)
Hello world Google Machine Learning Recipes 1 官方中文博客 http://chinagdg.org/2016/03/machine-learning-re ...
- AI - 机器学习常见算法简介(Common Algorithms)
机器学习常见算法简介 - 原文链接:http://usblogs.pwc.com/emerging-technology/machine-learning-methods-infographic/ 应 ...
- AI 机器学习基础
深度学习是机器学习的一个特定分支. 1.学习算法 对于某类任务T和性能度量P, 2.线性回归 3.正规方程(normal equation) 4.监督学习(supervised learning) 5 ...
随机推荐
- 20145216史婧瑶《Java程序设计》第9周学习总结
20145216 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 整合数据库 16.1 JDBC入门 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找. ...
- Redis-与python交互
安装包 到中文官网查找客户端代码 联网安装 sudo pip install redis 使用源码安装 unzip redis-py-master.zip cd redis-py-master sud ...
- [BZOJ4137]火星商店问题
Description 火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品, ...
- 从零开始玩转JMX(一)——简介和Standard MBean
JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展.这种机制可以方便的管理.监控正在运行中的Java程序.常用于管理线程,内存,日志Level,服 ...
- 管理账号密码的工具-KeePass使用方法
附件链接:https://files.cnblogs.com/files/stxs/KeePass.zip 打开压缩包“KeePass.zip",将文件"KeePass.exe&q ...
- Spring 集成rabbiatmq
pom 文件 <dependencies> <dependency> <groupId>com.rabbitmq</groupId> <artif ...
- 修改windows命令行字体
YaHei Consolas Hybrid
- centos7 systemctl一些用法
systemctl 是管制服务的主要工具, 它整合了chkconfig 与 service功能于一体. systemctl is-enabled servicename.service #查询服务是否 ...
- GDB操作基本命令
GDB操作基本命令 1 打开文件及退出操作 shell下输入 gdb filename : 打开单个文件 gdb filename -q: 打开单个文件,屏蔽掉GDB自带的说明信息 gdb下输入qui ...
- spring mvc: xml生成
spring mvc: xml生成 准备: javax.xml.bind.annotation.XmlElement; javax.xml.bind.annotation.XmlRootElement ...