【Kaggle入门练习赛】泰坦尼克之灾

首先要说明的是,学习的思路全部来自于这篇文章

https://blog.csdn.net/han_xiaoyang/article/details/49797143

写的超级好!!疯狂打call!!
我自己横向地总结了以下内容如下:

第零部分 数据可视化

工具:

import matplotlib.pyplot as plt

用到的方法:

图片句柄:fig = plt.figure()

fig.set(alpha) 设置图片透明度

在一张图里画多个子图的方法:

  1. ax=plt.subplot2grid((a,b),(c,d)) 在创建了figure之后,对于这个figure,它里面有a*b个图,我们马上要操作的这个图,是第c行的第d个图(注意c,d的起点是0)。
  2. ax1=fig.add_subplot(x,y,z), 在创建了figure之后,对于这个figure,它里面有x*y个图,我们马上要操作的这个图,是顺着往下数的第z个。

两种创建方式没有本质区别

plt.title plt.ylabel plt.xlabel 设置子图的标题,坐标轴

ax. set_xticklabels(list,rotation = 0) 设置子图坐标轴的刻度,list是列表,rotation设置刻度显示方式

ax.legend() 设置图例

fig.tight_layout() 设置子图不交叉

pandas的数据都可以直接加plot作图:

df.plot(kind='bar', stacked=True) 直接对dataframe进行绘图,每一行为图中的一个柱子,数值型的列显示出在这一行中所有列所占的比例

Series.plot(kind='bar', stacked=True) 直接对Series进行绘图,每一索引为图中的一个柱子,柱子的高度是索引对应的列值

Series.plot(kind='kde') 对Series中数据的分布进行密度拟合,可以查看列中数据的分布

plt.scatter(x,y) 对x,y序列作散点图

plt.grid(b=True, which='major', axis='y') 对y画网格

plt.show() 显示图形

 

第一部分 认识数据

  1. 对数据进行简单的统计

统计列的缺失情况(df.info())

统计每列的平均值(df.mean())

返回一个每行为0 or 1的索引,判断该行的指定列是否为空值(pd.notnull(df.column))

例:

按Cabin有无看获救情况

Survived_cabin = data_train.Survived[pd.notnull(data_train.Cabin)].value_counts()

Survived_nocabin = data_train.Survived[pd.isnull(data_train.Cabin)].value_counts()

pd.isnull(data_train.Cabin)和data_train.Cabin.isnull()是一样的效果

统计各个数据的出现次数(Series.value_counts()或df.column.counts()),返回值是Series,可以直接用上面说的plot作图

泰坦尼克之灾中,可以统计的包括:

获救情况

乘客等级分布

乘客年龄分布(年龄由于数目太多,考虑转为密度拟合分布)

各等级的乘客年龄分布

等等

 

 

  1. 对属性和数据的关系进行简单的统计

基本思路为统计不同特征中,标签值为0或1的样本个数。可以直观地看出这个特征是否是影响标签值的重要原因。

属性和数据的关系,主要可以分为下面两种:

(1)每个属性中获救的人的分布

泰坦尼克之灾:

#对Pclass这个特征,每一个Pclass中获救的人的比例分布,Pclass只有123三种

Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts()

Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()

df=pd.DataFrame({u'获救':Survived_1, u'未获救':Survived_0})

df.plot(kind='bar', stacked=True)

(2)获救的人中每个属性的分布

泰坦尼克之灾:

#对年龄这个特征,被救/没有被救的人中年龄的分布,年龄有非常多的情况

data_train.Age[data_train.Survived == 0].plot(kind='kde')

data_train.Age[data_train.Survived == 1].plot(kind='kde')

plt.xlabel(u"年龄")# plots an axis lable

plt.ylabel(u"密度")

plt.title(u"获救的人的年龄分布")

plt.legend((u'未获救',u'获救'),loc='best') # sets our legend for our graph.

 

泰坦尼克之灾中,可以统计的包括:

不同船舱等级、不同性别、不同码头登船、是否有cabin等特征中,获救人的分布;

