kaggle项目初探,使用机器学习包sklearn 预测泰坦尼克号乘客生存率,生存率预测是分类问题,使用逻辑回归。提出问题(Business Understanding )
理解数据(Data Understanding)
数据清洗(Data Preparation )
特征工程(Feature Engineering)
获取相关系数(Correlation)
构建模型(Modeling)
模型评估(Evaluation)
方案实施 (Deployment)
一、提出问题(Business Understanding )
1、查看官网项目情况,并下载数据集Titanic: Machine Learning from Disasterwww.kaggle.com
2、分析思路思维导图
3、提出问题
构建模型对船上乘客的生存概率进行预测,什么样的人在泰坦尼克号中更容易存活?
比如:
1)有没有可能一些特定的人群如妇女儿童会比大多数人更容易存活?
2)不同等级客存活概率是不是不同?
3)生存概率和年龄有关系吗?
4)生存概率会不会受家庭成员多少的影响?
二、理解数据 (Data Understanding)
1、导入数据到python中
理解每个字段的含义 一共12个字段
训练数据: (891, 12) 测试数据: (418, 11)
因为测试数据集没有生存率预测所以11行,训练数据12行)
表的合并:
append是series和dataframe的方法,使用它就是默认沿着列进行拼接表。
其中关于:ignore_index = True 使用ignore_index参数,值true,合并的两个表就是根据列字段对齐,然后合并,其中无效的值用NaN来表示,参考下面文章。PANDAS 数据合并与重塑www.cnblogs.com
#模块导入
import numpy as np
import pandas as pd
#把数据集导入python
train = pd.read_csv("/Users/tony/机器学习(入门)/3.泰坦尼克号/train.csv")
test = pd.read_csv("/Users/tony/机器学习(入门)/3.泰坦尼克号/test.csv")
#打印出来看多少行 多少列 (说明因为测试数据集没有生存率预测所以11行,训练数据12行)
print('训练数据:',train.shape,'测试数据:',test.shape)
#通过train.append()来合并数据集,使用ignore_index参数= true,
#合并的两个表就根据列字段对齐,然后合并。最后再重新整理一个新的index,空值NaN
full = train.append( test, ignore_index = True )
print( '合并后的数据集:' , full.shape)
2、查看数据集情况 info和describe
2.1查看数据的描述统计信息(只能查看数值型数据) 其中Age和Fare有缺失值
describe只能查看数据类型的描述统计信息,对于其他类型的数据不显示,比如字符串类型姓名(name),客舱号(Cabin),因为描述统计指标是计算数值,所以需要该列的数据类型是数据count数据总数
mean平均值
std标准差
min最小值
25%下四分位
50%中位数
75%上四分位
max最大值
#打印前几行 理解字段意思 一共12个字断。其中Survived 1为存活 0为死亡
#年龄 船舱号 登船港口 船票价格 名字 不同代亲属数 乘客编号 客舱等级 性别 同代亲属数 生存情况 船票编号
full.head()
#查看数据集的描述统计信息 只能查看数据类型的描述统计信息
full.describe()
#查看每一列的数据类型和数据总数 使用.info() 这里我们发现Age Cabin Embarked Fare四列有缺失值
full.info()
2.2查看数据的数据类型和数据总数 info()
数据总共有1309行。除了上面两个缺失值还有Cabin和Embarked两列有缺失
其中数据类型列:年龄(Age)、船舱号(Cabin)里面有缺失数据,查看缺失情况
1)年龄(Age)里面数据总数是1046条,缺失了1309-1046=263,缺失率263/1309=20%
2)船票价格(Fare)里面数据总数是1308条,缺失了1条数据
字符串列:登船港口(Embarked)和船舱号(Cabin)有缺失 看缺失情况
3)登船港口(Embarked)里面数据总数是1307,只缺失了2条数据,缺失比较少
4)船舱号(Cabin)里面数据总数是295,缺失了1309-295=1014,缺失率=1014/1309=77.5%,缺失比较大
这为我们下一步数据清洗指明了方向,只有知道哪些数据缺失数据,我们才能有针对性的处理。
三、数据清洗(Data Preparation )
在前面,理解数据阶段,我们发现数据总共有1309行。 其中数据类型列:年龄(Age)、船舱号(Cabin)里面有缺失数据。 字符串列:登船港口(Embarked)、船舱号(Cabin)里面有缺失数据。这为我们下一步数据清洗指明了方向,只有知道哪些数据缺失数据,我们才能有针对性的处理。很多机器学习算法为了训练模型,要求所传入的特征中不能有空值。如果是数值类型,用平均值取代
如果是分类数据,用最常见的类别取代
使用模型预测缺失值,例如:K-NN
缺失值处理方法:缺失值有两种方法处理,删除dropna或者插值填充fillna,这里我们需要预测生存率所以需要使用插值填充法。
3.1 数值型缺失值:平局值填充法
print('处理前的数据类型和总数:')
full.info()
#年龄(Age)的缺失值处理------
full['Age']=full['Age'].fillna( full['Age'].mean() )
#船票价格(Fare)
full['Fare'] = full['Fare'].fillna( full['Fare'].mean() )
print('处理后的数据类型和总数:')
full.info()
#处理完缺失值 打印前几条出来看看。Age 和Fare
full.head()
3.2 字符串缺失值处理
处理方法:fillna填充法,Embarked众数填充(S),Cabin 填充未知(U)=Unknow
登船港口(Embarked)illna填充 先统计出现最多是S,用S填充
船舱号(Cabin) 缺失值处理,U填充 未知值 unknow
#登船港口缺失值处理:插值填充法 用众数
#查看登船港口(Embarked)的前几行看看
full['Embarked'].head()
#full['Embarked'].value_counts() 查看最常见的类别数量 最多是S 914 用S进行填充
full['Embarked'].value_counts()
#使用fillna进行填充 填充完再次查看数量 S=916两条缺失值 已填充完毕
full['Embarked'] = full['Embarked'].fillna('S')
full['Embarked'].value_counts()
#船仓号缺失值处理
#查看船仓号(Cabin)里面的数据,打印几条出来看看
full['Cabin'].head()
#缺失数据较多,船舱号(Cabin)缺失值填充为U,表示未知(Uknow)
full['Cabin'] = full['Cabin'].fillna('U')
full['Cabin'].value_counts()
#查看填充后数据集情况,打印前几条
full.info()
full.head()
3.3 填充完成 查看数据情况
四、特征工程(Feature Engineering)
特征工程就是最大限度地从原始数据中提取特征以供机器学习算法和模型使用。
Feature Engineering is manually designing what the input x's should be.
处理方法:原始数据——数据清洗——特征提取——特征选择和特征降维——构建模型
1、性别(Sex) 特征处理 转为 数值1 男性male 0 女性female
建立一个映射关系的字典,使用map函数对传入每个数据应用自定义的函数替换。
#性别(Sex)-----------------------
full['Sex'].head()
#创建字典 男(male)对应数值1,女(female)对应数值0
#map函数:对Series每个数据应用自定义的函数计算 替换
sex_mapDict = { 'male':1, 'female':0 }
full['Sex'] = full['Sex'].map(sex_mapDict)
full['Sex'].head()
2、登船港口(Embarked)特征处理
处理思路:新建数据框——编码存入数据框——把数据框加入数据集删除原列名
使用get_dummies进行one-hot编码,产生虚拟变量(dummy variables),产生新对列,列名前缀(prefix)是Embarked。因为已经使用登船港口(Embarked)进行了one-hot编码产生了它的虚拟变量(dummy variables)所以这里把登船港口(Embarked)删掉因为drop(name,axis=1)里面指定了name是哪一列,比如指定的是A这一列,axis=1表示按行操作。那么结合起来就是把A列里面每一行删除,最终结果是删除了A这一列.使用drop删除某几列的方法记住这个语法就可以了:drop([列名1,列名2],axis=1)
#登船港口 (Embarked)-------------------
full['Embarked'].head()
#新建数据框 存放提取后的特征
embarkedDf = pd.DataFrame()
#get_dummies是实现one hot encode的一种方式
embarkedDf = pd.get_dummies(full['Embarked'], prefix = 'Embarked')
#打印前几行出来看看效果 编码完毕
embarkedDf.head()
#把新的数据框加入到原数据框中 concat替换原来的Embarked这一行(drop),axis=1是行对齐合并
full = pd.concat([full,embarkedDf], axis=1)
#替换掉原来的行 drop inplace=True 表示在原数据框上进行修改
full.drop('Embarked',axis=1,inplace=True)
#打印前几行出来看看
full.head()
3、客舱等级(Pclass)特征处理
处理方法同上
#客舱等级(Pclass)
full['Pclass'].head()
#新建数据框 存放提取后的特征
pclassDf = pd.DataFrame()
#get_dummies是实现one hot encode的一种方式
pclassDf = pd.get_dummies(full['Pclass'], prefix = 'Pclass')
#打印前几行出来看看效果 编码完毕
pclassDf.head()
#把新的数据框加入到原数据框中 concat替换原来的Embarked这一行(drop),axis=1是行对齐合并
full = pd.concat([full,pclassDf], axis=1)
#替换掉原来的行 drop inplace=True 表示在原数据框上进行修改
full.drop('Pclass',axis=1,inplace=True)
#打印前几行出来看看
full.head()
4、姓名(Name)特征处理 提取头衔Title
注意到在乘客名字(Name)中,有一个非常显著的特点:乘客头衔每个名字当中都包含了具体的称谓或者说是头衔,将这部分信息提取出来后可以作为非常有用一个新变量,可以帮助我们进行预测。例如:Braund, Mr. Owen Harris
4.1 split 姓名 (Name)提取头衔逗号分隔前后取后面[1]
点号分割出头衔取前面[0]
strip()去除空格
4.2 对名字中间对头衔或称谓建立映射关系,然后用map函数进行替换
4.3创建数据库 对数据进行one hot 编码 存入数据集
#乘客姓名(Name)
full['Name'].head()
#新建数据框存取数据
titleDf = pd.DataFrame()
#对姓名进行拆分 提取头衔 分3步 逗号分隔前后,取后面[1],点号分割出头衔取前面[0],strip()去除空格
#定义函数操作
def getTitle(name):
str1 = name.split(',')[1]
str2 = str1.split('.')[0]
str3 = str2.strip()
return str3
#存头衔特征 新建数据框
titleDf['Title']= full['Name'].map(getTitle)
titleDf.head()
#定义头衔类别的对应映射关系的字典
#姓名中头衔字符串与定义头衔类别的映射关系
title_mapDict = {
"Capt": "Officer",
"Col": "Officer",
"Major": "Officer",
"Jonkheer": "Royalty",
"Don": "Royalty",
"Sir" : "Royalty",
"Dr": "Officer",
"Rev": "Officer",
"the Countess":"Royalty",
"Dona": "Royalty",
"Mme": "Mrs",
"Mlle": "Miss",
"Ms": "Mrs",
"Mr" : "Mr",
"Mrs" : "Mrs",
"Miss" : "Miss",
"Master" : "Master",
"Lady" : "Royalty"
}
#map函数:对Series每个数据应用自定义的函数计算
titleDf['Title'] = titleDf['Title'].map(title_mapDict)
#使用get_dummies进行one-hot编码
titleDf = pd.get_dummies(titleDf['Title'])
titleDf.head()
#添加数据框到数据集full中 并删除原来的列 数据框改变
full = pd.concat([full,titleDf],axis=1)
full.drop('Name',axis=1,inplace=True)
full.head()
5、客舱号(Cabin)特征处理 提取首字母
python 使用 lambda 来创建匿名函数。所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数,如:ambda 参数1,参数2:函数体或者表达式
#从客舱中提取客舱类别 Cabin 查看客舱号的内容
full['Cabin'].head()
#新建数据框 用于存放编码后的客舱信息 one hot encode 使用get_dummies
#使用匿名函数 提取客舱信息的首字母
cabinDf = pd.DataFrame()
full[ 'Cabin' ] = full[ 'Cabin' ].map( lambda c : c[0] )
#使用get_dummies进行one-hot编码
cabinDf = pd.get_dummies( full['Cabin'] , prefix = 'Cabin' )
#打印前几行出#添加数据框cabinDf到数据集full中
full = pd.concat([full,cabinDf],axis=1)
#删掉客舱号这一列 改变数据框True
full.drop('Cabin',axis=1,inplace=True)
full.head()来看看
cabinDf.head()
6、组合特征 家庭人数 使用条件判断 加入数据集
家庭人数=同代直系亲属数(Parch)+不同代直系亲属数(SibSp)+乘客自己(因为乘客自己也是家庭成员的一个,所以这里加1)定义家庭类别:小家庭Family_Single:家庭人数=1
中等家庭Family_Small: 2<=家庭人数<=4
大家庭Family_Large: 家庭人数>=5
if 条件为真的时候返回if前面内容,否则返回0
#家庭人数档案建立(SibSp)和(Parch) 新建家庭档案数据框 存放编码后数据
familyDf = pd.DataFrame()
#家庭人数判断:
familyDf[ 'FamilySize' ] = full[ 'Parch' ] + full[ 'SibSp' ] + 1
#使用条件判断 if
familyDf[ 'Family_Single' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if s == 1 else 0 )
familyDf[ 'Family_Small' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if 2 <= s <= 4 else 0 )
familyDf[ 'Family_Large' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if 5 <= s else 0 )
#打印家庭信息数据库前几条
familyDf.head()
#添加数据框familyDf到泰坦尼克号数据集full
full = pd.concat([full,familyDf],axis=1)
full.head()
五、相关系数 (Correlation)
关于特征工程可以参考下面资料:机器学习之特征工程www.csuldw.com使用sklearn做单机特征工程 - jasonfreak - 博客园www.cnblogs.com
1、相关性矩阵与排序
相关系数法:计算各个特征的相关系数
查看各个特征与生成情况(Survived)的相关系数,ascending=False表示按降序排列
2、特征选取
根据各个特征与生成情况(Survived)的相关系数大小,我们选择了这几个特征作为模型的输入:
客舱等级(pclassDf)
家庭大小(familyDf)
船票价格(Fare)
船舱号(cabinDf)
登船港口(embarkedDf)
性别(Sex)
头衔 (titleDf)
#特征提取后 进入特征选择 计算相关性 相关矩阵
corrDf = full.corr()
corrDf
#特征提取后 进入特征选择 计算相关性 相关矩阵
corrDf = full.corr()
#数据排序 按照特征的生存率 查看特征相关性 降序排序
corrDf['Survived'].sort_values(ascending =False)
#按照相关性选择 特征
#特征选择
full_X = pd.concat( [titleDf,#头衔
pclassDf,#客舱等级
familyDf,#家庭大小
full['Fare'],#船票价格
cabinDf,#船舱号
embarkedDf,#登船港口
full['Sex']#性别
] , axis=1 )
full_X.head()
六、构建模型(Modeling)
用训练数据和某个机器学习算法得到机器学习模型,用测试数据评估模型。选取数据 建立训练数据集和测试数据集坦尼克号测试数据集因为是我们最后要提交给Kaggle的,里面没有生存情况的值,所以不能用于评估模型。我们将Kaggle泰坦尼克号项目给我们的测试数据,叫做预测数据集(记为pred,也就是预测英文单词predict的缩写)。也就是我们使用机器学习模型来对其生存情况就那些预测。
使用Kaggle泰坦尼克号项目给的训练数据集,做为我们的原始数据集(记为source),从这个原始数据集中拆分出训练数据集(记为train:用于模型训练)和测试数据集(记为test:用于模型评估)
从原始数据集(source)中拆分出训练数据集(用于模型训练train),测试数据集(用于模型评估test)rain_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和test data。train_data:所要划分的样本特征集 train_target:所要划分的样本结果 test_size:样本占比,如果是整数的话就是样本的数量
sourceRow是我们在最开始合并数据前知道的,原始数据集有总共有891条数据从特征集合full_X中提取原始数据集提取前891行数据时,我们要减去1,因为行号是从0开始的。891行前面的数据是测试数据集,891行之后的数据是预测数据集。[sourceRow:,:]就是从891行开始到最后一行作为预测数据集
#构建模型 进行机器学习
sourceRow = 891
#原始数据集:特征
source_X = full_X.loc[0:sourceRow-1,:]
#原始数据集:标签
source_y = full.loc[0:sourceRow-1,'Survived']
#预测数据集:特征
pred_X = full_X.loc[sourceRow:,:]
#原始数据集有多少行
print('原始数据集有多少行:',source_X.shape[0])
#预测数据集大小
print('原始数据集有多少行:',pred_X.shape[0])
from sklearn.model_selection import train_test_split
#建立模型用的训练数据集和测试数据集
train_X, test_X, train_y, test_y = train_test_split(source_X ,
source_y,
train_size=.8)
#输出数据集大小
print ('原始数据集特征:',source_X.shape,
'训练数据集特征:',train_X.shape ,
'测试数据集特征:',test_X.shape)
print ('原始数据集标签:',source_y.shape,
'训练数据集标签:',train_y.shape ,
'测试数据集标签:',test_y.shape)
七、模型评估 (Evaluation)
选择一个机器学习算法,用于模型的训练
选择模型:二分分类选择逻辑回归模型
#打印原始数据前几条看看原始数据
source_y.head()
#机器学习 训练模型,选择一个机器学习算法,用于模型的训练,这里选择逻辑回归模型
#第1步:导入算法
from sklearn.linear_model import LogisticRegression
#第2步:创建模型:逻辑回归(logisic regression)
model = LogisticRegression()
#第3步:训练模型
model.fit( train_X , train_y )
# 分类问题,score得到的是模型的正确率
model.score(test_X , test_y )
八、模型实施(Deployment)
使用数据进行预测
使用预测数据集到底预测结果,并保存到csv文件中
#使用机器学习模型,对预测数据集中的生存情况进行预测
pred_Y = model.predict(pred_X)
#数据类型转换 转为为整形
pred_Y=pred_Y.astype(int)
#乘客id
passenger_id = full.loc[sourceRow:,'PassengerId']
#数据框:乘客id,预测生存情况的值
predDf = pd.DataFrame(
{ 'PassengerId': passenger_id ,
'Survived': pred_Y } )
predDf.shape
predDf.head()
#保存结果
predDf.to_csv( 'titanic_pred2.csv' , index = False )