数据挖掘比赛通用框架

作者|穆文

报名啦CDA数据分析师认证培训Level 1
国内权威的数据分析师系统
培养学员超过上千人理论结合实际
更有多重福利提供


点击文末“阅读原文”查看详细

◆ ◆ ◆

前言

Kaggle上有篇名为「Approaching (Almost) Any Machine Learning Problem」的博客(点击底部阅读原文),作者是Kaggle比赛的专业户,博客是他参加Kaggle比赛的经验总结。在进入正题前随便扯几句:

本文并非原博客的翻译版,而是90%的原创,是在原博客基础上融合自己的经验,重写了大部分章节和代码。所以当你看到本文跟原博客差别很大时,请不要怀疑人生 ;-P 原博客题目直译过来是『解决(几乎)任一机器学习问题的方法』,但原博客内容更偏数据挖掘之『术』而非机器学习之『道』,因为讲解了很多实际操作的trick和代码,所以我给本文取名为『数据挖掘比赛通用框架』。为简化描述,后续用ML指代机器学习DM指代数据挖掘 本文可以看做是一篇科普性质的文章,内容简单基础,关键在于结合实际实践这些想法,所谓 practice makes perfect. 本人连续多天利用数个晚上写成此文,请尊重原创,转载请注明。也希望本文能给各位带来收获,如有疏漏,欢迎后台留言积极指正,先行谢过

◆ ◆ ◆

背景

DM流程通常分两个阶段

Step1. 数据清洗,数据格式调整 Step2. 特征构建,模型选择,效果评估

Step1.是整个流程中最耗时的,这点想必大家早有耳闻,DM界有句名言 garbage in ,garbage out ,可见清洗数据非常重要。从我的经验看,这部分工作跟实际处理的业务问题关系很大,比较dirty,也没有统一流程,所以本文重点放在Step2.

◆ ◆ ◆

前期准备

1、数据变换

先把原始数据通过一定变换,变成通用的多列数据类型,作为ML模型的输入,也就是上面的Step1。用X代表样本及其特征集合,y代表样本标签集合,整个流程如下:

2、问题分类

根据标签y的不同,可以把DM问题分为以下几类:

  • 二分类问题(这种问题在工业界最为常见,比如广告点击率预估、推荐系统购买行为预测),此时y只有一维,取值只有两个(比如0-1),每个样本有唯一的标签。比如预测广告是否会被用户点击;用户是否会购买某种商品
  • 多分类问题(比如微博用户情感分析、用户对理财产品偏好性分析),通常此时y有多维,每维代表一个类标签,取值只有两个(比如0-1),每个样本有唯一的标签;当然,y也可以只有一维,取值有多个,每个值代表一个类标签。比如通过微博分析出用户情感属于喜怒哀乐等哪类;将理财产品的用户群体分为偏好型/温和型/厌恶型
  • 多标签问题(比如音乐的标签划分),y有多维,跟多分类的区别在于,样本可以同时属于多个标签。作为一枚钢琴爱好者,这里以钢琴作品举例,假设标签集合为{独奏,协奏,浪漫主义,印象主义},最爱之一的德彪西「月光」无疑属于{独奏,印象主义},朗总成名作柴一则可归为{协奏,浪漫主义},云迪家喻户晓的肖邦夜曲是{独奏,浪漫主义},而中国特色的「保卫黄河」可归为{协奏}
  • 单回归问题(比如股价预测),y只有一维,取值为连续值。比如预测阿里明天的股价
  • 多回归问题(比如天气预测),y有多维,取值连续。比如预测明天的气温、空气湿度、降雨量

3、评价指标

预测结果的好坏需要用一些指标来衡量,通常不同类型的DM问题有不同的评价指标。对于二分类问题,很多时候类别本身不均衡(比如正样本很多负样本极少),所以我们通常用AUC值——即ROC曲线下的面积——来评价二分类结果;在多分类或者多标签问题中,我们通常选取评价指标为交叉熵(cross-entropy)或者log损失(log loss);对于回归问题,则可以选用MSE(mean square error)

4、 工具

我跟原博客作者一样,提倡使用python解决DM问题,因为python的第三方库非常齐全,以下是常见的、用于DM问题的python库:

  • pandas: 仿照了R语言的数据结构、数据操作,一般用来做数据预处理,特征工程,其DataFrame数据格式用起来相当便利
  • scikit-learn: 家喻户晓的ML库,各种聚类、分类、回归模型等,也可以用来做预处理
  • xgboost: 陈天奇大神的杰作,改进了传统的GBDT模型,在底层用一些trick加速模型训练,非常值得一试,可以取代其他ML库里的GBDT系列模型 (很早就听说过这个碉堡的库,但一直没有上手实践,实在汗颜…后面我会结合GBDT做特征工程,实践下效果,发布到公众号)
  • keras: 神经网络相关的库,可以选择基于tensorflow或theano,赶脚很强大,我也是刚接触
  • matplotlib: 作图必备,语言风格跟MATLAB很像,很好上手
  • tpdm: 我没听过,原作者提到的,感兴趣的童鞋可以了解下

