当前位置:   article > 正文

基于titanic数据集介绍数据分析处理流程

titanic数据集

对大树先生titanic数据集处理的总结:

本文对大数先生所做的titanic数据集进行进一步整理:
精确到解说每一步需要做什么掌握什么。
原代码链接
原文中数据处理主要分为8大类:
1.数据总览(教你浏览数据)
2.缺失数据处理办法(根据具体缺失的数据找方法对数据进行填充)
3.分析数据关系(教画图,从图像上找出各特征与生存之间的关系)
4.变量转换(介绍了数据预处理的方法)
5.特征工程(对数据进行特征提取)
6.模型融合及测试(建模调参)
7.验证(学习曲线)
8.超参数调试(调参)

1.数据总览

拿到数据集合我们需要看一眼数据集中的内容数据集中都有什么。
所需要的库:pandas
1.用pandas打开数据集

#使用read_csv()打开数据集这里需要相对路径如果你不知道相对路径
#可以通过import os对自己当前目录进行一个测试
train_data = pd.read_csv('datalab/1386/titanic_train.csv')
  • 1
  • 2
  • 3

2.对书籍集进行观测
目前笔者接触到3种方案:

#观测数据前5行
train_data.head()
#显示数据集中数据量可以清楚看到数据集是否缺失
train_data.info()
#对数据信息进行描述包括每列对应的数量、方差平均值
train_data.describe()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

titanic数据预览
这里对titanic数据集每列的label进行解释:
PassengerId=》乘客的ID
Survived=》是否存活
Pclass=》船舱等级
Name=》乘客姓名
Sex=》乘客性别
Age=》乘客年龄
SibSp=》有无兄弟姐妹
Parch=》有无父母子女
Ticket=》登船票号
Fare=》票价
Cabin=》船舱类型
Embarked=》所到达的港口

这里是使用info的方法对数据进行浏览,可以观测出数据中存在缺失值
数据总览

#这里画个饼图来观测存活情况顺便介绍一下饼图的画法
train_data['Survived'].value_counts().plot.pie(labeldistance = 1.1,autopct = '%1.2f%%',
                                               shadow = False,startangle = 90,pctdistance = 0.6)
#labeldistance,文本的位置离远点有多远,1.1指1.1倍半径的位置
#autopct,圆里面的文本格式,%3.1f%%表示小数有三位,整数有一位的浮点数
#shadow,饼是否有阴影
#startangle,起始角度,0,表示从0开始逆时针转,为第一块。一般选择从90度开始比较好看
#pctdistance,百分比的text离圆心的距离
#patches, l_texts, p_texts,为了得到饼图的返回值,p_texts饼图内部文本的,l_texts饼图外label的文本
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

2.缺失数据处理办法

1.首先对缺失数据进行分析
缺失依次为Age,Cabin,Embarked接下来要对缺失数据进行分析
观察类型以及数据缺失程度
Age=》不规则的数字
Cabin=》一艘船上只有几个船舱(英文)
Embarked=》到达的港口(英文)

如果数据集很多,但有很少的缺失值,可以删掉带缺失值的行;
如果该属性相对学习来说不是很重要,可以对缺失值赋均值或者众数。
对于标称属性,可以赋一个代表缺失的值,比如‘U0’。因为缺失本身也可能代表着一些隐含信息。比如船舱号Cabin这一属性,缺失可能代表并没有船舱。

由于数据量少所以选择将数据全部进行填充

#首先是到达港口缺失较少选择使用众数来进行填充mode()
train_data.Embarked[train_data.Embarked.isnull()] = train_data.Embarked.dropna().mode().values
#其次由于Cabin属性缺失过多可能代表没有船舱其实缺失数据本身可能就是一种隐藏属性。
train_data['Cabin'] = train_data.Cabin.fillna('U0') 
  • 1
  • 2
  • 3
  • 4

对于Age这种对模型影响比较大的参数可以选择多种方法进行补充:
作者选择使用随机森林回归的方法对模型进行训练用来预测Age的值

from sklearn.ensemble import RandomForestRegressor

#选择数据预测年龄
age_df = train_data[['Age','Survived','Fare', 'Parch', 'SibSp', 'Pclass']]
age_df_notnull = age_df.loc[(train_data['Age'].notnull())]
age_df_isnull = age_df.loc[(train_data['Age'].isnull())]
X = age_df_notnull.values[:,1:]
Y = age_df_notnull.values[:,0]

# 使用随机森林的方法去预测模型其中n_estimators=1000最大允许使用1000个若学习器
# n_job=-1CPU并行计算的核数(设置为-1表示对CPU核数不限制)
# 之后会对本文所用到的所有模型进行整理归纳
RFR = RandomForestRegressor(n_estimators=1000, n_jobs=-1)
RFR.fit(X,Y)
predictAges = RFR.predict(age_df_isnull.values[:,1:])
train_data.loc[train_data['Age'].isnull(), ['Age']]= predictAges
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

到这里为止数据已经完全补充完全

3.分析数据关系

这张主要讲的是个数据分析也就是数据可视化应该如何画图,笔者以为能画好图对数据分析非常重要
3.1Sex 与Survived 之间的关系(直方图画法)

#这里用到了groupby函数:以sex进行分组对其他参量进行求平均
train_data[['Sex','Survived']].groupby(['Sex']).mean()
  • 1
  • 2

数据格式

#这里非常方面可以直接接在数据后面用plot.bar进行图标绘制
#以sex为横坐标Survived为纵坐标
train_data[['Sex','Survived']].groupby(['Sex']).mean().plot.bar()
  • 1
  • 2
  • 3

可直观看出女士优先体现出性别的重要性
图片格式
3.2 Pclass vs Survived(依旧是直方图这里重复的东西不做过多解释)

train_data[['Pclass','Survived']].groupby(['Pclass']).mean().plot.bar()
  • 1

Pclass vs Survived

#这里也解释一下这里groupby的意思是以Pclass分类后再对Pclass中的sex进行分类
train_data[['Sex','Pclass','Survived']].groupby(['Pclass','Sex']).mean().plot.bar()
  • 1
  • 2

pclass ,sex vs Survived
3.3 Age 与 Survived之间的关系
因为Age是离散化较高的一个数据所以图形画法比较多结合数据集整合
3.3.1 小提琴图
分别分析不同等级船舱和不同性别下的年龄分布和生存的关系:
X[Pclass] Y[Age] hue[Survived]

