kaggle—泰坦尼克之灾1

泰坦尼克之灾是kaggle的一个入门案例,本文是我关于这个比赛的一些记录

1、jupyter notebook的安装

相比我之前使用的pycharm,jupyter notebook的优点是允许把代码写入独立的cell中,然后单独执行。这样做意味着我们可以在测试项目时单独测试特定代码块,无需从头开始执行代码。
安装教程参考https://blog.csdn.net/dream_an/article/details/50464940
使用教程参考https://blog.csdn.net/lee_j_r/article/details/52791228

2、泰坦尼克之灾比赛

大致流程如下,接下来我会根据这个流程解释并贴出相应的代码:
1、数据准备和了解:下载数据并了解数据的属性
2、数据清洗:即数据预处理,对缺失值进行补充或者把机器学习不能处理的数值类型转化为可以处理的int型
3、特征工程:提炼出新特征并进行特征选择来提高模型准确率
4、基准模型:跑几个基础模型。我选择了线性回归、逻辑回归、随机森林这三个,并通过交叉验证查看准确率
5、融合模型:我选择融合随机森林和逻辑回归模型

2.1数据准备和了解

首先,在kaggle上下载数据:https://www.kaggle.com/c/titanic/data


各个属性的含义如下:

PassengerId:乘客ID
Survived:是否获救
Pclass:乘客票务舱,1表示最高级
Name:乘客姓名
Sex:性别
Age:年龄
SibSp:堂兄弟妹个数
Parch:父母与小孩个数
Ticket:船票信息
Fare:票价
Cabin:客舱
Embarked:登船港口

再者,导入数据并对各个属性进行大致统计

"""查看数据""" 
import pandas as pd
titanic = pd.read_csv('train.csv')
# titanic.head(3)
print(titanic.describe())
print(titanic.info())

输出结果为

     PassengerId    Survived      Pclass         Age       SibSp  \
count   891.000000  891.000000  891.000000  714.000000  891.000000   
mean    446.000000    0.383838    2.308642   29.699118    0.523008   
std     257.353842    0.486592    0.836071   14.526497    1.102743   
min       1.000000    0.000000    1.000000    0.420000    0.000000   
25%     223.500000    0.000000    2.000000   20.125000    0.000000   
50%     446.000000    0.000000    3.000000   28.000000    0.000000   
75%     668.500000    1.000000    3.000000   38.000000    1.000000   
max     891.000000    1.000000    3.000000   80.000000    8.000000   

            Parch        Fare  
count  891.000000  891.000000  
mean     0.381594   32.204208  
std      0.806057   49.693429  
min      0.000000    0.000000  
25%      0.000000    7.910400  
50%      0.000000   14.454200  
75%      0.000000   31.000000  
max      6.000000  512.329200
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB
None

可以初步发现,Age这一列的count只有714,说明需要进行缺失值填充;Sex、Embarked、Name等属性都是object类型,要将其转化为机器学习能处理的类型。这都是数据预处理的内容,无论哪个案例都需要数据预处理。

2.2数据清洗

数据清洗即数据预处理,包括对缺失值进行填充把机器学习不能处理的数值类型转化为可以处理的int型。
缺失值填充一般用到fillna()函数,分两种情况:
1.如果是数值类型,用平均值或中位数取代
2.如果是分类数据,用最常见的类别取代
具体应用如下:

Age这一列有缺失值,用中位数填充(或平均值)

"""数据预处理"""
# 用中值填补缺失值
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())

Sex这一列的值male、female不能直接处理,分别将其转化为0、1

print(titanic['Sex'].unique())
# titanic.loc[0]表示第0行的样本
# titanic.loc[0, 'PassengerId']表示行为0,列为PassengerId的值
titanic.loc[titanic['Sex'] == 'male', 'Sex'] = 0
titanic.loc[titanic['Sex'] == 'female', 'Sex'] = 1

Embarked这一列有缺失值,用最常见的类别即‘S’填充,然后再将数据转化为int型