获救的人中,不同年龄(kde)、不同性别(bar)等的分布

 

 

 

第二部分 数据预处理

也就是我们通常说的【特征工程】

  1. 处理缺失数据

如果缺值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,可能反倒带入noise,影响最后的结果了

如果缺值的样本适中,而该属性非连续值特征属性(比如说类目属性),那就把NaN作为一个新类别,加到类别特征中

如果缺值的样本适中,而该属性为连续值特征属性,有时候我们会考虑给定一个step,然后把它离散化,之后把NaN作为一个type加到属性类目中。

有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上,如使用scikit-learn中的RandomForest模块。

在这个案例里,选择已有的数值型特征输入随机森林中,用已知年龄的训练数据拟合出未知年龄的那些人。

用到的方法:

df.as_matrix 将dataframe中的值拿出来组成一个array矩阵

然后注意df.loc[x,y]中作为行索引的x可以是一个列向量(Series),只要等号左右两边维数对应即可。

Cabin的处理就按照有无来进行二元判断。

 

  1. 字段型数据数值化

这里使用pd.get_dummies函数,用于对每列每个字段的每个值生成对应的0-1列,返回值是一个dataframe,需要和原训练数据merge

 

  1. 数据归一化

如果大家了解逻辑回归与梯度下降的话,会知道,各属性值之间scale差距太大,将对收敛速度造成几万点伤害值!甚至不收敛!

乘客id显然是垃圾数据,所以需要对age和fare做归一化,让所有的特征差不多在一个scale中。

特征工程那篇文章中提到了3种不同的标准化方法,都可以用。

按理说还应该有一种特征选择和降维的模块,但是这里没有用,不知道为什么,反正我们直接看下一部分。

 

第三部分 回归建模

df.filter(regex = str),str是正则表达式,可以用来筛选dataframe中行、列、数据,具体使用方法可以参考help方法。

这里的模型用linear_model.LogisticRegression来做,训练和测试都相当直观,注意测试集需要做和训练集一样的数据预处理。

 

第四部分 系统优化

  1. 交叉验证

由于不知道测试集的标签,因此交叉验证是唯一评估我们算法好坏的方法。

我们用scikit-learn的cross_validation来帮我们完成小数据集上的这个工作。

函数:

split_train,split_cv = model_selection.train_test_split(data_train,test_size = 0.3,random_state = 0)

这个方法用于将训练集和数据集分开,返回的其实是就训练集打乱后随机按照比例分成两部分。

  1. 模型系数关联分析

通过查看交叉验证中预测错误的那些项,判断特征应该如何拟合。

泰坦尼克之灾的案例中,根据教程的指导,可以从下面这些角度来优化:

 

  1. 学习率曲线

学习率曲线主要用于判断当前模型的拟合现状。当模型表现不佳时,对于过拟合和欠拟合两种情况,会有不同的处理方式。

过拟合和欠拟合的学习率曲线通常长这样:

