在kaggl上的入门实战代码,把一些心得和分析写在了注释中。
# -- coding: utf-8 --
import pandas as pd
import numpy as np
import re
import sklearn
import xgboost as xgb
import seaborn as sns
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
import plotly.offline as py
py.init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.tools as tls
import warnings
warnings.filterwarnings('ignore')
from sklearn.ensemble import (RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier, ExtraTreesClassifier)
from sklearn.svm import SVC
from sklearn.cross_validation import KFold
from sklearn.preprocessing import Imputer
train = pd.read_csv('/home/wrg/kaggle/titanic/train.csv')
test = pd.read_csv('/home/wrg/kaggle/titanic/test.csv')
PassengerId = test['PassengerId']
train.head(3)
full_data = [train, test]
train['Name_length'] = train['Name'].apply(len)
test['Name_length'] = test['Name'].apply(len)
train['Has_Cabin'] = train['Cabin'].apply(lambda x: 0 if type(x) == float else 1)
test['Has_Cabin'] = test['Cabin'].apply(lambda x : 0 if type(x) == float else 1)#就是这里把test写成了train导致失败从而两个小时找bug
for dataset in full_data:#dataset只有两个元素,train和set
dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1
for dataset in full_data:
dataset['IsAlone'] = 0
dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1
for dataset in full_data:
dataset['Embarked'] = dataset['Embarked'].fillna('S')
for dataset in full_data:
dataset['Fare'] = dataset['Fare'].fillna(train['Fare'].median())
train['CategoricalFare'] = pd.qcut(train['Fare'], 4)#只是为了下面变成离散特征做计算而已,之后要删除
for dataset in full_data:
age_avg = dataset['Age'].mean()
age_std = dataset['Age'].std()
age_null_count = dataset['Age'].isnull().sum()
age_null_random_list = np.random.randint(age_avg - age_std,
age_avg + age_std,
size = age_null_count)
dataset['Age'][np.isnan(dataset['Age'])] = age_null_random_list#这里读不懂应该是python水平还不到位
dataset['Age'] = dataset['Age'].astype(int)
train['CategoricalAge'] = pd.cut(train['Age'], 5)#只是为了下面变成离散特征做计算而已,之后要删除
def get_title(name):
title_search = re.search(' ([A-Za-z]+)\.', name)#正则表达式找到包含字母的名字,以.分开(数据中的,不知道为什么也被分开了
if title_search:
return title_search.group(1)#(0)是名字,(1)是Miss之类的,(2)是姓
return ""
for dataset in full_data:
dataset['Title'] = dataset['Name'].apply(get_title)#apply应用了一个函数规则
for dataset in full_data:
dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt',
'Col','Don', 'Dr', 'Major',
'Rev', 'Sir', 'Jonkheer', 'Dona'],
'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle','Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
for dataset in full_data:
dataset['Sex'] = dataset['Sex'].map({'female': 0, 'male': 1}).astype(int)
title_mapping = {"Mr": 1, "Miss": 2, "Mrs":3, "Master": 4, "rare": 5}
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
dataset['Embarked'] = dataset['Embarked'].map({'S': 0, 'C': 1, 'Q': 2}).astype(int)
dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare']> 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2
dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3
dataset['Fare'] = dataset['Fare'].astype(int)
dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
dataset.loc[ dataset['Age'] > 64, 'Age'] = 4 ;
drop_elements = ['PassengerId', 'Name', 'Ticket', 'Cabin', 'SibSp']
train = train.drop(drop_elements, axis = 1)
train = train.drop(['CategoricalAge', 'CategoricalFare'], axis = 1)
test = test.drop(drop_elements, axis = 1)
train.head(3)
colormap = plt.cm.RdBu#cm:colormap, RdBu:red, white, blue
plt.figure(figsize=(14,12))
plt.title('Pearson Correlation of Features',y=1.05, size=15)#y表示距离坐标轴的距离;size表示字体大小
sns.heatmap(train.astype(float).corr(), linewidths=0.1, vmax=1.0,
square=True, cmap=colormap, linecolor='white',annot=True)#linewidths:划分单元格的直线的宽度;vmax:右边条形颜色区域的最大值
#square:如果为True,则将Axes纵横比设置为“相等”,这样每个单元格将是正方形的
#cmap:从数据值到色彩空间的映射。如果没有提供,默认将取决于中心是否设置。
#annot:如果为True,则在每个单元格中写入数据值。如果一个数组的形状与数据形状相同,那么使用它来标注热图而不是原始数据。
#从图中可以看出:我们的训练集中没有太多冗余或多余的数据(根据pearson相关性)
#下面的pairplot因为python版本的原因没有画出来
#g = sns.pairplot(train[['Survived', 'Pclass', 'Sex', 'Age', 'Parch', 'Fare', 'Embarked',
# 'FamilySize', 'Title']], hue='Survived', palette = 'seismic',size=1.2,diag_kind = 'kde',diag_kws=dict(shade=True),plot_kws=dict(s=10))
#g.set(xticklabels=[])
ntrain = train.shape[0]
ntest = test.shape[0]
SEED = 0
NFOLDS = 5
kf = KFold(ntrain, n_folds= NFOLDS, random_state=SEED)
#KFold文档:#http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.KFold.html#sklearn.cross_validation.KFold
#创建一个skleranhelper类
class SklearnHelper(object):
def __init__(self, clf, seed=0, params=None):
params['random_state'] = seed
self.clf = clf(**params)#这里表示python中的多参数转字典类型的意思,传入要用哪种ML库
def train(self, x_train, y_train):
self.clf.fit(x_train, y_train)
def predict(self, x):
return self.clf.predict(x)
def fit(self,x,y):
return self.clf.fit(x,y)
def feature_importances(self,x,y):
print(self.clf.fit(x,y).feature_importances_)
#预测函数(这里还是有点懵逼)
def get_oof(clf, x_train, y_train, x_test):#x_train,y_train:是训练集的变量xy;x_test:是测试集中的x,要预测y_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):#枚举kf,kf是上面的KFold产生的,i表示第几折交叉验证
#但是这里kf为什么能产生这样的结构我还没有搞清楚
x_tr = x_train[train_index]#第i折的训练集x_str
y_tr = y_train[train_index]#第i折的训练集y_str
x_te = x_train[test_index]#第i折的测试集x_te
clf.train(x_tr, y_tr)#用第i折的x,y进行模型训练
oof_train[test_index] = clf.predict(x_te)#第i折的测试集x_te进行的预测(也就是再把训练集划分为k-1训练集和1分测试集)
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)#相当于转置
#reshape(-1,1)举例
#a = np.array([1, 2, 3, 4]);
#d = a.reshape((1,-1)) array([[1, 2, 3, 4]])
#d = a.reshape((-1,1))
#array([[1],
#[2],
#[3],
#[4]])
#开始基分类器的构建
#Random Forest classifier; Extra Trees classifier; AdaBoost classifer; Gradient Boosting classifer; Support Vector Machine
#先是每个分类器的参数
rf_params = {
'n_jobs': -1,
'n_estimators': 500,
'warm_start': True,
#'max_features': 0.2,
'max_depth': 6,
'min_samples_leaf': 2,
'max_features' : 'sqrt',
'verbose': 0
}
et_params = {
'n_jobs': -1,
'n_estimators':500,
#'max_features': 0.5,
'max_depth': 8,
'min_samples_leaf': 2,
'verbose': 0
}
ada_params = {
'n_estimators': 500,
'learning_rate' : 0.75
}
gb_params = {
'n_estimators': 500,
#'max_features': 0.2,
'max_depth': 5,
'min_samples_leaf': 2,
'verbose': 0
}
svc_params = {
'kernel' : 'linear',
'C' : 0.025
}
#通过上面定义的类sklearnhelper来产生五个对象
rf = SklearnHelper(clf=RandomForestClassifier, seed=SEED, params=rf_params)
et = SklearnHelper(clf=ExtraTreesClassifier, seed=SEED, params=et_params)
ada = SklearnHelper(clf=AdaBoostClassifier, seed=SEED, params=ada_params)
gb = SklearnHelper(clf=GradientBoostingClassifier, seed=SEED, params=gb_params)
svc = SklearnHelper(clf=SVC, seed=SEED, params=svc_params)
#创建numpy数组来feed我们的模型
y_train = train['Survived'].ravel()#ravel和flatten的区别:http://blog.youkuaiyun.com/lanchunhui/article/details/50354978
train = train.drop(['Survived'], axis=1)
x_train = train.values
x_test = test.values
#用上面的fole函数产生第一层基分类器的输出
et_oof_train, et_oof_test = get_oof(et, x_train, y_train, x_test) # Extra Trees
rf_oof_train, rf_oof_test = get_oof(rf,x_train, y_train, x_test) # Random Forest
ada_oof_train, ada_oof_test = get_oof(ada, x_train, y_train, x_test) # AdaBoost
gb_oof_train, gb_oof_test = get_oof(gb,x_train, y_train, x_test) # Gradient Boost
svc_oof_train, svc_oof_test = get_oof(svc,x_train, y_train, x_test) # Support Vector Classifier
print("Training is complete")
#下面是展示基分类器中,每个分类器的特征的重要性;几乎每一个sklearn都有feature_importances这个属性
rf_feature = rf.feature_importances(x_train,y_train)
et_feature = et.feature_importances(x_train, y_train)
ada_feature = ada.feature_importances(x_train, y_train)
gb_feature = gb.feature_importances(x_train,y_train)
#没有好的办法直接存储这些重要性,只好复制粘贴到列表中
rf_features = [ 0.13489756, 0.18166321, 0.02758151, 0.02169647, 0.06888994, 0.02290583,
0.10921789, 0.06505552, 0.06656376, 0.01332795, .28820037]
et_features = [ 0.12543729, 0.36809979, 0.0264444, 0.01642862, 0.05474128, 0.0273463,
0.04570301, 0.08072946, 0.04706416, 0.01955174, 0.18845394]
ada_features = [ 0.038, 0.01, 0.014, 0.066, 0.036, 0.008, 0.75, 0.002, 0.046, 0.006, 0.024]
gb_features = [ 0.07536723, 0.04250414, 0.12307408, 0.03138359, 0.09732762, 0.03925738,
0.39045526, 0.01596467, 0.07150022, 0.02626842, 0.08689739]
cols = train.columns.values
# Create a dataframe with features
feature_dataframe = pd.DataFrame( {'features': cols,
'Random Forest feature importances': rf_features,
'Extra Trees feature importances': et_features,
'AdaBoost feature importances': ada_features,
'Gradient Boost feature importances': gb_features
})
feature_dataframe.head()
#用散点图scatter来画出不同分类器中的特征重要性
#import plotly.graph_objs as go
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')#以上的一些参数设置需要查看文档
trace = go.Scatter(
y = feature_dataframe['Extra Trees 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['Extra Trees feature importances'].values,
colorscale='Portland',
showscale=True
),
text = feature_dataframe['features'].values
)
data = [trace]
layout= go.Layout(
autosize= True,
title= 'Extra Trees 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')
# Scatter plot
trace = go.Scatter(
y = feature_dataframe['AdaBoost 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['AdaBoost feature importances'].values,
colorscale='Portland',
showscale=True
),
text = feature_dataframe['features'].values
)
data = [trace]
layout= go.Layout(
autosize= True,
title= 'AdaBoost 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')
# Scatter plot
trace = go.Scatter(
y = feature_dataframe['Gradient Boost 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['Gradient Boost feature importances'].values,
colorscale='Portland',
showscale=True
),
text = feature_dataframe['features'].values
)
data = [trace]
layout= go.Layout(
autosize= True,
title= 'Gradient Boosting 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')
#创建一个平均值的新列
feature_dataframe['mean'] = feature_dataframe.mean(axis= 1) # axis = 1 计算每行的平均值 ; 0:计算每列的平均值
#画出平均值的重要性大小
y = feature_dataframe['mean'].values
x = feature_dataframe['features'].values
data = [go.Bar(
x= x,
y= y,
width = 0.5,
marker=dict(
color = feature_dataframe['mean'].values,
colorscale='Portland',
showscale=True,
reversescale = False
),
opacity=0.6
)]
layout= go.Layout(
autosize= True,
title= 'Barplots of Mean 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='bar-direct-labels')
#把基分类器的结果保存起来用于后面分类器使用
base_predictions_train = pd.DataFrame( {'RandomForest': rf_oof_train.ravel(),
'ExtraTrees': et_oof_train.ravel(),
'AdaBoost': ada_oof_train.ravel(),
'GradientBoost': gb_oof_train.ravel()
})
#相关性图
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')
x_train = np.concatenate(( et_oof_train, rf_oof_train, ada_oof_train, gb_oof_train, svc_oof_train), axis=1)
x_test = np.concatenate(( et_oof_test, rf_oof_test, ada_oof_test, gb_oof_test, svc_oof_test), axis=1)
#现在已经把x-train和x_test的一级训练和测试预测连接起来,现在我们可以适应二级学习模型。
#Second level learning model via XGBoost
#用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)#这些参数需要查看文档来了解作用,对XGBoost还不是太了解,这里先不写参数功能,后续再去学习。
predictions = gbm.predict(x_test)
#产生格式正确的submission文件:最后,我们现在可以将所有的一级和二级模型进行训练和适应,然后将预测结果输出到泰坦尼克号竞赛的正确格式如下
StackingSubmission = pd.DataFrame({ 'PassengerId': PassengerId,
'Survived': predictions })
StackingSubmission.to_csv("StackingSubmission.csv", index=False)
`