print(titanic['Embarked'].describe())
print(titanic['Embarked'].unique())
titanic['Embarked'] = titanic['Embarked'].fillna('S')
titanic.loc[titanic['Embarked'] == 'S', 'Embarked'] = 0
titanic.loc[titanic['Embarked'] == 'C', 'Embarked'] = 1
titanic.loc[titanic['Embarked'] == 'Q', 'Embarked'] = 2

2.3特征工程

“数据决定了机器学习的上限,而算法只是尽可能逼近这个上限”,这里的数据指的就是经过特征工程得到的数据。特征工程指的是把原始数据转变为模型的训练数据的过程,它的目的就是获取更好的训练数据特征,使得机器学习模型逼近这个上限。特征工程学习参考https://www.cnblogs.com/wxquare/p/5484636.html
案例中,通过提炼新特征并进行特征选择可以提高模型准确率。

提炼的3个新特征为FamilySize:SibSp和Parch的人数相加,看看是否家庭人数越多获救几率越大;NameLength:名字长度,外国名字越长地位越高;Title:在Name里提取的,类似Mr、Mrs、Dr表示性别职业

re.search():扫描整个字符串并返回第一个成功的匹配,没有就返回none
关于正则表达式:https://www.jb51.net/article/15707.htm

# 提炼新特征
titanic['FamilySize'] = titanic['SibSp'] + titanic['Parch']
titanic['NameLength'] = titanic['Name'].apply(lambda x: len(x))
import re
import pandas as pd
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)
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Dr": 5, "Rev": 6, "Major": 7, "Col": 8, "Mlle": 9,
                 "Mme": 10, "Don": 11, "Lady": 12, "Countess": 13, "Jonkheer": 14, "Sir": 15, "Capt": 16, "Ms": 17
                 }
for k, v in title_mapping.items():
    titles[titles == k] = v
print(pd.value_counts(titles))
titanic['Title'] = titles

SelectKBest():https://blog.csdn.net/sunshunli/article/details/82051138

# 特征选择
import numpy as np
from sklearn.feature_selection import SelectKBest, f_classif
import matplotlib.pyplot as plt
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", 
"FamilySize", "NameLength", "Title"]
selector = SelectKBest(f_classif, k=5)# 方差分析,计算方差分析(ANOVA)的F值 (组间均方 / 组内均方),选取前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')
plt.show()

可以发现“Pclass”、 "Sex"、“Fare”、"NameLength"和“Title”这5个特征比较重要

2.4基准模型

线性回归是机器学习最基础的算法,逻辑回归相比线性回归,代码更加简洁、而随机森林是集成学习,也不容易过拟合,所以我选择这三个模型,并通过交叉验证将初始样本分为3份,每次2份用作训练集,剩下1份作为测试集,这样可以有3次训练,得到3次训练结果,平均之后得到最后结果。

2.4.1线性回归

"""线性回归"""
from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import KFold
from sklearn import metrics
# 选择特征
predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
# 导入线性回归
alg = LinearRegression()
# 将样本分为3份进行交叉验证
kf = KFold(titanic.shape[0], n_folds=3, random_state=1)
predictions = []
for train_index, test_index in kf:
    # 用于训练的特征数据
    train_predictors = titanic[predictors].iloc[train_index, :]
    # 特征数据的label(即是否获救)
    train_target = titanic['Survived'].iloc[train_index]  # train_target = titanic['Survived'][train_index]
    # 训练线性回归模型
    alg.fit(train_predictors, train_target)    test_predictions = alg.predict(titanic[predictors].iloc[test_index, :])
    predictions.append(test_predictions)
# 线性回归得到的结果是在[0,1],转化为类别
import numpy as np
predictions = np.concatenate(predictions, axis=0)# predictions = np.hstack(predictions)
predictions[predictions > .5] = 1
predictions[predictions <= .5] = 0
# predictions = np.where(predictions > .5, 1, 0)
# 线性模型准确率
accuracy = sum(predictions == titanic['Survived']) / len(predictions)
print(accuracy)

