泰坦尼克号获救预测

练习:泰坦尼克号获救数据预测,预测人员获救与哪些因素有关。


1. 读取数据

import pandas as pd

df = pd.read_csv('titanic_train.csv')
print(df.head())
print(df.columns)
print(df.isnull().sum())
print(df.describe())

运行结果如图1所示:

图1

从图中可以看出数据大小为891 * 12,列名有['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket','Fare', 'Cabin', 'Embarked'],有些列的数据存在着缺失,我们先看看每一列代表什么意思。

'PassengerId':乘客的ID
'Survived':乘客是否获救,0表示未获救,1表示获救
'Pclass':乘客舱位等级
'Name':乘客名字
'Sex':乘客性别
'Age':乘客年龄
'SibSp':乘客兄弟姐妹数
'Parch':乘客携带的老人以及小孩数量
'Ticket':乘客船票编号
'Fare':乘客当前船票价格
'Cabin':缺失值太多,忽略
'Embarked':乘客上船地点,分别有C、S、Q


2.数据预处理

  • 从图1看出数据中'Age'列和'Carbin'列存在缺失值,所以我们先要对'Age'列进行填充,这里使用均值填充,而'Carbin'列在分析的时候可以忽视它。
df['Age'] = df['Age'].fillna(df['Age'].median())
print(df.describe())

运行结果如图2所示:

图2

从图2可以看出,'Age'列缺失的数据已经被填充好了。

  • 观察'Sex'这一列,发现里面的数据是male和female,分别代表男性和女性,在机器学习上无法识别str,我们需要将str转换为0,1,即male用0表示,female用1表示。
print(df['Sex'].unique())
df.loc[df['Sex'] == 'male','Sex'] = 0
df.loc[df['Sex'] == 'female','Sex'] = 1
print(df['Sex'].unique())

运行结果如图3所示:

图3

从图3可以看出,已经将male和female转换为0和1.


  • 观察Embarked这一列,发现里面的数据是C、Q、S,所以也要和上面的一样,进行数据类型转换。这里将S用0表示,C用1表示,Q用2表示。同时发现Embarked列也存在着缺失值,所以需要对缺失值进行填充,先统计C、Q、S中出现频率最高的,然后将出现频率最高的填入缺失值。
print(df['Embarked'].unique())
print(dict(df['Embarked'].value_counts()))

df['Embarked'] = df['Embarked'].fillna('S')
df.loc[df['Embarked'] == 'S','Embarked'] = 0
df.loc[df['Embarked'] == 'C','Embarked'] = 1
df.loc[df['Embarked'] == 'Q','Embarked'] = 2

print(df['Embarked'].unique())

运行结果如图4所示:

图4

从图4中可以看出S的频率最高,所以这里讲S填入缺失值,经过处理后的数据变为0、1、2。


3.模型建立

  • 用线性回归预测
# 利用线性回归预测
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import KFold

# 设置标签
predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
alg = LinearRegression()

kf = KFold(n_splits=3, random_state=1)
predictions = []
for train, test in kf.split(df[predictors]):
    train_predictors = df[predictors].iloc[train, :]
    train_target = df['Survived'].iloc[train]
    alg.fit(train_predictors, train_target)

    # 对测试集进行预测
    test_predictions = alg.predict(df[predictors].iloc[test, :])
    predictions.append(test_predictions)

predictions = np.concatenate(predictions, axis=0)
predictions[predictions > 0.5] = 1  # 大于0.5表示获救
predictions[predictions <= 0.5] = 0 # 小于0.5表示未获救
accuracy = len(predictions[predictions == df['Survived']]) / len(predictions)
print(accuracy)

运行结果为:0.7833894500561167
可见预测的准确率并不是很高。同时还要注意,由于版本的变换,KFold模块现在改为从model_selection中导入。还有,KFold的使用方法也改了,下面是之前版本的使用方式。