(参考https://blog.csdn.net/geduo_feng/article/details/79547554

学习率的绘制也使用scikit-learn里面的learning_curve,同时官方还提供了对应的代码例程。

到目前为止撸出来的baseline的学习率曲线长这样:

目前的曲线看来,我们的model并不处于overfitting的状态(overfitting的表现一般是训练集上得分高,而交叉验证集上要低很多,中间的gap比较大)。因此我们可以再做些feature engineering的工作,添加一些新产出的特征或者组合特征到模型中。

 

第五部分 模型融合

严格地说这应该属于系统优化,但是因为它被称为数据挖掘领域内的大杀器,为了体现对它的重视,我们把它单独分成一部分。

模型融合的基本思想是投票。这个投票可以用多种方式实现,比如我们选择不同的模型,来对同一份数据进行投票,或者我们把同一份数据分成许多份,分别用来训练相同的模型,然后对测试机进行投票,总之你能想到的都可以用,韩信点兵多多益善嘛。我理解组合分类器就类似我们所说的boosting,而组合数据集则差不多是bagging。

这里选择用后者。每次取训练集的一个subset,做训练,这样,我们虽然用的是同一个机器学习算法,但是得到的模型却是不一样的;同时,因为我们没有任何一份子数据集是全的,因此即使出现过拟合,也是在子训练集上出现过拟合,而不是全体数据上,这样做一个融合,可能对最后的结果有一定的帮助。对,这就是常用的Bagging。

我们用scikit-learn里面的Bagging来完成上面的思路

 

总结:第一次从头到尾写(chao)一个小的机器学习问题,感觉还是受益匪浅的,跟完了这篇教程之后,以后还希望自己可以加入一些优化的思路。

在看了这些理论分析之后,我充满雄心壮志地开始撸新特征。

首先,在观察bad_cases后,发现多数预测错的案例都是【女性,低等舱,没获救判断成了获救】

所以考虑将女性&三等舱作为一个融合特征来预测。折腾了半天,好不容易弄完了,发现反而预测准确率变低了……

0.76→0.75

为什么会出现这样的情况呢?回顾之前画的属性特征图,可以看到对于坐低等舱的女性,她们的获救率是这样的。

其实在第一部分就应该看到,女性&低级舱这一属性,其实获救没获救是差不多的,换句话说这是个废物属性,甚至还带来了一些噪声的效果。bad_cases里的是幸存者偏差而已……

没关系没关系,一回生二回熟。

我们可以看看别的特征嘛,比如年龄。对于年龄来说,我觉得把它作为一个连续属性是不合适的,不信我们来看看获救的年龄曲线。

我觉得可以把年龄按照段来划分,比如可以明显的看出来小孩获救率高,那就尝试一下以10岁为分界线把年龄特征二元化!我真棒!

于是我兴冲冲地提交了预测结果。

???

怎么预测结果里还有2了?说好的二元分类呢?

我回去查看代码的时候发现,原作者给的源代码中有一个地方可能可以改进一下,也就是这里

通过列的顺序来划分标签和特征,这样当我对列进行增减时,就可能改变标签列的位置,比如在刚才的问题里,原来是标签的第一列变成了Pclass。私以为更好的方法应该是采用DataFrame中的filter方法。

修正这个bug之后再次兴冲冲地提交。

0.76→0.75

只是从学习率曲线来看,这个真不是过拟合吗?

来来来改成L2范数。

很好,这次回到了baseline水平。

加上bagging之后可以稍微好一丢丢。

原作者说最好的结果是在『Survived~C(Pclass)+C(Title)+C(Sex)+C(Age_bucket)+C(Cabin_num_bucket)Mother+Fare+Family_Size』下取得的。

你问我怎么不试一下?

我今天在kaggle上的提交次数用完了……

目前看来,感觉自己还是经验太浅,不应该闭着眼睛乱搞,而应该多去看看别人的kernels,回头再慢慢优化自己的代码。加油加油。

上面用到的全部代码:

# -*- coding: utf-8 -*-
"""
Created on Mon Jan 21 19:21:38 2019

@author: xuefei
"""
import pandas as pd #数据分析 
import numpy as np #科学计算 
from pandas import Series,DataFrame 
import matplotlib.pyplot as plt 

data_train = pd.read_csv("D:\\学习\\研一\\数据挖掘\\kaggle入门\\练习赛\\泰坦尼克之灾\\train.csv",engine='python')

#==============================================================================
# ##########################################对数据本身的特性统计################################################
# 
# fig = plt.figure() 
# fig.set(alpha=0.2) # 图像透明度,无所谓
# 
# plt.subplot2grid((2,3),(0,0)) # 在一张大图里分列几个小图 
# data_train.Survived.value_counts().plot(kind='bar')# 柱状图 
# plt.title(u"获救情况 (1为获救)") # 标题 
# plt.ylabel(u"人数") 
# 
# ax1 = plt.subplot2grid((2,3),(0,1))
# data_train.Pclass.value_counts().plot(kind="bar")
# plt.ylabel(u"人数")
# plt.title(u"乘客等级分布")
# 
# 
# plt.subplot2grid((2,3),(0,2)) 
# #散点图
# plt.scatter(data_train.Survived, data_train.Age) 
# plt.ylabel(u"年龄") # 设定纵坐标名称 
# plt.grid(b=True, which='major', axis='y') 
# plt.title(u"按年龄看获救分布 (1为获救)")
# 
# plt.subplot2grid((2,3),(1,0), colspan=2) 
# data_train.Age[data_train.Pclass == 1].plot(kind='kde') 
# data_train.Age[data_train.Pclass == 2].plot(kind='kde') 
# data_train.Age[data_train.Pclass == 3].plot(kind='kde') 
# plt.xlabel(u"年龄")# plots an axis lable 
# plt.ylabel(u"密度") 
# plt.title(u"各等级的乘客年龄分布") 
# plt.legend((u'头等舱', u'2等舱',u'3等舱'),loc='best') # sets our legend for our graph.
# 
# plt.subplot2grid((2,3),(1,2))
# data_train.Embarked.value_counts().plot(kind='bar')
# plt.title(u"各登船口岸上船人数")
# plt.ylabel(u"人数")  
# 
# 
# #设置图表不交叉
# fig.tight_layout()
# 
# plt.show()
#==============================================================================





#==============================================================================
# ##############################################属性与获救结果的关联统计####################################################
# 
# 
# 
# #每一个船舱中,获救的人的比例分布
# fig = plt.figure() 
# fig.set(alpha=0.2) # 设定图表颜色alpha参数 
# Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts() 
# Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()
# df=pd.DataFrame({u'获救':Survived_1, u'未获救':Survived_0}) 
# #直接对df作图,可以画出每行对应列的分布比例,列是数值
# df.plot(kind='bar', stacked=True) 
# plt.title(u"各乘客等级的获救情况") 
# plt.xlabel(u"乘客等级") 
# plt.ylabel(u"人数") 
# plt.show()
# 
# #==============================================================================
# # #获救的人中,男女的比例分布
# # fig = plt.figure() 
# # fig.set(alpha=0.2) # 设定图表颜色alpha参数 
# # Survived_m = data_train.Survived[data_train.Sex == 'male'].value_counts()  
# # Survived_f = data_train.Survived[data_train.Sex == 'female'].value_counts() 
# # df=pd.DataFrame({u'男性':Survived_m, u'女性':Survived_f}) 
# # df.plot(kind='bar', stacked=True) 
# # plt.title(u"按性别看获救情况") 
# # plt.xlabel(u"性别") 
# # plt.ylabel(u"人数") 
# # plt.show()
# #==============================================================================
# 
# #不同性别的人中,获救的比例分布
# fig = plt.figure()
# fig.set(alpha = 0.2)
# Survived_0 = data_train.Sex[data_train.Survived == 0].value_counts() 
# Survived_1 = data_train.Sex[data_train.Survived == 1].value_counts()
# df = pd.DataFrame({u'获救':Survived_1, u'未获救':Survived_0})
# df.plot(kind = 'bar',stacked = True)
# plt.title(u"不同性别的获救情况") 
# plt.xlabel(u"性别") 
# plt.ylabel(u"人数") 
# plt.show()
# 
# fig=plt.figure()
# plt.xticks([])
# plt.yticks([])
# fig.set(alpha=0.2) # 设置图像透明度,无所谓
# plt.title(u"根据舱等级和性别的获救情况")
# 
# 
# 
# #性别+舱级的联合统计
# ax1=fig.add_subplot(221) 
# data_train.Survived[data_train.Sex == 'female'][data_train.Pclass != 3].value_counts().plot(kind='bar', label="female highclass", color='b') 
# ax1.set_xticklabels([u"获救", u"未获救"], rotation=0) 
# ax1.legend([u"女性/高级舱"], loc='lower center')
# 
# 
# ax2=fig.add_subplot(222) 
# data_train.Survived[data_train.Sex == 'female'][data_train.Pclass == 3].value_counts().plot(kind='bar', label="female highclass", color='b') 
# ax2.set_xticklabels([u"获救", u"未获救"], rotation=0) 
# plt.legend([u"女性/低级舱"], loc='lower center')
# 
# 
# ax3=fig.add_subplot(223) 
# data_train.Survived[data_train.Sex == 'male'][data_train.Pclass != 3].value_counts().plot(kind='bar', label="female highclass", color='b') 
# ax3.set_xticklabels([u"获救", u"未获救"], rotation=0) 
# plt.legend([u"男性/高级舱"], loc='lower center')
# 
# 
# ax4=fig.add_subplot(224) 
# data_train.Survived[data_train.Sex == 'female'][data_train.Pclass == 3].value_counts().plot(kind='bar', label="female highclass", color='b') 
# ax4.set_xticklabels([u"获救", u"未获救"], rotation=0) 
# plt.legend([u"男性/低级舱"], loc='lower center')
# 
# fig.tight_layout()
# plt.show()
# 
# 
# 
# 
# 
# #不同码头登船的人的分布
# fig = plt.figure() 
# fig.set(alpha=0.2) # 设定图表颜色alpha参数 
# Survived_0 = data_train.Embarked[data_train.Survived == 0].value_counts() 
# Survived_1 = data_train.Embarked[data_train.Survived == 1].value_counts()
# df=pd.DataFrame({u'获救':Survived_1, u'未获救':Survived_0}) 
# #直接对df作图,可以画出每行对应列的分布比例,列是数值
# df.plot(kind='bar', stacked=True) 
# plt.title(u"各码头登船的人的获救情况") 
# plt.xlabel(u"码头代号") 
# plt.ylabel(u"人数") 
# plt.show()
# 
# 
# #==============================================================================
# # #获救和没有获救的人中各码头的分布
# # fig = plt.figure()
# # fig.set(alpha = 0.2)
# # Survived_s = data_train.Survived[data_train.Embarked == 'S'].value_counts()
# # Survived_c = data_train.Survived[data_train.Embarked == 'C'].value_counts()
# # Survived_q = data_train.Survived[data_train.Embarked == 'Q'].value_counts()
# # df=pd.DataFrame({u'S码头':Survived_s, u'C码头':Survived_c,u'Q码头':Survived_q}) 
# # df.plot(kind='bar', stacked=True) 
# # plt.title(u"各码头登船的人的获救情况") 
# # plt.xlabel(u"获救情况") 
# # plt.ylabel(u"人数") 
# # plt.show()
# #==============================================================================
# 
# 
# fig = plt.figure() 
# fig.set(alpha=0.2) # 设定图表颜色alpha参数 
# #注意了,下面这两个函数可以筛选中dataframe中为/不为null的行
# Survived_cabin = data_train.Survived[pd.notnull(data_train.Cabin)].value_counts() 
# Survived_nocabin = data_train.Survived[pd.isnull(data_train.Cabin)].value_counts() 
# df=pd.DataFrame({u'有':Survived_cabin, u'无':Survived_nocabin}).transpose() 
# df.plot(kind='bar', stacked=True) 
# plt.title(u"按Cabin有无看获救情况") 
# plt.xlabel(u"Cabin有无") 
# plt.ylabel(u"人数") 
# plt.show()
# 
# #获救的人中的年龄分布
# #获救的人中,男女的比例分布
# fig = plt.figure() 
# fig.set(alpha=0.2) # 设定图表颜色alpha参数 
# data_train.Age[data_train.Survived == 0].plot(kind='kde') 
# data_train.Age[data_train.Survived == 1].plot(kind='kde')
# plt.xlabel(u"年龄")# plots an axis lable 
# plt.ylabel(u"密度") 
# plt.title(u"获救的人的年龄分布") 
# plt.legend((u'未获救',u'获救'),loc='best') # sets our legend for our graph.
# 
#==============================================================================




#######################################简单数据预处理############################################




#处理缺失数据
from sklearn.ensemble import RandomForestRegressor

#处理年龄属性:用随机森林拟合
def set_Missing_Ages(df):
    #只用有数值的这些列来做预测
    age_df = df[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]    
    known_age = age_df[pd.notnull(age_df.Age)].as_matrix()
    unknown_age = age_df[pd.isnull(age_df.Age)]
    unknown_age.drop('Age', 1,inplace = True)
    unknown_age = unknown_age.as_matrix()   
    #用随机森林进行拟合
    #这篇文章讲了参数选择的事情https://www.cnblogs.com/harvey888/p/6512312.html,具体怎么选我也不知道,先抄一个吧
    rfr = RandomForestRegressor(random_state = 0,n_estimators = 2000,n_jobs = -1)
    rfr.fit(known_age[:,1:],known_age[:,0])
    predictAges = rfr.predict(unknown_age)
    df.loc[pd.isnull(age_df.Age),'Age'] = predictAges    
    return rfr,df


#处理cabin:用有没有来近似处理
def set_Cabin_Type(df):
    df.loc[df.Cabin.notnull(),'Cabin'] = 'Yes'
    df.loc[df.Cabin.isnull(),'Cabin'] = 'No'
    return df


#处理非数值型数据
def dumies(df):
    dummies_Cabin = pd.get_dummies(df['Cabin'], prefix= 'Cabin') 
    dummies_Embarked = pd.get_dummies(df['Embarked'], prefix= 'Embarked') 
    dummies_Sex = pd.get_dummies(df['Sex'], prefix= 'Sex') 
    dummies_Pclass = pd.get_dummies(df['Pclass'], prefix= 'Pclass') 
    df = pd.concat([df, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass], axis=1) 
    df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True)
    return df

