Kaggle入门第一课-Titanic实例解析

时间:2022-06-15 02:50:49

本文kernel来源于:https://www.kaggle.com/helgejo/an-interactive-data-science-tutorial 旨在记录对该实例的解析,学习运用python进行简单的机器学习练习。本文更注重分析流程,建模部分仅用了一种机器学习模型,运用不同的模型进行建模的方法类似。

引入库文件

# 忽略警告Ignore warnings
import warnings
warnings.filterwarnings('ignore')


# 管理类似表格的数据或矩阵Handle table-like data and matrices
import numpy as np
import pandas as pd

# 建模的算法,主要来源于sklearn Modelling Algorithms
from sklearn.tree import DecisionTreeClassifier #决策树
from sklearn.linear_model import LogisticRegression #逻辑回归
from sklearn.neighbors import KNeighborsClassifier #k近邻
from sklearn.naive_bayes import GaussianNB #高斯
from sklearn.svm import SVC, LinearSVC 线性支持向量机
from sklearn.ensemble import RandomForestClassifier , GradientBoostingClassifier #随机森林分类,梯度推进分类

建模辅助Modelling Helpers

from sklearn.preprocessing import Imputer , Normalizer , scale
#http://blog.csdn.net/sinat_33761963/article/details/53433799机器学习中的数据预处理常用这个,imputer录入,正交化,变换范围
from sklearn.cross_validation import train_test_split , StratifiedKFold

#机器学习中的交叉验证,import:将数据随机分组为训练集和测试集,StratifiedKFold是k-Fold的变体,它返回分层折叠:每个集合大致保持了与原始完整集合中每个类的百分比。http://blog.csdn.net/Mr_tyting/article/details/73440712

from sklearn.feature_selection import RFECV
#机器学习中的特征选取,减少特征数量,增强模型泛化能力,减少过度拟合,增强特征和特征值之间的理解

# 可视化Visualisation
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
import seaborn as sns
#matplotlib下的两个模块pylot提供了类似MATLAB的绘图APIpylab包含了许多Numpy和pylot模块中常用的函数,在交互式工作时比较方便,但是需要与numpy、pylot分别导入使用。seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易

# 管理可视化Configure visualisations
%matplotlib inline
#在ipython下内置的魔法函数,用%模仿命令行形式访问。用于内嵌画图
mpl.style.use( 'ggplot' )#样式美化
sns.set_style( 'white' )
pylab.rcParams[ 'figure.figsize' ] = 8 , 6 #读入配置文件,可修改后面的配置字典。http://blog.csdn.net/iamzhangzhuping/article/details/50792208

功能函数:

#画直方图
def plot_histograms( df , variables , n_rows , n_cols ):
fig = plt.figure( figsize = ( 16 , 12 ) )
for i, var_name in enumerate( variables ):
ax=fig.add_subplot( n_rows , n_cols , i+1 )
df[ var_name ].hist( bins=10 , ax=ax )
ax.set_title( 'Skew: ' + str( round( float( df[ var_name ].skew() ) , ) ) ) # + ' ' + var_name ) #var_name+" Distribution")
ax.set_xticklabels( [] , visible=False )
ax.set_yticklabels( [] , visible=False )
fig.tight_layout() # Improves appearance a bit.
plt.show()

#画分布图,var横坐标,target纵坐标,kwargs指明行或列,例如本文plot_distribution(titanic,var='Fare',target='Survived',row='Sex'),即以两种性别为另外的维度,因此画了2个分布图,一个一行。
def plot_distribution( df , var , target , **kwargs ):
row = kwargs.get( 'row' , None )
col = kwargs.get( 'col' , None )#初始化默认值
facet = sns.FacetGrid( df , hue=target , aspect=4 , row = row , col = col )
facet.map( sns.kdeplot , var , shade= True )
facet.set( xlim=( 0 , df[ var ].max() ) )
facet.add_legend()
#画分类图,看统一特征的不同值对结果的影响
def plot_categories( df , cat , target , **kwargs ):
row = kwargs.get( 'row' , None )
col = kwargs.get( 'col' , None )
facet = sns.FacetGrid( df , row = row , col = col )
facet.map( sns.barplot , cat , target )
facet.add_legend()

def plot_correlation_map( df ):
corr = titanic.corr()
_ , ax = plt.subplots( figsize =( 12 , 10 ) )
cmap = sns.diverging_palette( 220 , 10 , as_cmap = True )
_ = sns.heatmap(
corr,
cmap = cmap,
square=True,
cbar_kws={ 'shrink' : .9 },
ax=ax,
annot = True,
annot_kws = { 'fontsize' : 12 }
)

def describe_more( df ):
var = [] ; l = [] ; t = []
for x in df:
var.append( x )
l.append( len( pd.value_counts( df[ x ] ) ) )
t.append( df[ x ].dtypes )
levels = pd.DataFrame( { 'Variable' : var , 'Levels' : l , 'Datatype' : t } )
levels.sort_values( by = 'Levels' , inplace = True )
return levels
#查看变量的重要性
def plot_variable_importance( X , y ):
tree = DecisionTreeClassifier( random_state = 99 )
tree.fit( X , y )
plot_model_var_imp( tree , X , y )

def plot_model_var_imp( model , X , y ):
imp = pd.DataFrame(
model.feature_importances_ ,
columns = [ 'Importance' ] ,
index = X.columns
)
imp = imp.sort_values( [ 'Importance' ] , ascending = True )
imp[ : 10 ].plot( kind = 'barh' )
print (model.score( X , y ))