5、开发环境

这里我补充说一下python开发环境和上面几个库的安装方法。首先我跟原作者一样,因为追求自(装)由(逼),所以不用python IDE(比如Anaconda, Pycharm),当然,装IDE可能省很多事情,个人建议安装Pycharm。然后我自己的python开发环境(纯属个人习惯,仅供参考):

  • windows: notepad++及其插件nppexec/explorer,结合我昨天发布的『一个神奇的脚本,一键运行各类程序』,里面的nppexec脚本可一键执行Python。以及linux风格的shell: git bash (git bash是基于msys的,跟cygwin略有不同)
  • mac: sublime及其插件Package Control/anaconda,以及iTerm2,或者自带的terminal。(sublime中import某些python库,比如matplotlib/sklearn/tensorflow会出点bug,需要修改下环境变量啥的,遇到相关问题可以微信我,尽量帮你解决)
  • linux: vim(因为我一般在命令行模式下开发)。如果是界面linux,应该可以有其他选择 另外,jupyter notebook(前身是ipython notebook)是个好东西,可以逐步执行python代码片段,不依赖于平台,可在浏览器中打开,非常适合学习过程中练手。

再说库的安装,首先强烈建议安装64位python2.7,然后针对不同操作系统:

  • windows[不推荐]: 略蛋疼,64位的库大多没有官方版本,具体安装方式见我之前写过的一篇文章『在Windows下安装64位Python及数据挖掘相关库』(后续我会完善该文,但只发送给指定分组,具体见文末Bonus)。大多数库的安装都类似,但xgboost稍微复杂些,不能直接pip install,而是要装VS来编译其中相关文件,再安装,遇到问题可以微信我。另外tensroflow目前没有windows版本
  • mac[推荐]: 最新的python2.7一般都自带pip,所以装好python后,直接在terminal中 pip install 相关库就可以了,注意库的依赖关系,一般先安装numpy,scipy,matplotlib,再装其他库
  • linux[推荐]: 基本跟mac类似

◆ ◆ ◆

DM问题框架

终于到了最核心的部分,原作者总结了一个他参加各类DM比赛常用的ML流程图,真是一图胜千言

这里我擅自补充一下,这张图看着眼花缭乱,其实就两点,这两点也是DM比赛中最核心的

两点

特征工程(包括各种离散化、组合、选择) 模型选择、模型融合(即ensemble)

能把这两点做好,实属不易,但其实在工业界,特征工程和模型融合是否需要做到极致,是要看具体问题的。有些业务的数据维度本身就很稀少,并不足以支撑庞大的特征体系;有些业务需要很强的可解释性(比如金融领域),于是很多模型不能直接用;有些业务则要系统的实时性和稳定性,过于复杂的ensemble虽然能提升一点指标,但也许得不偿失。

上图当中的粉色部分是最常用的一些步骤,简单梳理一下:先确定DM问题的类型,然后对数据集划分,接着对常见的数值变量和类别变量做相应处理,可以进行特征选择,最后选择合适的模型做预测,评估模型并输出结果。下面将详细展开。

1. 问题定义

首先搞清楚要解决的问题属于哪一类,结合上节所讲,我们一般通过观察y标签类来定义DM问题的类型。

2. 数据集划分

在明确了问题的分类后,我们将对数据集划分成训练集(Training Data)和验证集(Validation Data)(补充:很多时候还要划分出测试集(Test Data),先用训练集验证集的交叉验证来寻找模型的最优超参数,模型调优完毕后,最终用测试集来评估模型最终效果,具体参考我之前在公众号发布的『新手数据挖掘中的几个常见误区』第二节)。划分方式如下:

这里我用自己本地的一个小数据集(名为toy_data.txt)做展示,获取方式见文末Bonus,加载以上小数据集的代码如下:

import pandas as pd
df = pd.read_csv("toy_data.txt",sep = "\t")
df.head()

运行结果:

最后一个字段Label就是我们要预测的y,在我的数据集里取值0或1,所以是一个二分类问题。