rfr,data_train = set_Missing_Ages(data_train)
data_train = set_Cabin_Type(data_train)
data_train = dumies(data_train)
    
#把数据不同特征的scale归到差不多的范围里
import sklearn.preprocessing as preprocessing 
from sklearn.preprocessing import StandardScaler


def scale(df):
    #df['Age'] = StandardScaler().fit_transform(df['Age'].values.reshape(-1, 1))
    df['Fare'] = StandardScaler().fit_transform(df['Fare'].values.reshape(-1, 1))
    return df

data_train = scale(data_train)




#########################################################################################
#########################################################################################
###############################下面我要开始自己撸特征了####################################
#==============================================================================
# #我觉得可以把女性和三等舱融合一下,因为bad_cases里没有获救的女性基本都是三等舱里的
# data_train = pd.concat([data_train, pd.DataFrame(columns=['Sex_Pclass'],dtype = np.float)])
# data_train.loc[(data_train.Sex_female == 1)&(data_train.Pclass_3 == 1).values,'Sex_Pclass'] = 1
# data_train.loc[data_train.Sex_Pclass.isnull(),'Sex_Pclass'] = 0
# #data_train=pd.DataFrame(data_train,dtype=np.float)
# 好的,事实证明并没什么乱用
#==============================================================================
#那还可以试试把age离散化一下,把它按照10岁、40岁划分成3段
#==============================================================================
# data_train.loc[data_train.Age < 10,'Age'] = 0
# data_train.loc[(data_train.Age >= 10) & (data_train.Age < 40) ,'Age'] = 1
# data_train.loc[data_train.Age >= 40,'Age'] = 2
#==============================================================================
data_train.loc[data_train.Age < 10,'Age'] = 0
data_train.loc[data_train.Age >= 10,'Age'] = 1



