机器学习与数据挖掘大数据首页投稿

数据挖掘实战总结

2018-05-21  本文已影响12人  PeTu

零、 引言

此篇文章的初版,是笔者照着kaggle竞赛社区中Titanic项目中的两篇文章实战后的总结,两篇文章分别为:

  1. Titanic Data Science Solutions

    第一篇文章是以Titanic项目为例完完整整的介绍了一遍数据挖掘实战从理解数据到训练模型最后提交的整个过程,跟着实现一遍可以很清楚的理解与感知数据挖掘实战全过程,非常有助于培养实战的感觉

  2. Introduction to Ensembling/Stacking in Python

    第二篇文章也是一个以Titanic项目为例完整介绍了实战过程的文章,但是这篇文章的重心在于介绍与实践数据挖掘的集成算法 — Stacking 算法

一、 实战过程及常用方法

0. 理解题目与观察数据

- 理解题目

接手任何一竞赛或者项目的时候,第一件事都是要认真的阅读题目,充分理解题目的背景,因为每个项目虽然大体上的流程是差不多,但是每一个步骤的实现都会不一样,例如特征提取与选择方面,除去利用数学知识降维或者提取主要特征之外,还有一个很重要的方面,就是需要理解题目的业务场景,代入背景去思考业务的情况,这种做法可以让我们事先加强对特征的理解,方便我们判断特征工程过程中的合理性,也可以在一些项目场景中利用其特有的数据特征来修正这种场景下的模型已达到很好的效果

这种对于业务场景的思考应是贯彻到整个项目实战过程中的

- 观察数据

初步题目后,紧接着就是对于数据的观察和思考,python中利用pandas进行数据的加载和处理非常方便,其中pandas库中的一些观察数据的方法有

import pandas as pd
train_df = pd.read_csv('./data/train.csv')
train_df.head()
train_df.info()
# describe() 用于观察连续数值特征
train_df.describe()
# describe(include=['O']) 用于观察字符串特征及非连续值分类特征
train_df.describe(include=['O'])

其中describe()是个很有效的描述数据的方法,可以加入percentiles=[.1, .2, .3, .4, .5, .6, .7]这样的分位参数来将连续数值特征排序并显示分位值。描述分类特征则可以返回特征值的个数、频率等值

一般观察思考数据是结合业务场景的,需要理解什么样的场景下会产生这样的数据,哪些数据特征与结果存在明显的对应关系等,在采取合适的操作之前应该有一些我们自己的关于数据的假设,然后在数据中佐证我们的假设

1. 分析数据与特征工程

We need arrive at following assumptions based on data analysis done so far. We may validate these assumptions further before taking appropriate actions.

上句是借用第一篇文章的一句话,也是我们这一部分的思考,数据分析比较多的都是用数据来验证我们的假想,然后再采取更合适的操作

- 特征工程部分的工作流程需要解决七个主要目标:

上述的七个方向不仅是特征工程部分我们需要思考的,也是我们进行数据分析处理的七个角度

所以对应的数据清洗操作就可包含:

- 数据分析常用的方法有

Analyze by pivoting feature

train_df[['feature1', 'feature2']].groupby(['feature1 or feature2'], as_index=False).mean().sort_values(by='feature1 or feature2', ascending=False)

Analyze by visualizing data

# 利用 seaborn 画图
# sns.barplot | plt.hist | sns.pointplot
grid = sns.FacetGrid(train_df, col='feature1', row='feature2', size=2.2, aspect=1.6)
grid.map(plt.hist, 'feature3', alpha=.5, bins=20)
grid.add_legend()
grid = sns.FacetGrid(train_df, row='Embarked', size=2.2, aspect=1.6)
grid.map(sns.pointplot, 'Pclass', 'Survived', 'Sex', palette='deep')
grid.add_legend()
plt.show()
# 特征值相关性的热力图
colormap = plt.cm.RdBu
plt.figure(figsize=(14,12))
plt.title('Correlation of Features', y=1.05, size=15)
sns.heatmap(train.astype(float).corr(),linewidths=0.1,vmax=1.0, 
            square=True, cmap=colormap, linecolor='white', annot=True)
g = sns.pairplot(train[[u'Survived', u'Pclass', u'Sex', u'Age', u'Parch', u'Fare', u'Embarked',
       u'FamilySize', u'Title']], hue='Survived', palette = 'seismic',size=1.2,diag_kind = 'kde',diag_kws=dict(shade=True),plot_kws=dict(s=10) )
g.set(xticklabels=[])
# 利用 plotly 画图 
# go.Scatter | go.Bar 
trace = go.Scatter(
    y = feature_dataframe['Random Forest feature importances'].values,
    x = feature_dataframe['features'].values,
    mode='markers',
    marker=dict(
        sizemode = 'diameter',
        sizeref = 1,
        size = 25,
#       size= feature_dataframe['AdaBoost feature importances'].values,
        #color = np.random.randn(500), #set color equal to a variable
        color = feature_dataframe['Random Forest feature importances'].values,
        colorscale='Portland',
        showscale=True
    ),
    text = feature_dataframe['features'].values
)
data = [trace]