#对画布进行布局
fig,ax = plt.subplots(1,2, figsize = (18,5))
#对y轴进行范围设置
ax[0].set_yticks(range(0,110,10))
#对sns.violinplot进行传参x为Pclass y为Age 需要对比的是Survived
#这里我们分析一下什么样的数据类型可以画小提琴图
#也就是说X类别比较少的一类参数Y为类别比较大 hue为2分类情况
sns.violinplot("Pclass","Age",hue="Survived",data=train_data,split=True,ax=ax[0])
ax[0].set_title('Pclass and Age vs Survived') 

ax[1].set_yticks(range(0,110,10))
sns.violinplot("Sex","Age",hue="Survived",data=train_data,split=True,ax=ax[1])
ax[1].set_title('Sex and Age vs Survived')
 
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

图片为小提琴图
3.3.2 hist 分布直方图和盒图(单列数据作图)

#另一种布置方式
plt.figure(figsize=(15,5))
plt.subplot(121)
#单列作图图主要用于看Age在数据集中的分布bins代表柱的个数
train_data['Age'].hist(bins=100)
plt.xlabel('Age')
plt.ylabel('Num')
 
plt.subplot(122)
#盒图很坐标为Age纵坐标为年龄尺度后面还会有对盒子图的介绍(详细用法)
train_data.boxplot(column='Age',showfliers=False)
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

hist与盒图
3.3.3 使用FacetGrid进行作图作kdeplot曲线图通过拟合的一种曲线
不同年龄下的生存和非生存的分布情况:

#前期对facet进行设定1.数据集2.hue指定参数进行区分
facet = sns.FacetGrid(train_data,hue="Survived",aspect=4)
#用map进行作图1.图的类型sns.kdeplot 2.作图的数据3.Shade是否需要填充
facet.map(sns.kdeplot,'Age',shade=True)
#对x轴的范围进行设置
facet.set(xlim=(0,train_data['Age'].max()))
#添加hue的标签
facet.add_legend()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.3.4不同年龄下的平均生存率:(使用sns进行绘制直方图主要是好看)

fig,axis1 = plt.subplots(1,1,figsize=(18,4))
#绘制直方图对Age需要进行转格式
train_data['Age_int'] = train_data['Age'].astype(int)
#这里是不是很熟悉对也可以用上述绘制直方图的方式进行作图
average_age = train_data[["Age_int", "Survived"]].groupby(['Age_int'],as_index=False).mean()
1.X	2.Y 3.Data
sns.barplot(x='Age_int',y='Survived',data=average_age)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Age vs Survived
3.3.5 对年龄进行分类看看不同年龄区间对生存的影响

bins = [0, 12, 18, 65, 100]
#采用pd.cut对年龄进行划分将具体的Age归类到具体的区间
train_data['Age_group'] = pd.cut(train_data['Age'],bins)
by_age = train_data.groupby('Age_group')['Survived'].mean()
print(by_age)
by_age.plot(kind = 'bar')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

直方图
3.4称呼与存活之间的关系
通过观察名字数据,我们可以看出其中包括对乘客的称呼,如:Mr、Miss、Mrs等,称呼信息包含了乘客的年龄、性别,同时也包含了入社会地位等的称呼,如:Dr,Lady,Major(少校),Master(硕士,主人,师傅)等的称呼。

#姓名中提取.之前的称呼
train_data['Title'] = train_data['Name'].str.extract(' ([A-Za-z]+)\.',expand=False)
#交叉透视表看称呼与性别之间的关系
pd.crosstab(train_data['Title'],train_data['Sex'])
  • 1
  • 2
  • 3
  • 4

交叉透视表

train_data[['Title','Survived']].groupby(['Title']).mean().plot.bar()
  • 1

在这里插入图片描述
这里作者提到了一个比较玄学的概念名字长度与生存之间的关系

fig, axis1 = plt.subplots(1,1,figsize=(18,4))
train_data['Name_length'] = train_data['Name'].apply(len)
name_length = train_data[['Name_length','Survived']].groupby(['Name_length'], as_index=False).mean()
sns.barplot(x='Name_length', y='Survived',data=name_length)
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
3.5 有无兄弟姐妹和存活与否的关系 SibSp(饼图)
value_counts().plot.pie()
在这里插入图片描述
3.6 有无父母子女和存活与否的关系 Parch(饼图)
在这里插入图片描述
3.7亲友的人数和存活与否的关系 SibSp & Parch(直方图)
在这里插入图片描述3.8 票价分布和存活与否的关系 Fare
hist
在这里插入图片描述
这里绘制票价与Pclass的关系盒图

#以Pclass进行分类每列都代表票价
train_data.boxplot(column='Fare', by='Pclass', showfliers=False)
  • 1
  • 2

在这里插入图片描述
绘制生存与否与票价均值和方差的关系:

fare_not_survived = train_data['Fare'][train_data['Survived'] == 0]
fare_survived = train_data['Fare'][train_data['Survived'] == 1]
 
average_fare = pd.DataFrame([fare_not_survived.mean(),fare_survived.mean()])
std_fare = pd.DataFrame([fare_not_survived.std(),fare_survived.std()])
#yerr让柱状图的顶端空出一部分
average_fare.plot(yerr=std_fare,kind='bar',legend=False)
 
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述
3.9 船舱类型和存活与否的关系 Cabin
由于船舱的缺失值确实太多,有效值仅仅有204个,很难分析出不同的船舱和存活的关系,所以在做特征工程的时候,可以直接将该组特征丢弃掉。 当然,这里我们也可以对其进行一下分析,对于缺失的数据都分为一类。 简单地将数据分为是否有Cabin记录作为特征,与生存与否进行分析:

train_data.loc[train_data.Cabin.isnull(),'Cabin'] = 'U0'
train_data['Has_Cabin'] = train_data['Cabin'].apply(lambda x: 0 if x == 'U0' else 1)
train_data[['Has_Cabin','Survived']].groupby(['Has_Cabin']).mean().plot.bar()
  • 1
  • 2
  • 3

在这里插入图片描述