kf = KFold(df.shape[0], n_folds=3,  random_state=1)
predictions = []
for train, test in kf:
    train_predictors = (df[predictors].iloc[train, :]

  • 用逻辑回归预测
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression

predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
alg_1 = LogisticRegression(random_state=1)
scores = model_selection.cross_val_score(alg_1, df[predictors], df['Survived'], cv=3)

print(scores.mean())

运行结果为:0.7878787878787877
可见预测的准确率之比线性回归高了那么一点点,但还是不高。在运行程序时发现了警告,警告内容如图5所示:

图5

虽然警告信息并不影响代码运行,但输出窗口异常明显的几行红字提醒,总觉得不爽。
FutureWarning是语言或者库中将来可能改变的有关警告。
根据报警信息和参考相关文档,“Default will change from 'liblinear' to 'lbfgs' in 0.22.”,默认的solver参数在0.22版本中,将会由“liblinear”变为“lbfgs”,且指定solver参数可以消除该warning。
这是代码在发出警告,将来代码运行时如果没有及时关注到版本的问题,可能solver的参数会发生改变。所以,最安全的方法并不是通过ignore消除警告,而是指定一个solver参数。
解决办法:

# 版本问题,需要在后面添加 solver='liblinear',否则会有警告,虽然不影响运行
alg_1 = LogisticRegression(random_state=1, solver='liblinear')

另一种思路是:

# 这种方法可以消除任何警告信息
import warnings
warnings.filterwarnings("ignore")

  • 随机森林模型进行预测
    同时我们要考虑上述标签中,到底是哪个标签的权重对获救的概率影响高一点,哪个权重会使得获救的概率降低,这一点需要考虑。这里引进随机森林模型,能够综合的利用标签,降低过拟合的风险,提高预测的准确性。
# 使用随机森林模型
from sklearn import model_selection
from sklearn.ensemble import RandomForestClassifier

# 设置标签
predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']

# 通过随机森林进行预测,这里随机森林的参数只是随便设定的,具体参数需要建立一个随机森林模型    
# n_estimators指树的个数,min_samples_split指内部节点再划分所需最小样本数,min_samples_leaf叶子节点最少样本数
alg_2 = RandomForestClassifier(random_state=1, n_estimators=50,   min_samples_split=4, min_samples_leaf=2)
kf = model_selection.KFold(n_splits=3, random_state=1, shuffle=True)
scores_1 = model_selection.cross_val_score(alg_2, df[predictors], df['Survived'], cv=kf)
print(scores_1.mean())

运行结果为:0.8260381593714926
从图中的结果可以看出预测的准确率又比前面的高了一些,但还是不够。由于这里的随机森林模型是随便设定的,没有设定好参数,所以需要对模型进行优化,建立合适的树模型,优化数的个数和深度。
RandomForestClassifier用法参考:https://www.cnblogs.com/pinard/p/6160412.html


  • 自己构造特征

前面我们还有一些标签没有使用上,在这里我们将剩下的一些标签给用上,将标签进行数字化处理。其中,构建一个FamilySize标签,它是由SibSp标签和Parch标签相加得到;构建一个NameLength标签,它是乘客的名字长度;再构建Title标签,它是每个乘客的称号,如Mr、Mrs、Miss、Dr...。然后将标签的数据转换为数字进行处理。

# 自己构建特征
df['FamilySize'] = df['SibSp'] + df['Parch']  # 兄弟姐妹和老人小孩
df['NameLength'] = df['Name'].apply(lambda x: len(x))  # 名字的长度

import re


# 每个人都有自己的身份的词,如Miss, Mr...
def get_title(name):
    title_search = re.search(' ([A-Za-z]+)\.', name)
    if title_search:
        return title_search.group(1)
    return ''


titles = df['Name'].apply(get_title)
print(pd.value_counts(titles))

# 将称号用数字表示
title_mapping = {'Mr': 1, 'Miss': 2, 'Mrs': 3, 'Master': 4, 'Dr': 5, 'Rev': 6, 'Col': 7, 'Major': 8, 'Mlle': 9,
             'Countess': 10, 'Ms': 11, 'Lady': 12, 'Jonkheer': 13, 'Don': 14, 'Mme': 15, 'Capt': 16, 'Sir': 17}
for k, v in title_mapping.items():
    titles[titles == k] = v
print(pd.value_counts(titles))

df['Title'] = titles

运行结果如图6、7所示:

图6-各个称号的个数

图7-各个称号数字化处理后的结果

至此,3个新的标签就已经构建好了,我们先将数据可视化,观察哪个标签所占的权重较高,然后使用随机森林模型进行预测。

from sklearn.feature_selection import SelectKBest, f_classif

predictors_new = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'FamilySize', 'NameLength', 'Title']

selector = SelectKBest(f_classif, k=5)
selector.fit(df[predictors_new], df['Survived'])
scores_2 = -np.log10(selector.pvalues_)

plt.bar(range(len(predictors_new)), scores_2)
plt.xticks(range(len(predictors_new)), predictors_new, rotation='vertical')
plt.show()

SelectKBest用法参考:https://www.jianshu.com/p/586ba8c96a3d
运行结果如图8所示:

图8-各个标签所占权重

通过上述图8我们选择5个最重要的标签,接下来用随机森林模型进行预测。

predictors_1 = ['Pclass', 'Sex', 'Fare', 'Title', 'NameLength']
alg_3 = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=8, min_samples_leaf=4)
kf = model_selection.KFold(n_splits=3, random_state=1, shuffle=True)
scores_1 = model_selection.cross_val_score(alg_3, df[predictors_1], df['Survived'], cv=kf)

print(scores_1.mean())

运行结果为:0.8215488215488215
可见,预测的结果并没有多大的改变,可见随机森林的预测效果还不够好,看能否优化一下树结构。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容