layout= go.Layout(
    autosize= True,
    title= 'Random Forest Feature Importance',
    hovermode= 'closest',
#     xaxis= dict(
#         title= 'Pop',
#         ticklen= 5,
#         zeroline= False,
#         gridwidth= 2,
#     ),
    yaxis=dict(
        title= 'Feature Importance',
        ticklen= 5,
        gridwidth= 2
    ),
    showlegend= False
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig,filename='scatter2010')
# 用 plotly 画热力图
data = [
    go.Heatmap(
        z= base_predictions_train.astype(float).corr().values ,
        x=base_predictions_train.columns.values,
        y= base_predictions_train.columns.values,
          colorscale='Viridis',
            showscale=True,
            reversescale = True
    )
]
py.iplot(data, filename='labelled-heatmap')

2. 模型训练与预测

这里是对于数据挖掘算法的选择,一般分类用的算法包括:

- Stacking 算法

此处额外需要讲述一种集成算法 —Stacking 集成算法,以两层Stacking 算法为例:

第一层,可以挑选 4 种或 5 种分类算法,记为model_amodel_bmodel_cmodel_dmodel_e

对训练数据进行训练,此时就需要注意,在Stacking算法中,对训练数据的模型训练需要用到 K-折交叉验证 方法以 5-折交叉验证 为例:

首先假设我们有 m * n维度的训练数据train_set以及k * w维度的测试数据test_set,把train_set分为5份,取出其中的 4 份作为新的(4/5)m * n维度的训练数据记为tr_set,另一份则作为临时的(1/5)m * n维度的测试数据记为te_set,假设模型model_a,利用tr_setmodel_a进行训练,训练好的模型来预测余下的一份te_set,得到的结果为(1/5)m * 1维度,用一种m * 1维度的数据结构model_list_a中的一部分记录下来,然后继续用此时的model_a预测全部的测试数据,得到结果model_a_tmp_1

因为是 **5-折 **交叉验证,所以这个过程会重复五遍,即model_a模型会被不同的(4/5)m * n维度的训练数据训练五遍,最终的model_list_a里保存的则是model_a对于所有训练数据的预测值,每一次的重复又会产生不同的model_a_tmp_(2,3,4,5),将这些model_a_tmp相加求平均得model_a_test

而又因为我们选择了五个训练模型,所以对于model_bmodel_cmodel_dmodel_e四个模型,我们同样会各训练五遍,也就自然会产生model_list_bmodel_list_cmodel_list_dmodel_list_e,分别存储的是四个模型对于全部训练数据的预测值,还会产生每个模型的对于测试数据test_set的平均预测结果 model_b_testmodel_c_testmodel_d_testmodel_e_test

然后将得到的结果拼接,如下代码实现:

x_train = np.concatenate(( model_list_a, model_list_b, model_list_c, model_list_d, model_list_e), axis=1)
x_test = np.concatenate(( model_a_test, model_b_test, model_c_test, model_d_test, model_e_test), axis=1)

此时得到的x_train的数据结构可能是这样的

屏幕快照 2018-05-21 下午11.06.43.png

我们就是利用这个 x_trainx_test 进行 stacking 算法的第二层训练,例如利用xgboost算法进行训练,如下:

gbm = xgb.XGBClassifier(
    #learning_rate = 0.02,
 n_estimators= 2000,
 max_depth= 4,
 min_child_weight= 2,
 #gamma=1,
 gamma=0.9,                        
 subsample=0.8,
 colsample_bytree=0.8,
 objective= 'binary:logistic',
 nthread= -1,
 scale_pos_weight=1).fit(x_train, y_train)
predictions = gbm.predict(x_test)

则此时得到的predictions就是我们利用Stacking算法集成了很多种基础算法得到的最终结果

这个过程中有一个难点就是关于每个模型利用 k-折交叉验证 的思想进行的 k 次重复训练,实现代码如下:

# Some useful parameters which will come in handy later on
ntrain = train.shape[0]
ntest = test.shape[0]
SEED = 0 # for reproducibility
NFOLDS = 5 # set folds for out-of-fold prediction
kf = KFold(ntrain, n_folds= NFOLDS, random_state=SEED)

def get_oof(clf, x_train, y_train, x_test):
    oof_train = np.zeros((ntrain,))
    oof_test = np.zeros((ntest,))
    oof_test_skf = np.empty((NFOLDS, ntest))

    for i, (train_index, test_index) in enumerate(kf):
        x_tr = x_train[train_index]
        y_tr = y_train[train_index]
        x_te = x_train[test_index]

        clf.train(x_tr, y_tr)

        oof_train[test_index] = clf.predict(x_te)
        oof_test_skf[i, :] = clf.predict(x_test)

    oof_test[:] = oof_test_skf.mean(axis=0)
    return oof_train.reshape(-1, 1), oof_test.reshape(-1, 1)

此外推荐阅读 数据比赛大杀器----模型融合(stacking&blending),并且会总结一些其它重要的算法,此处挖坑GBDTxgboost

上一篇下一篇

猜你喜欢

热点阅读