dummies_Age = pd.get_dummies(data_train['Age'], prefix= 'Age') 
data_train = pd.concat([data_train, dummies_Age], axis=1) 
data_train.drop(['Age'], axis=1, inplace=True)




#########################################################################################
#########################################################################################







######################################逻辑回归建模#######################################
from sklearn import linear_model

train_df = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np = train_df.as_matrix()

#逻辑斯蒂回归参数说明https://blog.csdn.net/jark_/article/details/78342644
clf = linear_model.LogisticRegression(C = 1.0,penalty = 'l1',tol = 1e-6)
#clf.fit(train_np[:,:-1],train_np[:,-1].astype('int'))
clf.fit(train_np[:,1:],train_np[:,0])

#######################################预测##############################################
data_test = pd.read_csv("D:\\学习\\研一\\数据挖掘\\kaggle入门\\练习赛\\泰坦尼克之灾\\test.csv",engine='python')
#一个预处理,放在这里是因为测试数据里有nan而训练数据里没有
data_test.loc[data_test.Fare.isnull(),'Fare'] = 0
#然后对test数据进行一样一样的预处理
#一个是对缺失数据拟合,这里采用训练集中的随机森林,不用重新训练随机森林
age_df = data_test[['Age','Fare', 'Parch', 'SibSp', 'Pclass']] 
unknown_age = age_df[pd.isnull(age_df.Age)]
unknown_age.drop('Age', 1,inplace = True)
unknown_age = unknown_age.as_matrix() 
predictAges = rfr.predict(unknown_age)
data_test.loc[pd.isnull(age_df.Age),'Age'] = predictAges    
#对cabin进行有无的判定
data_test = set_Cabin_Type(data_test)
#对字段型数据数值化
data_test = dumies(data_test)
#把特别大的特征归一化
data_test = scale(data_test)
#==============================================================================
# #增加一个特征
# data_test = pd.concat([data_test, pd.DataFrame(columns=['Sex_Pclass'])])
# data_test.loc[(data_test.Sex_female == 1)&(data_test.Pclass_3 == 1).values,'Sex_Pclass'] = 1
# data_test.loc[data_test.Sex_Pclass.isnull(),'Sex_Pclass'] = 0
# data_test=pd.DataFrame(data_test,dtype=np.float)
#==============================================================================
#把年龄分段
#==============================================================================
# data_test.loc[data_test.Age < 10,'Age'] = 0
# data_test.loc[(data_test.Age >= 10) & (data_test.Age < 40) ,'Age'] = 1
# data_test.loc[data_test.Age >= 40,'Age'] = 2
#==============================================================================
data_test.loc[data_test.Age < 10,'Age'] = 0
data_test.loc[data_test.Age >= 10,'Age'] = 1