对于分类问题,要根据标签来划分数据集,比如每种标签采样多少,这样才能保证训练集跟验证集的样本标签分布接近,另外采样方式也不限于随机采样,可以根据实际业务问题选择合适的采样方式。这里我们可以借助scikit-learn来实现分层的K折交叉验证,代码如下

X = df.ix[:,0:-1]
y = df.ix[:,-1]
from sklearn.cross_validation import StratifiedKFold
kf = StratifiedKFold(y,3) # 三折交叉验证

用以下代码验证一下训练集和验证集中的正样本的占比:

idx_train, idx_valid = next(iter(kf))
print float(sum(y[idx_train]))/len(idx_train)
print float(sum(y[idx_valid]))/len(idx_valid)

结果为0.69713 0.69565,两者非常接近。 注意,不太推荐使用iter(kf),这里只是为了展示标签分布,具体我会在本文第五节『实战』中介绍如何高效地使用交叉验证。

如果是回归问题,则不存在分类问题中类别标签分布不均的情况,所以我们只需采用普通的K折交叉验证即可:

from sklearn.cross_validation import KFold
kf = KFold()

3. 特征工程

毫不夸张地说,特征工程是DM重要的一环,也是决定DM比赛的关键因素。纵观DM比赛,几年间已由追求模型是否fancy转向无尽的特征工程,主要得益于越来越标准化的ML模型,以及更好的计算能力。

特征工程可以做的很复杂很庞大,但受限于本人目前的水平,这里只结合原博客内容讲解一些最基本(也是最经典)的处理方法。

3.1. 处理类别变量

类别变量(categorial data)是一种常见的变量,在我之前写的『新手数据挖掘中的几个常见误区』 一文的第三节中讨论过为何要对类别变量编码

toy_data当中,字段Continent, Country, Product, Brand, TreeID, Industry, Saler都可以看做是类别变量。处理类别变量一般是先标签化,然后再二值化编码。标签化的目的是将字段的原始值(如字符串、不连续的数字等)转换成连续的整数值,再对整数值二值化编码,如果原始值是整数,则直接二值化即可

我们拿toy_data前几个样本的Continent字段举例,对其进行编码:

mapper = skp.DataFrameMapper([
('Continent', sklearn.preprocessing.LabelBinarizer()),
])
tempX = df[['Continent']].head()
print tempX
print mapper.fit_transform(tempX.copy())

运行结果如下

可以看到,原来的一列Continent字段变成了三列,分别代表[ 'AM', 'EP', 'LA' ],取值1表明是,取值0表明否。这就是常说的one-hot编码。如果类别变量的取值是整数,则直接用sklearn.preprocessing.OneHotEncoder()即可,把上面代码中LabelBinarizer()替换掉

注意我们必须将对训练集上的变换原封不动的作用到测试集,而不能重新对测试集的数据做变换(详见我之前写的『新手数据挖掘中的几个常见误区』第一节)。

3.2. 处理数值变量

一般而言,数值变量不用做太多处理,只需做正规化(normalization)和标准化(standardization)即可,分别对应scikit-learn中的NormalizerStandardScaler。不过对于稀疏变量,在做标准化的时候要注意,选择不去均值。

其实数值型变量最好也进行离散化,离散手段从基本的等距离散法、按分隔点人为指定,到聚类、输入树模型等,手段很多,在此不详细展开,我会在后续文章中提及。

3.3. 处理文本变量

文本在实际问题中很常见,比如用户评论、新闻摘要、视频弹幕等等。我们用的toy_data不包含文本变量,所以这里我参考了scikit-learn的文档,一个小的corpus作为我们的训练数据集。

corpus = [
'This is the first document.',
'This is the second second document.',
'And the third one.',
'Is this the first document?',
]

corpus有四句话,可以看做是四个样本。接下来我们先用一个简单的方法处理文本变量——统计corpus中每个词出现次数,代码如下:

from sklearn.feature_extraction.text import CountVectorizer
vectorizer1 = CountVectorizer(min_df=1)
temp1 = vectorizer1.fit_transform(corpus)
print vectorizer1.get_feature_names()
print temp1.toarray() # temp1是sparse类型, 转换成ndarray方便查看

运行结果:

第一行是corpus中所有词,下面的ndarray每行代表该词在该样本中出现次数,比如第2行第6列的2代表second这个词在第二句话中出现了2次。一般我们不会直接用这个结果,而是会将每行归一化之类。

这种处理方式简单粗暴,没有考虑词与词之间的关系。我们改进一下这个方法,除了考虑单个词之外,还考虑corpus中成对出现的词(类似NLP里n-gram的 bi-gram,具体请自行Google),代码如下

