1.提出问题
根据已知人员数据信息,对其他人员的生存情况做出预测。
2.理解数据
1.数据来源:kaggle网站的Titanic生存模型预测,含有2组数据,训练集train.csv和测试集test.csv。
2.数据指标:
passengerId:
Survived: 是否生存,0=死亡,1=生存
Pclass: 船票等级,1=一等舱,2=二等舱,3=三等舱
Name:姓名
Sex:性别
Age:年龄
SibSp:船上的兄弟姐妹/配偶数
Parch:船上的父母/子女数
Ticket:船票号
Fare:票价
Cabin:船舱号
Embarked:出发港口,C=瑟堡(法国),S=南安普顿 ,Q=昆士敦
3.数据清洗
(1)如果数据集很多,只有很少的缺失值,可以删掉带缺失值的行;
(2)如果该属性相对学习来说不是很重要,可以对缺失值赋均值或者众数,比如Embarked。
(3)对于缺失很多的重要属性,可以赋值Uknow,比如船舱号Cabin。
导入模块:
import numpy as np
import pandas as pd
读取文件:(类型csv/text/DataFrame)
train = pd.read_csv('C:/Users/titanic/train.csv')
test = pd.read_csv('C:/Users/titanic/test.csv')
查看数据结构:
print('训练数据集:', train.shape, '测试数据集', test.shape)
合并数据集,便于清洗:
# ignore_index=True产生新索引,sort=True对新数据调整
full = train.append(test, ignore_index=True, sort=True)
print('合并后的数据集:', full.shape)
#查看数据集结构发现缺失的指标有:Age/Cabin/Embarked/Fare/
print(full.info())
(1)数值型缺失——均值填充fillna
full['Age'] = full['Age'].fillna(full['Age'].mean())
full['Fare'] = full['Fare'].fillna(full['Fare'].mean())
(2)字符串型缺失——数量少填充最频繁的值,多则取新值uknow
print(full['Embarked'].head())
full['Embarked'] = full['Embarked'].fillna('S')
print(full['Cabin'].head())
full['Cabin'] = full['Cabin'].fillna('U')
(3)分类数据转换:数值或one-hot编码
# 性别Sex:female/male转换为数值0/1,map对指定列做映射
sex_mapDict = {'male': 1,'female': 0}
full['Sex']=full['Sex'].map(sex_mapDict)
# 登船港口Embarked:S/C/Q进行One-hot编码,用get_dummies
# 存放提取的特征
embarkedDf = pd.DataFrame()
# 转化为3个新变量,prefix列名加前缀
embarkedDf = pd.get_dummies(full['Embarked'], prefix='Embarked')
print(embarkedDf.head())
# 合并,axis=1表示列合并
full = pd.concat([full, embarkedDf], axis=1)
# 丢弃原来的Embarked列,inplace=1表示在原表修改,不创建新对象
full.drop('Embarked', axis=1, inplace=True)
# 船舱等级Pclass:进行One-hot编码
pclassDf = pd.DataFrame()
pclassDf = pd.get_dummies(full['Pclass'], prefix='Pclass')
print(pclassDf.head())
full = pd.concat([full, pclassDf], axis=1)
full.drop('Pclass', axis=1, inplace=True)
# 船舱号Cabin:编号进行One-hot编码
# lambda定义匿名函数,返回Cabin的首字母
cabinDf = pd.DataFrame()
full['Cabin'] = full['Cabin'].map(lambda c: c[0])
cabinDf = pd.get_dummies(full['Cabin'], prefix='Cabin')
print(cabinDf.head())
full = pd.concat([full, cabinDf], axis=1)
full.drop('Cabin', axis=1, inplace=True)
# 也可以full = pd.get_dummies(full,columns=['Cabin']),更简洁
# 从姓名(名,头衔.姓)中获取头衔姓名进行one-hot编码,可定义函数
def getTitle(name):
str1 = name.split(',')[1]
str2 = str1.split('.')[0]
str3 = str2.strip()
return str3
titleDf = pd.DataFrame()
titleDf['Title'] = full['Name'].map(getTitle)
# 查看某列有多少不同值
print(titleDf['Title'].value_counts())
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"
}
titleDf['Title']=titleDf['Title'].map(title_mapDict)
titleDf=pd.get_dummies(titleDf['Title'])
print(titleDf.head())
full=pd.concat([full,titleDf],axis=1)
full.drop('Name',axis=1,inplace=True)
# 划分家庭规模:小家庭=1,中等家庭(2,4),大家庭>=5,进行one-hot编码
familyDf=pd.DataFrame()
familyDf['FamilySize']=full['Parch']+full['SibSp']+1
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 s>=5 else 0)
print(familyDf.head())
full=pd.concat([full,familyDf],axis=1)
4.构建模型
生成相关系数矩阵,选择特征:
corrDf=full.corr()
print(corrDf)
print(corrDf['Survived'].sort_values(ascending=False))
full_x=pd.concat([titleDf,
pclassDf,
familyDf,
full['Fare'],
cabinDf,
embarkedDf,
full['Sex']]
,axis=1)
print(full_x.head())
将train、test数据集分开:
sourceRow=891
#原始数据:特征
x=full_x.iloc[0:sourceRow,:]
print(x.shape)
#原始数据:标签
y=full.loc[0:sourceRow-1,'Survived']
print(y.shape)
#预测数据集:特征
pred_x=full_x.iloc[sourceRow:,:]
print('原始数据集有%s行'%source_x.shape[0])
#将原始数据分为训练数据和测试数据
from sklearn.model_selection import train_test_split
train_x,test_x,train_y,test_y=train_test_split(x,y,train_size=0.8)
#输出数据集大小
print('原始数据集特征:',x.shape,
'训练数据集特征:',train_x.shape,
'测试数据集特征:',test_x.shape)
print('原始数据集特征:',y.shape,
'训练数据集特征:',train_y.shape,
'测试数据集特征:',test_y.shape)
#使用逻辑回归进行预测,max_iter默认1000,警告时可以调大
from sklearn.linear_model import LogisticRegression
model=LogisticRegression(max_iter=5000)
model.fit(train_x,train_y)
5.模型评估
#模型评价:评分(即准确率0.8379)
print(model.score(test_x,test_y))
6.实施方案
补充:交叉验证思想
把某种意义下将原始数据(dataset)进行分组,一部分作为训练集(train set),另一部分作为验证集(test set),首先用训练集对分类器进行训练,再利用验证集来测试训练得到模型(model),以此来作为评价分类器的性能指标。
交叉验证用于评估模型的预测性能,尤其是训练好的模型在新数据上的表现,可以在一定程序熵减少过拟合。
交叉验证还可以从有限的数据中获取尽可能多的有效信息。