dummies_Age = pd.get_dummies(data_test['Age'], prefix= 'Age') 
data_test = pd.concat([data_test, dummies_Age], axis=1) 
data_test.drop(['Age'], axis=1, inplace=True)





test_df = data_test.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
#这句话没有也行,主要是为了跟上面的对称,上面的要转化成array多半是为了切分特征和标签
test_np = test_df.as_matrix()
predictions = clf.predict(test_np)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].astype(np.int32),'Survived':predictions.astype(np.int32)})
result.to_csv("D:\\学习\\研一\\数据挖掘\\kaggle入门\\练习赛\\泰坦尼克之灾\\logistic_regression_predictions.csv", index=False)



######################################交叉验证###########################################
from sklearn import model_selection
split_train,split_cv = model_selection.train_test_split(data_train,test_size = 0.5,random_state = 0)
train_df = split_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6)
clf.fit(train_df.as_matrix()[:,1:], train_df.as_matrix()[:,0])
cv_df = split_cv.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*') 
predictions = clf.predict(cv_df.as_matrix()[:,1:])
origin_data_train = pd.read_csv("D:\\学习\\研一\\数据挖掘\\kaggle入门\\练习赛\\泰坦尼克之灾\\train.csv",engine='python')
#在交叉验证中,筛选出错误的那些案例
bad_cases = origin_data_train.loc[origin_data_train['PassengerId'].isin(split_cv[predictions != cv_df.as_matrix()[:,0]]['PassengerId'])]
print('交叉验证正确率为:',1 - bad_cases.shape[0] / cv_df.shape[0])