# 可以观测Cabin的数据形状为C85,A90之类的可以通过正则表达式取前面的字母以分类不同的船舱
train_data['CabinLetter'] = train_data['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group())
# 使用factorize将只剩字母的船舱号进行数字化映射
train_data['CabinLetter'] = pd.factorize(train_data['CabinLetter'])[0]
train_data[['CabinLetter','Survived']].groupby(['CabinLetter']).mean().plot.bar()
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
3.10 Embark(港口)与存活之间的关系

#countplot计算数量的一个图
sns.countplot('Embarked',hue='Survived',data=train_data)
plt.title('Embarked and Survived')
  • 1
  • 2
  • 3

在这里插入图片描述

#这里可以显示数据量以及到达港口的生存均值
sns.factorplot('Embarked','Survived',data = train_data, size=3, aspect=2)
plt.title('Embarked and Survived rate')
plt.show()
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

4. 变量转换(介绍了数据预处理的方法)

变量转换的意思就是将非数字型转变为数字型
4.1 Dummy Variables(one-hot处理类型)

#将Embark对应的S,C,Q对应成数字分为3列在某港口置1不在某港口置0
embark_dummies = pd.get_dummies(train_data['Embarked'])
#在dataframe行相同添加列用join
train_data = train_data.join(embark_dummies)
train_data.drop(['Embarked'], axis=1, inplace=True)
embark_dummies = train_data[['S','C','Q']]
embark_dummies.head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

使用dummy之后的效果
4.2 Factoring(将非数字的特征进行对应数字化映射)

dummy不好处理Cabin(船舱号)这种标称属性,因为他出现的变量比较多。所以Pandas有一个方法叫做factorize(),它可以创建一些数字,来表示类别变量,对每一个类别映射一个ID,这种映射最后只生成一个特征,不像dummy那样生成多个特征。
有时候可以结合Factorize与dummy一起使用,用来创建更多的特征

# Replace missing values with "U0"
train_data['Cabin'][train_data.Cabin.isnull()] = 'U0'
# create feature for the alphabetical part of the cabin number
train_data['CabinLetter'] = train_data['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group())
# convert the distinct cabin letters with incremental integer values
train_data['CabinLetter'] = pd.factorize(train_data['CabinLetter'])[0]
train_data[['Cabin','CabinLetter']].head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.3 Scaling (将大范围数进行小范围映射)

#导入sklearn预处理模块
from sklearn import preprocessing
#先对np.size进行验证
assert np.size(train_data['Age']) == 891
# StandardScaler will subtract the mean from each value then scale to the unit varience
scaler = preprocessing.StandardScaler()
train_data['Age_scaled'] = scaler.fit_transform(train_data['Age'].values.reshape(-1,1))
print(train_data['Age_scaled'].head())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述
4.4 Binning(将数据按照范围进行归类)
这里介绍使用bins的两种方法

#这是上文中已经出现过的对年龄划分的一个概念通过自己定义区间对数据进行划分
bins = [0, 12, 18, 65, 100]
#采用pd.cut对年龄进行划分将具体的Age归类到具体的区间
train_data['Age_group'] = pd.cut(train_data['Age'],bins)
  • 1
  • 2
  • 3
  • 4
#这是使用qcut对数据进行统计然后自动划分成几块
train_data['Fare_bin'] = pd.qcut(train_data['Fare'],5)
print(train_data['Fare_bin'].head())
  • 1
  • 2
  • 3

这里使用过binning之后会对数据进行factorize和dummies进行二次处理使数据标准化

5.特征工程(作者对数据再次进行处理这里的处理是用于后面的训练)

在进行特征工程的时候,我们不仅需要对训练数据进行处理,还需要同时将测试数据同训练数据一起处理,使得二者具有相同的数据类型和数据分布。也就是说要将测试集添加到原来的数据集当中。

这里作者有一些做的不好的地方,因为titanic是比赛用数据集所以才测试集上并没有label因此对模型准度没办法验证笔者认为应该先预留出一部分测试数据集用于验证模型的准度。

这里就简单介绍一下作者对数据处理的一些步骤:

1.将测试集与训练集合拼接在一起(pd.append横拼 pd.join纵拼)
2.将数据进行特征处理
3.将训练集与测试集分开

这里就简单介绍一下作者对各模型的一个参考方法
5.1 Embarked
以众数补齐参数再通过dummies进行one-hot处理

#这里prefix是给one—hot处理后的数据加上label也就是说换列名
emb_dummies_df = pd.get_dummies(combined_train_test['Embarked'],prefix=combined_train_test[['Embarked']].columns[0])
  • 1
  • 2

5.2 Sex
依旧是使用dummies进行one-hot处理

5.3 Name
5.3.1
正则表达式取称呼

#取称呼
combined_train_test['Title'] = combined_train_test['Name'].map(lambda x: re.compile(",(.*?)\.").findall(x)[0])
#去留白
combined_train_test['Title'] = combined_train_test['Title'].apply(lambda x:x.strip())
  • 1
  • 2
  • 3
  • 4

5.3.2
对称呼进行分类统一化处理

#用map结合字典的方法赌数据进行替换
title_Dict = {}
title_Dict.update(dict.fromkeys(['Capt','Col','Major','Dr','Rev'],'Officer'))
title_Dict.update(dict.fromkeys(['Don','Sir','the Countess','Dona','Lady'],'Royalty'))
title_Dict.update(dict.fromkeys(['Mme','Ms','Mrs'],'Mrs'))
title_Dict.update(dict.fromkeys(['Male','Miss'],'Miss'))
title_Dict.update(dict.fromkeys(['Mr'],'Mr'))
title_Dict.update(dict.fromkeys(['Master','Jonkheer'],'Master'))

combined_train_test['Title'] = combined_train_test['Title'].map(title_Dict)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5.3.3
使用factorize跟dummies对数据进行处理
5.3.4
增加名字长度的特征

combined_train_test['Name_length'] = combined_train_test['Name'].apply(len)
  • 1

5.4 Fare
5.4.1
由前面分析可以知道,Fare项在测试数据中缺少一个值,所以需要对该值进行填充。我们按照一二三等舱各自的均价来填充:
下面transform将函数np.mean应用到各个group中。

#这里的fillna是对应位补齐同参数表对应位置进行补齐
combined_train_test['Fare'] = combined_train_test[['Fare']].fillna(combined_train_test.groupby('Pclass').transform(np.mean))
  • 1
  • 2

5.4.2
通过对Ticket数据的分析,我们可以看到部分票号数据有重复,同时结合亲属人数及名字的数据,和票价船舱等级对比,我们可以知道购买的票中有家庭票和团体票,所以我们需要将团体票的票价分配到每个人的头上。

#编程思路按组分类求数量再除以数量
combined_train_test['Group_Ticket'] = combined_train_test['Fare'].groupby(by=combined_train_test['Ticket']).transform('count')
combined_train_test['Fare'] = combined_train_test['Fare']/combined_train_test['Group_Ticket']
combined_train_test.drop(['Group_Ticket'],axis=1,inplace=True)
  • 1
  • 2
  • 3
  • 4

5.4.3
使用bins跟dummies对票价等级进行分类

5.5Pclass
Pclass这一项,其实已经可以不用继续处理了,我们只需将其转换为dummy形式即可。 但是为了更好的分析,我们这里假设对于不同等级的船舱,各船舱内部的票价也说明了各等级舱的位置,那么也就很有可能与逃生的顺序有关系。所以这里分析出每等舱里的高价和低价位。以均值为分水岭

print(combined_train_test['Fare'].groupby(by=combined_train_test['Pclass']).mean())
  • 1

在这里插入图片描述

from sklearn.preprocessing import LabelEncoder
 
#建立Pclass Fare Category
def pclass_fare_category(df,pclass1_mean_fare,pclass2_mean_fare,pclass3_mean_fare):
    if df['Pclass'] == 1:
        if df['Fare'] <= pclass1_mean_fare:
            return 'Pclass1_Low'
        else:
            return 'Pclass1_High'
    elif df['Pclass'] == 2:
        if df['Fare'] <= pclass2_mean_fare:
            return 'Pclass2_Low'
        else:
            return 'Pclass2_High'
    elif df['Pclass'] == 3:
        if df['Fare'] <= pclass3_mean_fare:
            return 'Pclass3_Low'
        else:
            return 'Pclass3_High'
 
Pclass1_mean_fare = combined_train_test['Fare'].groupby(by=combined_train_test['Pclass']).mean().get(1)
Pclass2_mean_fare = combined_train_test['Fare'].groupby(by=combined_train_test['Pclass']).mean().get(2)
Pclass3_mean_fare = combined_train_test['Fare'].groupby(by=combined_train_test['Pclass']).mean().get(3)
 
#建立Pclass_Fare Category axis指的是对列进行相同的操作,很重要
combined_train_test['Pclass_Fare_Category'] = combined_train_test.apply(pclass_fare_category,args=(
        Pclass1_mean_fare,Pclass2_mean_fare,Pclass3_mean_fare),axis=1)
#这里已经对不同船舱的高低价格进行了分类

#使用LabelEncoder对标签进行数字化处理
pclass_level = LabelEncoder()
 
#给每一项添加标签(0-5做到每一项是什么心里有数)
pclass_level.fit(np.array(['Pclass1_Low','Pclass1_High','Pclass2_Low','Pclass2_High','Pclass3_Low','Pclass3_High']))
 
#转换成数值这里也可以用字典的放法
combined_train_test['Pclass_Fare_Category'] = pclass_level.transform(combined_train_test['Pclass_Fare_Category'])
 
# dummy 转换
pclass_dummies_df = pd.get_dummies(combined_train_test['Pclass_Fare_Category']).rename(columns=lambda x: 'Pclass_' + str(x))
combined_train_test = pd.concat([combined_train_test,pclass_dummies_df],axis=1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

5.6 Parch and SibSp

#将家庭氛围大家庭小家庭也是用LabelEncoder进行对家庭人数进行分组
def family_size_category(family_size):
    if family_size <= 1:
        return 'Single'
    elif family_size <= 4:
        return 'Small_Family'
    else:
        return 'Large_Family'

combined_train_test['Family_Size'] = combined_train_test['Parch'] + combined_train_test['SibSp'] + 1
combined_train_test['Family_Size_Category'] = combined_train_test['Family_Size'].map(family_size_category)

le_family = LabelEncoder()
le_family.fit(np.array(['Single', 'Small_Family', 'Large_Family']))
combined_train_test['Family_Size_Category'] = le_family.transform(combined_train_test['Family_Size_Category'])

family_size_dummies_df = pd.get_dummies(combined_train_test['Family_Size_Category'],
                                        prefix=combined_train_test[['Family_Size_Category']].columns[0])
combined_train_test = pd.concat([combined_train_test, family_size_dummies_df], axis=1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

5.7 Age
因为Age项的缺失值较多,所以不能直接填充age的众数或者平均数。

常见的有两种对年龄的填充方式:一种是根据Title中的称呼,如Mr,Master、Miss等称呼不同类别的人的平均年龄来填充;一种是综合几项如Sex、Title、Pclass等其他没有缺失值的项,使用机器学习算法来预测Age。

这里我们使用后者来处理。以Age为目标值,将Age完整的项作为训练集,将Age缺失的项作为测试集。

#这里就降到了建模过程
from sklearn import ensemble
from sklearn import model_selection
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.ensemble import RandomForestRegressor

def fill_missing_age(missing_age_train, missing_age_test):
#训练集的筛选
    missing_age_X_train = missing_age_train.drop(['Age'], axis=1)
    missing_age_Y_train = missing_age_train['Age']
    missing_age_X_test = missing_age_test.drop(['Age'], axis=1)
#模型的建立以及训练
#这里使用了model_selectio调参神器设置多组参数对最优的参数进行选择然后进行模型训练
    # model 1  gbm
    gbm_reg = GradientBoostingRegressor(random_state=42)
    gbm_reg_param_grid = {'n_estimators': [2000], 'max_depth': [4], 'learning_rate': [0.01], 'max_features': [3]}
    gbm_reg_grid = model_selection.GridSearchCV(gbm_reg, gbm_reg_param_grid, cv=10, n_jobs=25, verbose=1, scoring='neg_mean_squared_error')
    gbm_reg_grid.fit(missing_age_X_train, missing_age_Y_train)
    print('Age feature Best GB Params:' + str(gbm_reg_grid.best_params_))
    print('Age feature Best GB Score:' + str(gbm_reg_grid.best_score_))
    print('GB Train Error for "Age" Feature Regressor:' + str(gbm_reg_grid.score(missing_age_X_train, missing_age_Y_train)))
    missing_age_test.loc[:, 'Age_GB'] = gbm_reg_grid.predict(missing_age_X_test)
    print(missing_age_test['Age_GB'][:4])

    # model 2 rf
    rf_reg = RandomForestRegressor()
    rf_reg_param_grid = {'n_estimators': [200], 'max_depth': [5], 'random_state': [0]}
    rf_reg_grid = model_selection.GridSearchCV(rf_reg, rf_reg_param_grid, cv=10, n_jobs=25, verbose=1, scoring='neg_mean_squared_error')
    rf_reg_grid.fit(missing_age_X_train, missing_age_Y_train)
    print('Age feature Best RF Params:' + str(rf_reg_grid.best_params_))
    print('Age feature Best RF Score:' + str(rf_reg_grid.best_score_))
    print('RF Train Error for "Age" Feature Regressor' + str(rf_reg_grid.score(missing_age_X_train, missing_age_Y_train)))
    missing_age_test.loc[:, 'Age_RF'] = rf_reg_grid.predict(missing_age_X_test)
    print(missing_age_test['Age_RF'][:4])

    # two models merge
    print('shape1', missing_age_test['Age'].shape, missing_age_test[['Age_GB', 'Age_RF']].mode(axis=1).shape)
    # missing_age_test['Age'] = missing_age_test[['Age_GB', 'Age_LR']].mode(axis=1)

#最后对两个模型求出来的参数进行求平均之后会对模型训练过程弄一个总结
    missing_age_test.loc[:, 'Age'] = np.mean([missing_age_test['Age_GB'], missing_age_test['Age_RF']])
    print(missing_age_test['Age'][:4])

    missing_age_test.drop(['Age_GB', 'Age_RF'], axis=1, inplace=True)

    return missing_age_test
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
#pandas对同列名进行填充
combined_train_test.loc[(combined_train_test.Age.isnull()), 'Age'] = fill_missing_age(missing_age_train, missing_age_test)
  • 1
  • 2

5.8 Ticket
将数字信息与字母信息分开将所有数字信息归为一类字母信息归为一类

#提取数字信息
combined_train_test['Ticket_Letter'] = combined_train_test['Ticket'].str.split().str[0]
combined_train_test['Ticket_Letter'] = combined_train_test['Ticket_Letter'].apply(lambda x: 'U0' if x.isnumeric() else x)
#使用factorize对字母进行数字化
combined_train_test['Ticket_Letter'] = pd.factorize(combined_train_test['Ticket_Letter'])[0]
  • 1
  • 2
  • 3
  • 4
  • 5

5.9 Cabin
因为Cabin项的缺失值确实太多了,我们很难对其进行分析,或者预测。所以这里我们可以直接将Cabin这一项特征去除。但通过上面的分析,可以知道,该特征信息的有无也与生存率有一定的关系,所以这里我们暂时保留该特征,并将其分为有和无两类。

combined_train_test.loc[combined_train_test.Cabin.isnull(), 'Cabin'] = 'U0'
combined_train_test['Cabin'] = combined_train_test['Cabin'].apply(lambda x: 0 if x == 'U0' else 1)
  • 1
  • 2

5.10特征相关性分析
提取特征并进行map图的绘制

Correlation = pd.DataFrame(combined_train_test[['Embarked','Sex','Title','Name_length','Family_Size',
                                                'Family_Size_Category','Fare','Fare_bin_id','Pclass',
                                                'Pclass_Fare_Category','Age','Ticket_Letter','Cabin']])
#主要是使用corrr()来计算相关性
colormap = plt.cm.viridis
plt.figure(figsize=(14,12))
plt.title('Pearson Correaltion of Feature',y=1.05,size=15)
sns.heatmap(Correlation.astype(float).corr(),linewidths=0.1,vmax=1.0,square=True,cmap=colormap,linecolor='white',annot=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

5.11 特征之间的数据分布图
这里建议不要使用kde图我电脑上运行不起来

g = sns.pairplot(combined_train_test[[u'Survived',u'Pclass',u'Sex',u'Age',u'Fare',u'Embarked',
                                      u'Family_Size',u'Title',u'Ticket_Letter']],hue='Survived',
                                      palette = 'seismic',size=1.2,diag_kind ='kde',diag_kws=
                                      dict(shade=True),plot_kws=dict(s=10))
g.set(xticklabels=[])
  • 1
  • 2
  • 3
  • 4
  • 5

5.12 输入模型之前处理
主要是丢弃无用的特征与正则化可能正则化不行也可能很好要通过具体尝试
5.12.1正则化

from sklearn import preprocessing
scale_age_fare = preprocessing.StandardScaler().fit(combined_train_test[['Age','Fare','Name_length']])
combined_train_test[['Age','Fare','Name_length']] = scale_age_fare.transform(combined_train_test[['Age','Fare','Name_length']])
  • 1
  • 2
  • 3

5.12.2丢弃无用的特征

combined_data_backup = combined_train_test

combined_train_test.drop(['PassengerId','Embarked','Sex','Name','Fare_bin_id','Pclass_Fare_Category',                          'Parch','SibSp','Family_Size_Category','Ticket'],axis=1,inplace=True)
  • 1
  • 2
  • 3

5.12.3 将训练数据和测试数据分开:

train_data = combined_train_test[:891]
test_data = combined_train_test[891:]
 
titanic_train_data_X = train_data.drop(['Survived'],axis=1)
titanic_train_data_Y = train_data['Survived']
titanic_test_data_X = test_data.drop(['Survived'],axis=1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6.模型融合及测试

模型融合的过程需要分几步来进行。
6.1 利用不同的模型来对特征进行筛选,选出较为重要的特征:(这段代码长度很长而且有些地方比较难懂难懂的我会标注出来)

from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
 
#作者定义了一个函数叫获取前几个重要的特征所传参数为训练X训练Y与前几个参数
def get_top_n_features(titanic_train_data_X,titanic_train_data_Y,top_n_features):
    
    #randomforest
    rf_est = RandomForestClassifier(random_state=0)
    rf_param_grid = {'n_estimators':[500],'min_samples_split':[2,3],'max_depth':[20]}
    rf_grid = model_selection.GridSearchCV(rf_est,rf_param_grid,n_jobs=25,cv=10,verbose=1)
    rf_grid.fit(titanic_train_data_X,titanic_train_data_Y)
    #打印出最佳参数
    print('Top N Features Best RF Params:' + str(rf_grid.best_params_))
    #最佳模型的分数
    print('Top N Features Best RF Score:' + str(rf_grid.best_score_))
    #模型训练出来的损失值
    print('Top N Features RF Train Score:' + str(rf_grid.score(titanic_train_data_X,titanic_train_data_Y)))
    #rf_grid.best_estimator_.feature_importances_可以给出参数重要性评价分数并对重要性进行排序
    feature_imp_sorted_rf = pd.DataFrame({'feature':list(titanic_train_data_X),
                                          'importance':rf_grid.best_estimator_.feature_importances_}).sort_values('importance',ascending=False)
     #提取出前多少需要的参数下面的做法跟上面都一样
    features_top_n_rf = feature_imp_sorted_rf.head(top_n_features)['feature']
    print('Sample 10 Feeatures from RF Classifier')
    print(str(features_top_n_rf[:10]))
    
    #AdaBoost
    ada_est = AdaBoostClassifier(random_state=0)
    ada_param_grid = {'n_estimators':[500],'learning_rate':[0.01,0.1]}
    ada_grid = model_selection.GridSearchCV(ada_est,ada_param_grid,n_jobs=25,cv=10,verbose=1)
    ada_grid.fit(titanic_train_data_X,titanic_train_data_Y)
    print('Top N Features Best Ada Params:' + str(ada_grid.best_params_))
    print('Top N Features Best Ada Score:' + str(ada_grid.best_score_))
    print('Top N Features Ada Train Score:' + str(ada_grid.score(titanic_train_data_X,titanic_train_data_Y)))
    feature_imp_sorted_ada = pd.DataFrame({'feature':list(titanic_train_data_X),
                                           'importance':ada_grid.best_estimator_.feature_importances_}).sort_values('importance',ascending=False)
    features_top_n_ada = feature_imp_sorted_ada.head(top_n_features)['feature']
    print('Sample 10 Features from Ada Classifier:')
    print(str(features_top_n_ada[:10]))
    
    #ExtraTree
    et_est = ExtraTreesClassifier(random_state=0)
    et_param_grid = {'n_estimators':[500],'min_samples_split':[3,4],'max_depth':[20]}
    et_grid = model_selection.GridSearchCV(et_est,et_param_grid,n_jobs=25,cv=10,verbose=1)
    et_grid.fit(titanic_train_data_X,titanic_train_data_Y)
    print('Top N Features Best ET Params:' + str(et_grid.best_params_))
    print('Top N Features Best DT Score:' + str(et_grid.best_score_))
    print('Top N Features ET Train Score:' + str(et_grid.score(titanic_train_data_X,titanic_train_data_Y)))
    feature_imp_sorted_et = pd.DataFrame({'feature':list(titanic_train_data_X),
                                          'importance':et_grid.best_estimator_.feature_importances_}).sort_values('importance',ascending=False)
    features_top_n_et = feature_imp_sorted_et.head(top_n_features)['feature']
    print('Sample 10 Features from ET Classifier:')
    print(str(features_top_n_et[:10]))
    
    # GradientBoosting
    gb_est = GradientBoostingClassifier(random_state=0)
    gb_param_grid = {'n_estimators':[500],'learning_rate':[0.01,0.1],'max_depth':[20]}
    gb_grid = model_selection.GridSearchCV(gb_est,gb_param_grid,n_jobs=25,cv=10,verbose=1)
    gb_grid.fit(titanic_train_data_X,titanic_train_data_Y)
    print('Top N Features Best GB Params:' + str(gb_grid.best_params_))
    print('Top N Features Best GB Score:' + str(gb_grid.best_score_))
    print('Top N Features GB Train Score:' + str(gb_grid.score(titanic_train_data_X,titanic_train_data_Y)))
    feature_imp_sorted_gb = pd.DataFrame({'feature':list(titanic_train_data_X),
                                          'importance':gb_grid.best_estimator_.feature_importances_}).sort_values('importance',ascending=False)
    features_top_n_gb = feature_imp_sorted_gb.head(top_n_features)['feature']
    print('Sample 10 Feature from GB Classifier:')
    print(str(features_top_n_gb[:10]))
    
    # DecisionTree
    dt_est = DecisionTreeClassifier(random_state=0)
    dt_param_grid = {'min_samples_split':[2,4],'max_depth':[20]}
    dt_grid = model_selection.GridSearchCV(dt_est,dt_param_grid,n_jobs=25,cv=10,verbose=1)
    dt_grid.fit(titanic_train_data_X,titanic_train_data_Y)
    print('Top N Features Bset DT Params:' + str(dt_grid.best_params_))
    print('Top N Features Best DT Score:' + str(dt_grid.best_score_))
    print('Top N Features DT Train Score:' + str(dt_grid.score(titanic_train_data_X,titanic_train_data_Y)))
    feature_imp_sorted_dt = pd.DataFrame({'feature':list(titanic_train_data_X),
                                          'importance':dt_grid.best_estimator_.feature_importances_}).sort_values('importance',ascending=False)
    features_top_n_dt = feature_imp_sorted_dt.head(top_n_features)['feature']
    print('Sample 10 Features from DT Classifier:')
    print(str(features_top_n_dt[:10]))
    
    # merge the three models
    #对3个数据进行纵向拼接再通过drop_duplicates()去除重复得到想要的结果
    features_top_n = pd.concat([features_top_n_rf,features_top_n_ada,features_top_n_et,features_top_n_gb,features_top_n_dt],ignore_index=True).drop_duplicates()
    features_importance = pd.concat([feature_imp_sorted_rf,feature_imp_sorted_ada,feature_imp_sorted_et,
                                     feature_imp_sorted_gb,feature_imp_sorted_dt],ignore_index=True)
    
    return features_top_n,features_importance
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

6.2 依据我们筛选出的特征重新构建训练集和测试集

feature_to_pick = 30
feature_top_n,feature_importance = get_top_n_features(titanic_train_data_X,titanic_train_data_Y,feature_to_pick)
titanic_train_data_X = pd.DataFrame(titanic_train_data_X[feature_top_n])
titanic_test_data_X = pd.DataFrame(titanic_test_data_X[feature_top_n])
  • 1
  • 2
  • 3
  • 4

6.2.1用可视化可以看出不同模型对特征之间的排列

rf_feature_imp = feature_importance[:10]
Ada_feature_imp = feature_importance[32:32+10].reset_index(drop=True)

# make importances relative to max importance
rf_feature_importance = 100.0 * (rf_feature_imp['importance'] / rf_feature_imp['importance'].max())
Ada_feature_importance = 100.0 * (Ada_feature_imp['importance'] / Ada_feature_imp['importance'].max())

# Get the indexes of all features over the importance threshold
rf_important_idx = np.where(rf_feature_importance)[0]
Ada_important_idx = np.where(Ada_feature_importance)[0]

# Adapted from http://scikit-learn.org/stable/auto_examples/ensemble/plot_gradient_boosting_regression.html
pos = np.arange(rf_important_idx.shape[0]) + .5

plt.figure(1, figsize = (18, 8))

plt.subplot(121)
plt.barh(pos, rf_feature_importance[rf_important_idx][::-1])
plt.yticks(pos, rf_feature_imp['feature'][::-1])
plt.xlabel('Relative Importance')
plt.title('RandomForest Feature Importance')

plt.subplot(122)
plt.barh(pos, Ada_feature_importance[Ada_important_idx][::-1])
plt.yticks(pos, Ada_feature_imp['feature'][::-1])
plt.xlabel('Relative Importance')
plt.title('AdaBoost Feature Importance')

plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

6.3模型融合
常见的模型融合方法有:Bagging、Boosting、Stacking、Blending。

6.3.1 Bagging
Bagging将多个模型,也就是基学习器的预测结果进行简单的加权平均或者投票。它的好处是可以并行地训练基学习器。Random Forest就用到了Bagging的思想。

6.3.2 Boosting
Boosting的思想有点像知错能改,每个基学习器是在上一个基学习器学习的基础上,对上一个基学习器的错误进行弥补。我们将会用到的AdaBoost,Gradient Boost就用到了这种思想。

6.3.3. Stacking
Stacking是用新的次学习器去学习如何组合上一层的基学习器。如果把Bagging看作是多个基分类器的线性组合,那么Stacking就是多个基分类器的非线性组合。Stacking可以将学习器一层一层地堆砌起来,形成一个网状的结构。 相比来说Stacking的融合框架相对前面二者来说在精度上确实有一定的提升,所以在下面的模型融合上,我们也使用Stacking方法。

6.3.4 Blending
Blending和Stacking很相似,但同时它可以防止信息泄露的问题。

Stacking框架融合:这里我们使用了两层的模型融合

Level 1使用了:Random Forest、AdaBoost、ExtraTrees、GBDT、Decision Tree、KNN、SVM,一共7个模型

Level 2使用了XGBoost,使用第一层预测的结果作为特征对最终的结果进行预测。

Level 1:

Stacking框架是堆叠使用基础分类器的预测作为对二级模型的训练的输入。然而,我们不能简单地在全部训练数据上训练基本模型,产生预测,输出用于第二层的训练。如果我们在Train Data上训练,然后在Train Data上预测,就会造成标签。为了避免标签,我们需要对每个基学习器使用K-fold,将Kge模型对Valid Set的预测结果拼起来,作为下一层学习器的输入。

所以这里我们建立输出fold预测方法:

#很多同学可能交叉验证这里代码看不懂下面给出了注释
from sklearn.model_selection import KFold
 
# Some useful parameters which will come in handy later on
ntrain = titanic_train_data_X.shape[0]
ntest = titanic_test_data_X.shape[0]
SEED = 0 #for reproducibility
NFOLDS = 7 # set folds for out-of-fold prediction
kf = KFold(n_splits = NFOLDS,random_state=SEED,shuffle=False)
 
def get_out_fold(clf,x_train,y_train,x_test):
    oof_train = np.zeros((ntrain,))
    oof_test = np.zeros((ntest,))
    
    oof_test_skf = np.empty((NFOLDS,ntest))
    #这里enumerate是交叉验证的索引
    #将交叉验证数据集分为多种会给出他们的索引
    for i, (train_index,test_index) in enumerate(kf.split(x_train)):
        x_tr = x_train[train_index]
        y_tr = y_train[train_index]
        x_te = x_train[test_index]
        
        clf.fit(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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

这里选择了7个模型并且要对其进行传参

from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
 
rf = RandomForestClassifier(n_estimators=500,warm_start=True,max_features='sqrt',max_depth=6,min_samples_split=3,min_samples_leaf=2,n_jobs=-1,verbose=0)
 
ada = AdaBoostClassifier(n_estimators=500,learning_rate=0.1)
 
et = ExtraTreesClassifier(n_estimators=500,n_jobs=-1,max_depth=8,min_samples_leaf=2,verbose=0)
 
gb = GradientBoostingClassifier(n_estimators=500,learning_rate=0.008,min_samples_split=3,min_samples_leaf=2,max_depth=5,verbose=0)
 
dt = DecisionTreeClassifier(max_depth=8)
 
knn = KNeighborsClassifier(n_neighbors=2)
 
svm = SVC(kernel='linear',C=0.025)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

数据集全部转成values的形式进行传参

x_train = titanic_train_data_X.values   #Creates an array of the train data
x_test = titanic_test_data_X.values   #Creates an array of the test data
y_train = titanic_train_data_Y.values
  • 1
  • 2
  • 3
rf_oof_train,rf_oof_test = get_out_fold(rf,x_train,y_train,x_test)  # Random Forest
ada_oof_train,ada_oof_test = get_out_fold(ada,x_train,y_train,x_test)  # AdaBoost
et_oof_train,et_oof_test = get_out_fold(et,x_train,y_train,x_test)  # Extra Trees
gb_oof_train,gb_oof_test = get_out_fold(gb,x_train,y_train,x_test)  # Gradient Boost
dt_oof_train,dt_oof_test = get_out_fold(dt,x_train,y_train,x_test)  #Decision Tree
knn_oof_train,knn_oof_test = get_out_fold(knn,x_train,y_train,x_test)  # KNeighbors
svm_oof_train,svm_oof_test = get_out_fold(svm,x_train,y_train,x_test)  # Support Vector
 #rf_oof_train为原数据集验证结果 rf_oof_test 测试数据集验证结果
print("Training is complete")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
#将得到的数据集进行纵拼
x_train = np.concatenate((rf_oof_train,ada_oof_train,et_oof_train,gb_oof_train,dt_oof_train,knn_oof_train,svm_oof_train),axis=1)

x_test =np.concatenate((rf_oof_test,ada_oof_test,et_oof_test,gb_oof_test,dt_oof_test,knn_oof_test,svm_oof_test),axis=1)
  • 1
  • 2
  • 3
  • 4
#使用xg_boost对训练上次训练的结果组成的数据集再次进行训练
from xgboost import XGBClassifier
 
gbm = XGBClassifier(n_estimators=200,max_depth=4,min_child_weight=2,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)
StackingSubmission = pd.DataFrame({'PassengerId':PassengerId,'Survived':predictions})
StackingSubmission.to_csv('StackingSubmission.csv',index=False,sep=',')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7.模型验证:学习曲线(对模型的验证)

在我们对数据不断地进行特征工程,产生的特征越来越多,用大量的特征对模型进行训练,会使我们的训练集拟合得越来越好,但同时也可能会逐渐丧失泛化能力,从而在测试数据上表现不佳,发生过拟合现象。 当然我们建立的模型可能不仅在预测集上表现不好,也很可能是因为在训练集上的表现不佳,处于欠拟合状态。 下图是在吴恩达老师的机器学习课程上给出的四种学习曲线:
在这里插入图片描述
上面红线代表test error(Cross-validation error),蓝线代表train error。这里我们也可以把错误率替换为准确率,那么相应曲线的走向就应该是上下颠倒的,(score=1-error)。

注意我们的图中是error曲线。

左上角是最优情况,随着样本数的增加,train error虽然有一定的增加,但是test error却有很明显的降低;

右上角是最差情况,train error很大,模型并没有从特征 中学习到什么,导致test error非常大,模型几乎无法预测数据,需要去寻找数据本身和训练阶段的原因;

左下角是high variance,train error虽然较低,但是模型产生了过拟合,缺乏泛化能力,导致test error很高;

右下角是high bias的情况,train error很高,这时需要去调整模型的参数,减小train error。

所以我们通过学习曲线观察模型处于什么样的状态。从而决定对模型进行如何的操作。当然,我们把验证放到最后,并不是这一步在最后去做。对于我们的Stacking框架中第一层的各个基学习器我们都应该对其学习曲线进行观察,从而去更好地调节超参数,进而得到更好的最终结果。构建绘制学习曲线的函数:

rom sklearn.learning_curve import learning_curve
 
def plot_learning_curve(estimator,title,X,y,ylim=None,cv=None,
                        n_jobs=1,train_sizes=np.linspace(.1,1.0,5),verbose=0):
    """
    Generate a simple plot of the test and training learning curve.
    
    Parameters
    -------------
    estimator:object type that implents the "fit" and "predict" methods
    An object of that type which is cloned for each validation.
    
    title:string
    Title for the chart.
    
    X:array-like,shape(n_samples,n_features)
    Training vector,where n_samples is the number of samples and n_features is 
    the number of features.
    
    y:array-like,shape(n_samples) or (n_samples,n_features),optional
    Target relative to X for classification or regression;
    None for unsupervised learning.
    
    ylim:tuple,shape(ymin,ymax),optional
    Defines minimum and maximum yvalues plotted.
    
    cv:integer,cross-validation generator,optional
    If an integer is passed,it is the number of folds(defaults to 3).
    Specific cross-validation objects can be passed,see
    sklearn.cross_validation module for the list of possible objects
    
    n_jobs:integer,optional
    Number of jobs to run in parallel(default 1).
    """
    plt.figure()
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    train_sizes,train_scores,test_scores = learning_curve(estimator,X,y,cv=cv,
                                                          n_jobs=n_jobs,train_sizes=train_sizes)
    train_scores_mean = np.mean(train_scores,axis=1)
    train_scores_std = np.std(train_scores,axis=1)
    test_scores_mean = np.mean(test_scores,axis=1)
    test_scores_std = np.std(test_scores,axis=1)
    plt.grid()
    
    plt.fill_between(train_sizes,train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std,alpha=0.1,color='r')
    plt.fill_between(train_sizes,test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std,alpha=0.1,color='g')
    plt.plot(train_sizes,train_scores_mean,'o-',color="r",label="Training score")
    plt.plot(train_sizes,test_scores_mean,'o-',color="g",label="Cross-validation score")
    
    plt.legend(loc="best")
    return plt
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
X = x_train
Y = y_train
 
# RandomForest
rf_parameters = {'n_jobs':-1,'n_estimators':500,'warm_start':True,'max_depth':6,
                 'min_samples_leaf':2,'max_features':'sqrt','verbose':0}
 
# AdaBoost
ada_parameters = {'n_estimators':500,'learning_rate':0.1}
 
# ExtraTrees
et_parameters = {'n_jobs':-1,'n_estimators':500,'max_depth':8,'min_samples_leaf':2,'verbose':0}
 
# GradientBoosting
gb_parameters = {'n_estimators':500,'max_depth':5,'min_samples_leaf':2,'verbose':0}
 
# DecisionTree
dt_parameters = {'max_depth':8}
 
# KNeighbors
knn_parameters = {'n_neighbors':2}
 
# SVM
svm_parameters = {'kernel':'linear','C':0.025}
 
# XGB
gbm_parameters = {'n_estimators':2000,'max_depth':4,'min_child_weight':2,'gamma':0.9,'subsample':0.8,
                  'colsample_bytree':0.8,'objective':'binary:logistic','nthread':-1,'scale_pos_weight':1}
 
 
title = "Learning Curves"
plot_learning_curve(RandomForestClassifier(**rf_parameters),title,X,Y,cv=None,n_jobs=4,
                    train_sizes=[50,100,150,200,250,350,400,450,500])
plt.show()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/718097
推荐阅读
相关标签
  

闽ICP备14008679号