泰坦尼克号数据分析以及幸存预测

泰坦尼克号数据分析

标签: 机器学习深度学习


这个是对kaggle上的泰坦尼克号的数据分析,通过对数据中的各个特征,进行最后是否能够幸存的预测,然后与是否幸存的标签进行比较,得到一个准确度,下面包含线性回归预测以及随机森林预测和联合Boosting的预测

目录如下

[TOC]

首先导入计算库,并且导入数据

import pandas as pd
import numpy as np

titanic = pd.read_csv("train.csv")

然后进行数据预处理,对Age的缺失数据(nan)进行缺失处理,然后将Sex这一项的字符串用.map()方法,替换为0和1.同样,对Embarked这一项用.map()方法替换为0-2的三项.

#进行数据预处理,将age中的NAN按照均值进行填充
titanic["Age"] = titanic["Age"].fillna(titanic["Age"].median())
titanic.describe()

print(titanic["Sex"].unique())

# 将Sex中的male 与 femal 改为0和1
Sex_map = {'male':0, 'female':1}
titanic['Sex'] = titanic['Sex'].map(Sex_map)
titanic.head()

print(titanic["Sex"].unique())

# 将Sex中的male 与 femal 改为0和1
Sex_map = {'male':0, 'female':1}
titanic['Sex'] = titanic['Sex'].map(Sex_map)
titanic.head()print(titanic["Sex"].unique())

# 将Sex中的male 与 femal 改为0和1
Sex_map = {'male':0, 'female':1}
titanic['Sex'] = titanic['Sex'].map(Sex_map)
titanic.head()print(titanic["Sex"].unique())

# 将Sex中的male 与 femal 改为0和1
Sex_map = {'male':0, 'female':1}
titanic['Sex'] = titanic['Sex'].map(Sex_map)
titanic.head()

#同样,对于Embarked进行map
print(titanic["Embarked"].unique())

Embarked_map = {'S':0, 'C':1, 'Q':2}
titanic["Embarked"] = titanic["Embarked"].map(Embarked_map)
titanic["Embarked"] = titanic["Embarked"].fillna('0')
titanic.head()

到这里,数据预处理就完成了.


两种预测方法进行预测:

线性回归
随机森林

1. 线性回归

首先导入库,用的是机器学习库sklearn里面的函数

from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import KFold
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

然后开始进行预测分析

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"] 

alg = LinearRegression() 

#训练集与测试集的百分比分割
x_train, x_test, y_train, y_test = train_test_split(titanic[predictors], titanic["Survived"], test_size = 0.2, train_size = 0.8, random_state = 1)


#对数据进行标准化
sc_x = StandardScaler()
x_train = sc_x.fit_transform(x_train)
x_test = sc_x.transform(x_test)


for i in range (1, 101):
    alg.fit(x_train, y_train)
#     print("这是第",i,"次训练")
test_hat = alg.predict(x_test)

test_hat[test_hat > 0.5] =  1
test_hat[test_hat <= 0.5] =  0

rate = sum(test_hat[test_hat == y_test]) / len(test_hat)
print(rate)

重点重点:这个预测准确率实在是,,,惨不忍睹,,,并且,,,暂时不知道为啥,,,一个二分类问题,随机选都有百分之50左右准确度,,,竟然能预测到27%,,,罪过罪过...
但是吧,接下来的随机森林预测,效果还是看得下去的.


2. 随机森林预测

  • 对样本进行随机采样
  • 对7个特征进行随机选择(5个)
  • 森林的意思是,通过多个决策树进行分类,相当于投票,最后得出结果

就是按照上面的这个规则,我们来用sklearn模型构建一个随机森林的预测

#我们先导入库
from sklearn import cross_validation
from sklearn.ensemble import RandomForestClassifier

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]

alg = RandomForestClassifier(random_state = 1, n_estimators = 10, min_samples_split = 2, min_samples_leaf = 1)

