天天看点

用python参加Kaggle的些许经验总结

用python在kaggle上试了几个project,有点体会,记录下。

EDA,也就是对数据进行探索性的分析,一般就用到pandas和matplotlib就够了。EDA一般包括:

每个feature的意义,feature的类型,比较有用的代码如下

df.describe()

df['Category'].unique()

看是否存在missing value

df.loc[df.Dates.isnull(),'Dates']

每个特征下的数据分布,可以用boxplot或者hist来看

%matplotlib inline

import matplotlib.pyplot as plt

df.boxplot(column='Fare', by = 'Pclass')

plt.hist(df['Fare'], bins = 10, range =(df['Fare'].min(),df['Fare'].max()))

plt.title('Fare >distribution')

plt.xlabel('Fare')

plt.ylabel('Count of Passengers')

#如果变量是categorical的,想看distribution,则可以:

df.PdDistrict.value_counts().plot(kind='bar', figsize=(8,10))

如果想看几个feature之间的联立情况,则可以用pandas的groupby,

temp = pd.crosstab([df.Pclass, df.Sex], df.Survived.astype(bool))

temp.plot(kind='bar', stacked=True, color=['red','blue'], grid=False)

在这步完成之后,要对以下几点有大致了解

理解每个特征的意义

要知道哪些特征是有用的,这些特征哪些是直接可以用的,哪些需要经过变换才能用,为之后的特征工程做准备

数据预处理,就是将数据处理下,为模型输入做准备,其中包括:

处理missing value:这里学问有点深,如果各位有好的经验可以跟我交流下。以我浅薄的经验来说我一般会分情况处理

如果missing value占总体的比例非常小,那么直接填入平均值或者众数

如果missing value所占比例不算小也不算大,那么可以考虑它跟其他特征的关系,如果关系明显,那么直接根据其他特征填入;也可以建立简单的模型,比如线性回归,随机森林等。

如果missing value所占比例大,那么直接将miss value当做一种特殊的情况,另取一个值填入

处理Outlier:这个就是之前EDA的作用了,通过画图,找出异常值

处理categorical feature:一般就是通过dummy variable的方式解决,也叫one hot encode,可以通过pandas.get_dummies()或者 sklearn中preprocessing.OneHotEncoder(), 我个人倾向于用pandas的get_dummies()

看个例子吧,

dummy variable

将一列的month数据展开为了12列,用0、1代表类别。

另外在处理categorical feature有两点值得注意:

如果特征中包含大量需要做dummy variable处理的,那么很可能导致得到一个稀疏的dataframe,这时候最好用下PCA做降维处理。

(更新)近期在kaggle成功的案例中发现,对于类别特征,在模型中加入tf-idf总是有效果的。

还有个方法叫“Leave-one-out” encoding,也可以处理类别特征种类过多的问题,实测效果不错。

理论上来说,特征工程应该也归属于上一步,但是它太重要了,所以将它单独拿出来。kaggle社区对特征工程的重要性已经达成了共识,可以说最后结果的好坏,大部分就是由特征工程决定的,剩下部分应该是调参和Ensemble决定。特征工程的好坏主要是由domain knowledge决定的,但是大部分人可能并不具备这种知识,那么只能尽可能多的根据原来feature生成新的feature,然后让模型选择其中重要的feature。这里就又涉及到feature selection,

最常用的模型是Ensemble Model,比如 Random Forest,Gradient Boosting。当然在开始的时候,可以用点简单的模型,一方面是可以作为底线threshold,另一方面也可以在最后作为Ensemble Model。

from sklearn.grid_search import GridSearchCV

from pprint import pprint

clf=RandomForestClassifier(random_state=seed)

parameters = {'n_estimators': [300, 500], 'max_features':[4,5,'auto']}

grid_search = GridSearchCV(estimator=clf,param_grid=parameters, cv=10, scoring='accuracy')

print("parameters:")

pprint(parameters)

grid_search.fit(train_x,train_y)

print("Best score: %0.3f" % grid_search.best_score_)

print("Best parameters set:")

best_parameters=grid_search.best_estimator_.get_params()

for param_name in sorted(parameters.keys()):

print("\t%s: %r" % (param_name, best_parameters[param_name]))

Model Ensemble有Bagging,Boosting,Stacking,其中Bagging和Boosting都算是Bootstraping的应用。Bootstraping的概念是对样本每次有放回的抽样,抽样K个,一共抽N次。

Bagging:每次从总体样本中随机抽取K个样本来训练模型,重复N次,得到N个模型,然后将各个模型结果合并,分类问题投票方式结合,回归则是取平均值,e.g.Random Forest。

Boosting:一开始给每个样本取同样的权重,然后迭代训练,每次对训练失败的样本调高其权重。最后对多个模型用加权平均来结合,e.g. GBDT。

Bagging与Boosting的比较:在深入理解Bagging和Boosting后发现,bagging其实是用相同的模型来训练随机抽样的数据,这样的结果是各个模型之间的bias差不多,variance也差不多,通过平均,使得variance降低(由算平均方差的公式可知),从而提高ensemble model的表现。而Boosting其实是一种贪心算法,不断降低bias。

Stacking: 训练一个模型来组合其他各个模型。首先先训练多个不同的模型,然后再以之前训练的各个模型的输出为输入来训练一个模型,以得到一个最终的输出。使用过stacking之后,发现其实stacking很像神经网络,通过很多模型的输出,构建中间层,最后用逻辑回归讲中间层训练得到最后的结果。这里贴一个例子供参考。

最后是我的两点心得吧

设置random seed,使得你的模型reproduce,以Random Foreset举例:

seed=0

每个project组织好文件层次和布局,既方便与其他人交流,也方便自己。比如在一个project下,分设3个文件夹,一个是input,放训练数据、测试数据,一个model,放模型文件,最后一个submission文件,放你生成要提交的结果文件。

这篇文章是参加kaggle之后的第一次总结,描述了下kaggle的步骤,通用的知识点和技巧。希望在未来一个月中,能把xgboost和stacking研究应用下,然后再来update。希望大家有什么想法都能跟我交流下~~

update: 更新了关于类别特征的处理方式以及Boosting和Bagging的看法,还有stacking的内容。

转自:https://www.jianshu.com/p/32def2294ae6