vectorizer2 = CountVectorizer(ngram_range=(1, 2))
temp2 = vectorizer2.fit_transform(corpus)
print vectorizer2.get_feature_names()
print temp2.toarray()

运行结果:

然而,这还不够,像a is this这类的助词、介词等,词频将非常高(在NLP中又叫停止词 stop word),所以需要减小他们的权重。一种做法是,不再简单统计该词在文档中出现的词频,而且还要统计 出现该词的文档的占比,这在NLP中叫tfidf。说的有点绕,具体到我们的例子中可以写成如下表达式:

某单词x的tfidf = x在一个样本中出现的次数/出现x的文档占比

分子即tf,分母即1/idf,有时需要用log sqrt之类的函数作用在tf或者 1/idf上,以减弱某项的影响。同样,我们可以:

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer3 = TfidfVectorizer(ngram_range=(1, 2))
temp3 = vectorizer3.fit_transform(corpus)
print vectorizer3.get_feature_names()
print temp3.toarray()

运行结果:

仔细观察不难发现,is this这类的停止词在变换后数值变小了。

!!注意!!跟处理类别变量、数值变量一样,我们在处理文本变量时,必须将训练集上的变换方式原封不动地作用到验证集或测试集上,而不能重新对验证集或者测试集做变换。比如在得到上面的vectorizer3后,我们将其作用在一个新的样本 ['a new sentence']上,代码如下

print vectorizer1.transform(['a new sentence']).toarray()

我们可以看到,结果是 [[0 0 0 0 0 0 0 0 0]],因为这个样本里的三个词从未出现在训练集corpus中,这是正确的结果!

为了方便将变换作用在未来的测试集,我们可以先把vectorizer3pickle保存到本地,用的时候再load,保存方式如下:

import cPickle as pickle
pickle.dump(vectorizer3, open('vectorizer3.pkl','w'))

用的时候再 vectorizer = pickle.load(open('vectorizer3.pkl','r'))即可。

3.4. 特征融合

ToDo 区别对待稠密特征和稀疏特征,

3.4. 特征降维

ToDo PCA等

3.5. 特征选择

ToDo

4. 模型选择和模型融合

ToDo

◆ ◆ ◆

实战

to do,欢迎各位到微信菜单“问答社区”交流实战经验。


来源:大数据 文摘

原文发布于微信公众号 - PPV课数据科学社区(ppvke123)

原文发表时间:2016-08-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习之旅

python开发:特征工程代码模版(二)

正题开始: 这篇文章是入门级的特征处理的打包解决方案的python实现汇总,如果想get一些新鲜血液的朋友可以叉了,只是方便玩数据的人进行数据特征筛选的代码集...

1633
来自专栏深度学习入门与实践

【深度学习系列】PaddlePaddle垃圾邮件处理实战(一)

4004
来自专栏PPV课数据科学社区

R语言与数据分析之二:绘图

? 图形展示是最高效且形象的数据描述手段,因此巧妙的图像展示是高质量数据分析报告的必备内容,因此强大的图形展示功能也是统计分析软件的必备功能。R语言提供了强大...

43315
来自专栏机器之心

教程 | AI玩微信跳一跳的正确姿势:跳一跳Auto-Jump算法详解

39411
来自专栏懒人开发

(8.3)James Stewart Calculus 5th Edition:Applications to Physics and Engineering

any point in a liquid the pressure is the same in all directions 液体中任何点在任何方向收到的...

1054
来自专栏深度学习

机器学习在web攻击检测中的应用实践

一、背景 通俗地讲,任何一个的机器学习问题都可以等价于一个寻找合适变换函数的问题。例如语音识别,就是在求取合适的变换函数,将输入的一维时序语音信号变换到语义空间...

3785
来自专栏机器之心

贾扬清撰文详解Caffe2:从强大的新能力到入门上手教程

选自 Nvidia Blog 作者:Aaron Markham、贾扬清 机器之心编译 昨天,Facebook 推出了 Caffe2,一个兼具表现力、速度和模块性...

2943
来自专栏CVer

重磅 | TensorFlow学习资料最全集锦

TensorFlow 已然成为深度学习框架中的扛把子,各位童鞋即使没有学习过,但一定有所耳闻。本文总结了TensorFlow相关的入门指南、网上教程、视频教程、...

1873
来自专栏目标检测和深度学习

资源 | DLL:一个炙手可热的快速深度神经网络库

771
来自专栏媒矿工厂

FVC/H.266参考软件JEM的性能评价

JEM简介 ? FVC/H.266编解码器采用的参考软件为JEM(Joint Exploration Model),JEM是在HEVC参考软件HM...

7867

扫码关注云+社区

领取腾讯云代金券