加载数据:

# 读取csv数据为DF结构 get titanic & test csv files as a DataFrame
train = pd.read_csv("../input/train.csv")
test = pd.read_csv("../input/test.csv")
full = train.append( test , ignore_index = True )#训练集加测试集
titanic = full[ :891 ]
del train , test
print ('Datasets:' , 'full:' , full.shape , 'titanic:' , titanic.shape)

统计情况小节和数据可视化:

titanic.head()#显示前5行数据
titanic.describe()#数据描述,表格形式表现数值数据的均值等基本统计参数
plot_correlation_map( titanic )#各个特征之间的相关性
plot_distribution( titanic , var = 'Age' , target = 'Survived' , row = 'Sex' )#年龄、性别的结果占比
plot_categories( titanic , cat = 'Embarked' , target = 'Survived' )#每个特征值的不值对结果的影响程度是否有差别

数据预处理:

1.  非数值变量转换为数值变量
用pd.Series()分别用10代表男和女。对n个值(n>2)的变量,用pd.get_dummies()拆分成n列数据。
2. 填补缺失数据
为了更好的训练模型。最简单的方法是用变量的平均数填补空缺。新建一个DataFrame用full.Age.fillna(full.Age.mean())来填补full中Age列的空白。
3. 特征提取-创造新变量

提取新特征:

  1. 从游客姓名提取称呼:用.map( lambda name: name.split( ‘,’ )[1].split( ‘.’ )[0].strip() )为姓名——拆分后的姓名做映射。创建称呼和称呼分类的字典。将称呼和此字典映射,即对称呼分类。Get_dummies函数拆分n列数据。pd.concat用来连接表。
  2. 从Ticket号码提取仓位:对Ticket进行数据清理ticket[ ‘Ticket’ ] = full[ ‘Ticket’ ].map( cleanTicket ),cleanTicket函数是对每行的ticket数据进行处理,split拆分字符串成为list,strip把一个字符串中的前后空格给去掉,filter保留非纯数字的字符串,纯数字的list长度为复数,这样就可以返回字符串的开头字母,非字符串的都是XXX。映射每个ticket的值到这个函数,然后get_dummies拆分n列数据。
  3. 家庭成员数量提取:df结构的数据可以直接累加,用map对累加的结果分类,get_dummies拆分行。
  4. 所有特征的dataset总和:pd.concat
    训练集和测试集:
train_valid_X = full_X[ 0:891 ] #full_X是所有的1309条特征集合(包括891条带结果的用于训练和481条不带结果的用于测试)
train_valid_y = titanic.Survived #titanic是前891条带结果的数据
test_X = full_X[ 891: ] #剩下的481条不带结果的数据
train_X , valid_X , train_y , valid_y = train_test_split( train_valid_X , train_valid_y , train_size = .7 )# 随机选取训练集和验证集
print (full_X.shape , train_X.shape , valid_X.shape , train_y.shape , valid_y.shape , test_X.shape)

得到(1309, 15) (623, 15) (268, 15) (623,) (268,) (418, 15)
说明:带X的表示15列特征,带y的表示Survived的结果。分别对这两个进行划分。然后train_X&train_y用于训练模型,valid_X&valid_y用于验证模型的性能。如果符合要求,那么可以把该模型应用在test_X测试集上得出预测结果。
train_X , valid_X , train_y , valid_y = train_test_split( train_valid_X , train_valid_y , train_size = .7 )
train_X:训练集X 70% + valid_X:验证集X 30%= train_valid_X 890条特征数据
train_y:训练集y 70% + valid_y:验证集y30%=train_valid_y 890 条结果
train_size:训练集占总集合的比例
建模&训练模型
model = LogisticRegression()
model.fit( train_X , train_y ) #训练集(特征+结果)

评价

  1. 模型表现:
    print (model.score( train_X , train_y ) , model.score( valid_X , valid_y ))#前者为训练集(特征+结果),后者为验证集(特征+结果),比较后者和前者的score,因为是根据前者建模的,所以如果后者的score低很多,那么说明本次建模过度拟合,

  2. 特征重要性:

#需要自己编写函数来实现,见上文
plot_model_var_imp(model, train_X, train_y)
#自动选取最优的特征
rfecv = RFECV( estimator = model , step = 1 , cv = StratifiedKFold( train_y , 2 ) , scoring = 'accuracy' )
rfecv.fit( train_X , train_y )
#以下都是画图步骤
#print (rfecv.score( train_X , train_y ) , rfecv.score( valid_X , valid_y ))
#print( "Optimal number of features : %d" % rfecv.n_features_ )

# Plot number of features VS. cross-validation scores
#plt.figure()
#plt.xlabel( "Number of features selected" )
#plt.ylabel( "Cross validation score (nb of correct classifications)" )
#plt.plot( range( 1 , len( rfecv.grid_scores_ ) + 1 ) , rfecv.grid_scores_ )
#plt.show()

发布结果

返回的结果是两列,一列是乘客ID,一列是根据本文的模型预测的生还结果

test_Y = model.predict( test_X ) #用剩下的400条数据预测
passenger_id = full[891:].PassengerId #
test = pd.DataFrame( { 'PassengerId': passenger_id , 'Survived': test_Y } ) #存储在df格式中
test.shape #整形
test.head()
test.to_csv( 'titanic_pred.csv' , index = False ) #导出到工作目录下