kf = cross_validation.KFold(titanic.shape[0], n_folds = 3, random_state = 1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv = kf)

print(scores.mean())

最后我们得到一个预测值:

0.7856341189674523

可以看出这个准确率,对于一个二分类问题来说,效果一般,毕竟我们平常用CNN做图片二分类的话,一般都可以达到百分之93以上.

  • 有一个点是,这个随机森林的"树"太少了,这里只有10个(n_estimators这个参数).
  • 接着,我们把树的深度增加(min_samples_split这个参数)
  • 下面我们试着把"树"的数目增加一下,并且树深一些.
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]

alg = RandomForestClassifier(random_state = 1, n_estimators = 100, min_samples_split = 6, min_samples_leaf = 2)

kf = cross_validation.KFold(titanic.shape[0], n_folds = 3, random_state = 1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv = kf)

print(scores.mean())

0.8305274971941637

终于上了百分之80大关,但是,,,效果还是一般吧...
但是这里我一开始用的"树"是50,深度是4, 叶子是2,得到的准确度差不多是百分之81,然后一步步尝试着调参,最后得到了这个.


特征提取

这里就有个问题值得我们去考虑了,在实际的数据分析中,往往需要我们自己去在数据中寻找标签.下面我们就来从原有数据中,生成一些标签.

比如,通过观察,我们发现

  1. 如果一家人一起出游,相互帮助会不会增加生还率呢?
  2. 然后发现大家名字长短也有很大区别,要不玄学一下,名字长短会不会对最后的生还造成影响呢.
  3. 还有,仔细观察发现名字里面包含着Mr, Miss, Sir等等这样的一定程度上代表者身份的内容,如果我们把这些提取出来,也可以分析一下,身份对生还率的影响.
#比如我们可以看看一起来的人的个数和是否存活的关系
#我们新建一个特征,就是看看家庭有多少人
titanic["FamilySize"] = titanic["SibSp"] + titanic["Parch"]

#再玄乎点,我们看看名字长度和最后存活有没有关系
titanic["NameSize"] = titanic["Name"].apply(lambda x:len(x))

titanic.head()

下面是对名字隐含的身份信息的提取.

import re

#观察名字,我们发现名字里有一些特殊的前缀称为,比如Mr, Miss, Dr, 等等,我们可以看看这些特征对结果有什么影响
def get_title(name):
    title_search = re.search('([A-Za-z]+)\.', name)
    
    if title_search:
        return title_search.group(1)
    return ""

titles = titanic["Name"].apply(get_title)
# print(titles)
print(pd.value_counts(titles))

title_map = {"Mr":1, "Miss":2, "Mrs":3, "Master":4, "Dr":5, "Rev":6, "Mlle":7, "Col":8, "Major":9, "Countess":10, "Lady":11, "Sir":12, "Capt":13, "Mme":14, "Jonkheer":15, "Ms":16, "Don":17,}

titles = titles.map(title_map)
print(titles)

titanic["Title"] = titles

特征重要程度衡量

上面我们构造了三个特征,然后我们要来看看如何衡量一个特征是否对结果产生了决定性的作用.

衡量一个特征的重要程度的方法

  • 要选出对结果影响更加明显的特征,也就是更加重要的特征
  • 先对需要测试的特征不做任何处理,训练,可以得到模型的错误率(1-准确率)error1
  • 然后对该要测试的特征打乱,比如可以随机给该特征添加噪音(但是要保证其他特征不发生变化),然后再训练得到error2
  • 如果error2有明显的变化,那么,该特征很重要,如果没发生变化,说明影响不大
from sklearn.feature_selection import SelectKBest, f_classif
import matplotlib.pyplot as plt

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", "FamilySize", "NameSize", "Title"]

selector = SelectKBest(f_classif, k = 5)
selector.fit(titanic[predictors], titanic["Survived"])
scores = -np.log10(selector.pvalues_)