输出线性回归准确率为

0.783389450056

得到的准确率有点低,我们尝试下逻辑回归模型

2.4.2逻辑回归

函数:cross_val_score(model_name, X,y, cv=k)
参数:1、模型函数名,如 LogisticRegression()2、训练集 3、测试属性 4、K折交叉验证
作用:验证某个模型在某个训练集上的稳定性,输出k个预测精度。

"""逻辑回归"""
from sklearn import cross_validation
from sklearn.linear_model import LogisticRegression
alg = LogisticRegression(random_state=1)
scores = cross_validation.cross_val_score(alg, titanic[predictors], titanic['Survived'], cv=3)
print(scores)
print(scores.mean())

输出逻辑回归准确率为

[ 0.78451178  0.78787879  0.79124579]
0.787878787879

准确率提高了一点

2.4.3随机森林

随机森林的随机体现在两点:1、取样本是随机的,且是有放回的 2、特征的选择是随机的,不一定所有的属性特征都要用到。森林表示生成多个决策树

函数:RandomForestClassifier()
参数解释:random_state = 1 表示此处代码多运行几次得到的随机值都是一样的,如果不设置,两次执行的随机值是不一样的;n_estimators=50 表示有50棵决策树;树的分裂的条件是: min_samples_split =4代表样本不停的分裂,某一个节点上的样本如果只有4个了 ,就不再继续分裂了;min_samples_leaf =2表示叶子节点的最小个数为2

"""随机森林"""
from sklearn import cross_validation
from sklearn.ensemble import RandomForestClassifier
alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=4, 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.81593714927

准确率超过了81%。后续还可以通过调整随机森林模型的参数看是否能继续提高准确率,但不是越高越好,可能会导致过拟合

2.5混合模型

混合模型是在竞赛中常用的办法:集成多个模型,得出每个模型的结果,并赋予每个模型权重,求出最后的平均结果。上面跑基准模型发现逻辑回归和随机森林效果更好,所以我集成了这两种模型。如果发现某个模型更好,权重可以更高(案例中随机森林权重是2,逻辑回归的是1)

predict_proba():https://blog.csdn.net/m0_37870649/article/details/79549142

# 混合模型
from sklearn.ensemble import GradientBoostingClassifier
import numpy as np
algorithms = [
    [RandomForestClassifier(random_state=1, n_estimators=20, min_samples_split=4, min_samples_leaf=2),
     ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'FamilySize', 'NameLength', 'Title']],
    [LogisticRegression(random_state=1),
     ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'FamilySize', 'NameLength', 'Title']]
]
kf = KFold(titanic.shape[0], n_folds=11, random_state=1)
predictions = []
for train, test in kf:
    train_target = titanic['Survived'].iloc[train]
    full_test_prediction = []
    for alg, predictors in algorithms:
        alg.fit(titanic[predictors].iloc[train, :], train_target)
        test_prediction = alg.predict_proba(titanic[predictors].iloc[test, :].astype(float))[:, 1]
        full_test_prediction.append(test_prediction)
    test_predictions = (full_test_prediction[0] * 2 + full_test_prediction[1]) / 3
    test_predictions[test_predictions > .5] = 1
    test_predictions[test_predictions <= .5] = 0
    predictions.append(test_predictions)
predictions = np.concatenate(predictions, axis=0)
accuracy = sum(predictions == titanic['Survived']) / len(predictions)
print(accuracy)

输出混合模型结果为

0.832772166105

总结:对于一般的简单机器学习,先进行数据探索,了解属性;再将原始数据经过预处理之后得到完整可处理的数据即数据清洗;再进行特征工程,得到重要特征;然后跑基准模型看看效果;复杂的数据可以尝试混合模型集成学习,具体情况具体分析。

参考视频
代码点这里

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

推荐阅读更多精彩内容