######################################learning curve########################################
#https://blog.csdn.net/geduo_feng/article/details/79547554
import numpy as np
import matplotlib.pyplot as plt
from sklearn.learning_curve import learning_curve

#下面这个例子是官方的例程
import numpy as np 
import matplotlib.pyplot as plt 
 # 用sklearn的learning_curve得到training_score和cv_score,使用matplotlib画出learning curve 
def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, n_jobs=1, 
                        train_sizes=np.linspace(.05, 1., 20), verbose=0, plot=True):
    """
    画出data在某模型上的learning curve.
    参数解释
    ----------
    estimator : 你用的分类器。
    title : 表格的标题。
    X : 输入的feature,numpy类型
    y : 输入的target vector
    ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点
    cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份)
    n_jobs : 并行的的任务数(默认1)
    """ 
    train_sizes, train_scores, test_scores = learning_curve( estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes, verbose=verbose) 
    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) 
    if plot: 
        plt.figure() 
        plt.title(title) 
        if ylim is not None: 
            plt.ylim(*ylim) 
        plt.xlabel(u"训练样本数") 
        plt.ylabel(u"得分") 
        plt.gca().invert_yaxis() 
        plt.grid() 
        plt.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.1, color="b") 
        plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, alpha=0.1, color="r") 
        plt.plot(train_sizes, train_scores_mean, 'o-', color="b", label=u"训练集上得分") 
        plt.plot(train_sizes, test_scores_mean, 'o-', color="r", label=u"交叉验证集上得分") 
        plt.legend(loc="best") 
        plt.draw() 
        plt.show() 
        #plt.gca().invert_yaxis() 
    midpoint = ((train_scores_mean[-1] + train_scores_std[-1]) + (test_scores_mean[-1] - test_scores_std[-1])) / 2 
    diff = (train_scores_mean[-1] + train_scores_std[-1]) - (test_scores_mean[-1] - test_scores_std[-1]) 
    return midpoint, diff 
df = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*').as_matrix()
plot_learning_curve(clf, u"学习曲线", df[:,1:],df[:,0])



#############################################模型融合###################################################
from sklearn.ensemble import BaggingRegressor
train_df = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np = train_df.as_matrix()

# y即Survival结果
y = train_np[:, 0]
# X即特征属性值
X = train_np[:, 1:]

# fit到BaggingRegressor之中
clf = linear_model.LogisticRegression(C=1.0, penalty='l2', tol=1e-6)
#直接调用内置的bagging包,各参数意义在这里https://blog.csdn.net/genghaihua/article/details/81156228

bagging_clf = BaggingRegressor(clf, n_estimators = 20, max_samples=0.8, max_features=1.0, bootstrap=True, bootstrap_features=False, n_jobs=1) 
bagging_clf.fit(X, y) 
test = data_test.filter(regex='Survived|Age_.*|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*') 
predictions = bagging_clf.predict(test) 
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(), 'Survived':predictions.astype(np.int32)}) 
result.to_csv("D:\\学习\\研一\\数据挖掘\\kaggle入门\\练习赛\\泰坦尼克之灾\\logistic_regression_bagging_predictions.csv", index=False)












2019-01-25 更新

之后又试了很多次特征的各种组合/分桶等等,都没有获得理想的效果,猜测原因可能是对特征工程认识还不够深入,以及作为新手小白还不会换英雄(一直用的这一个逻辑斯蒂回归模型)。

另外,还有一个令人费解的问题,我在自己的spyder中测试的学习曲线和交叉验证结果和kaggle的提交结果并不一致,比如说自己的交叉验证结果得分提高后的程序版本跑出来的结果,在kaggle中的评测结果反而是下降了。

总结一下目前的问题:
(1)如何处理特征

(2)如何合理地换模型(中间手贱随便尝试了下随机森林然后正确率惨不忍睹)

(3)如何较好的评测本次的程序结果

泰坦尼克之灾这个问题前前后后花了差不多半周的时间来做,从教程中也是受益匪浅。自己目前的主要问题我觉得还是见识太浅,所以这个问题先告一段落,刚好也要放假了,接下来打算去看kaggle的其他练习赛及教程。运用和总结是最好的学习方式,fighting~

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值