plt.bar(range(len(predictors)), scores)
plt.xticks(range(len(predictors)), predictors, rotation = "vertical")

上面的代码我们对10个特征进行了重要程度的计算,然后通过一个条形图显示出来了,图片如下(越重要的值越大):


特征重要度显示

我们可以看出,有5个特征是相对突出的,其中性别尤为重要(莫非这就是所说的,让孩子和女性先走.)

既然我们选出了几个重要的特征,那么我们就要开始用这几个选出来的特征进行预测了

predictors = ["Pclass", "Sex", "Age", "Fare", "Embarked", "NameSize", "Title"]

alg = RandomForestClassifier(random_state = 1, n_estimators = 100, min_samples_split = 6, min_samples_leaf = 2)

kf = cross_validation.KFold(titanic.shape[0], n_folds = 3, random_state = 1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv = kf)

print(scores.mean())
#好吧,貌似好像并没有什么很明显的提升...并且一开始只用上面选出来的4个特征的话,准确率还只有79.9%...还下降了几个百分点

最后的准确度:

0.830527497194164

就像我在注释中说的,如果只用选出来的4个特征,准确度还有所下降,所以一定的特征个数或许还是很重要的.

用多个分类器联合方式(Boosting)方法

就是把之前的两个东西联合起来.代码如下:
里面因为随机森林效果更好,所以在最后"投票"阶段,给随机森林加了更重的权重,即:(随机森林*3 + 线性回归)/4

#我们之前分别用线性回归和随机森林做了预测,我们现在把这两个东西联合起来
from sklearn.ensemble import GradientBoostingClassifier 
from sklearn.linear_model import LogisticRegression

algorithms = [
#     [GradientBoostingClassifier(random_state = 1, n_estimators = 25, max_depth = 3), ["Pclass", "Sex", "Age", "Fare", "Embarked", "NameSize", "Title"]],
    [LogisticRegression(random_state = 1), ["Pclass", "Sex", "Age", "Fare", "Embarked", "NameSize", "Title"]]
]

kf = KFold(titanic.shape[0], n_folds=3, random_state=1)

predictions=[]

# for train, test in kf:
#     train_y = titanic["Survived"].iloc[train]
#     full_test_predictions = []
    
#     for alg, predictors in algorithms:
#         alg.fit(titanic[predictors].iloc[train, :], train_y)
#         test_predictions = alg.predict_proba(titanic[predictors].iloc[test, :].astype(float))[:, 1]
#         full_test_predictions.append(test_predictions)
    
#     test_predictions = (full_test_predictions[0] + full_test_predictions[1]) / 2 
    
#     test_predictions[test_predictions >= 0.5] = 1
#     test_predictions[test_predictions < 0.5] = 0
#     predictions.append(test_predictions)
    
# predictions = np.concatenate(predictions, axis = 0)


full_predictions = []
for alg, predictors in algorithms:
    alg.fit(titanic[predictors], titanic["Survived"])
    predictions = alg.predict_proba(titanic[predictors])[:, 1]
    full_predictions.append(predictions)
    
# predictions = (full_predictions[0] * 3 + full_predictions[1]) / 4
# print(predictions)

predictions[predictions >= 0.5] = 1
predictions[predictions < 0.5] = 0


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

推荐阅读更多精彩内容

  • 心与心之间,不在乎距离,即使相隔万里。 心与心之间,不在乎容貌,即使隔着屏幕。 心与心之间,不在乎爱情,即使充满基...
    止步于谁阅读 315评论 0 3
  • 我如同一只慢慢爬行的蜗牛,不温不火地写了六万多字,终于也获得了1000个赞。没有当初想象的惊喜,心里却也颇不平静。...
    疏林红叶阅读 1,891评论 134 114
  • 火车出了甘肃省,就是满眼的绿色。这样的景色我已经不是第一次见。 自从到南方读书,坐火车连续二十几个小时已经是常事,...
    阿羊ai阅读 439评论 3 2