机器学习(十一)使用sklearn对kaggle的Titanic进行建模

转自寒老师的七月算法ML课程
数据集下载地址:https://www.kaggle.com/c/titanic

# -*- coding: utf-8 -*-
"""
Created on Tue Nov 01 09:04:12 2016

@author: Sirius

kaggle上的Titanic经典案例,建立一个模型,预测乘客是否获救,二分类问题
记:寒老师七月算法ML课程课后笔记
"""

import pandas as pd
import numpy as np

data_train=pd.read_csv('train.csv')
data_test=pd.read_csv('test.csv')

"""
trian数据集,11个属性+1获救情况
Index 
PassengerId => 乘客ID  --891
Pclass => 乘客等级(1/2/3等舱位) --891 --离散值
Name => 乘客姓名 --891 --文本特征
Sex => 性别 --891 --离散值
Age => 年龄  --714,不全  --连续值
SibSp => 堂兄弟/妹个数 --891 --离散值
Parch => 父母与小孩个数 --891 --离散值
Ticket => 船票信息 --891 --文本信息
Fare => 票价 --891 --连续值
Cabin => 客舱--204,不全 
Embarked => 登船港口 --889 --离散值
"""

"""
   通过对数据进行统计分析,Age和Cabin这两个属性对是否获救的影响很大,因此要设法不全
通常遇到缺值的情况,我们会有几种常见的处理方式:---
   1.如果缺值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,
     可能反倒带入noise,影响最后的结果了。
   2.如果缺值的样本适中,而该属性非连续值特征属性(比如说类目属性),
     那就把NaN作为一个新类别,加到类别特征中。
   3.如果缺值的样本适中,而该属性为连续值特征属性,有时候我们会考
     虑给定一个step(比如这里的age,我们可以考虑每隔2/3岁为一个步长),
     然后把它离散化,之后把NaN作为一个type加到属性类目中。
   4.有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。
本例中,后两种处理方式应该都是可行的,我们先试试拟合补全吧(虽然说没有
    特别多的背景可供我们拟合,这不一定是一个多么好的选择)
"""

#由于Cabin缺失的值较多,因此用方式2处理,有cabin信息则为1,没有则为0
def set_Cabin_type(df):
    df.loc[(df.Cabin.notnull()),'Cabin']='Yes'
    df.loc[(df.Cabin.isnull()),'Cabin']='No'
    return df
data_train=set_Cabin_type(data_train)

#Age信息缺失适中,通过RandForest拟合
from sklearn.ensemble import RandomForestRegressor

def set_missing_ages(df):
    #把已有数值型特征喂给RandomForestRegressor
    age_df=df[['Age','Fare','Parch','SibSp','Pclass']]

    known_age=age_df[age_df.Age.notnull()].as_matrix()
    unknown_age=age_df[age_df.Age.isnull()].as_matrix()

    y=known_age[:,0]#目标输出
    X=known_age[:,1:]#输入特征值

    rfr=RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1)
    rfr.fit(X,y)

    predictedAges=rfr.predict(unknown_age[:,1::])

    #y用预测得到的结果填补缺失数据
    df.loc[(df.Age.isnull()),'Age']=predictedAges

    return df,rfr 

data_train,rfr=set_missing_ages(data_train)   


"""
----------------------对离散值特征进行one-hot编码处理----------------------------

以Embarked为例,原本一个属性维度,因为其取值可以是[‘S’,’C’,’Q‘],而将其平展开为’Embarked_C’,’Embarked_S’, ‘Embarked_Q’三个属性
原本Embarked取值为S的,在此处的”Embarked_S”下取值为1,在’Embarked_C’, ‘Embarked_Q’下取值为0
原本Embarked取值为C的,在此处的”Embarked_C”下取值为1,在’Embarked_S’, ‘Embarked_Q’下取值为0
原本Embarked取值为Q的,在此处的”Embarked_Q”下取值为1,在’Embarked_C’, ‘Embarked_S’下取值为0

"""
#Cabin原本只有yes和no,现在扩展为Cabin_yes和Cabin_no两个属性
dummies_Cabin=pd.get_dummies(data_train['Cabin'],prefix='Cabin')

#Embarked由原来三个值S\C\Q扩展为Embarked_C、Embarked_S、Embarked_C三个属性
dummies_Embarked=pd.get_dummies(data_train['Embarked'],prefix='Embarked')

dummies_Sex=pd.get_dummies(data_train['Sex'],prefix='Sex')

dummies_Pclass=pd.get_dummies(data_train['Pclass'],prefix='Pclass')

df=pd.concat([data_train,dummies_Cabin,dummies_Embarked,dummies_Sex,dummies_Pclass],axis=1)

df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True)



"""
-------------------------对连续值特征进行标准化------------------------
"""
import sklearn.preprocessing as preprocessing
scaler=preprocessing.StandardScaler()
age_scaler_param=scaler.fit(df['Age'])
df['Age_scaled']=scaler.fit_transform(df['Age'],age_scaler_param)

fare_scale_param = scaler.fit(df['Fare'])
df['Fare_scaled'] = scaler.fit_transform(df['Fare'], fare_scale_param)



"""
-----------------------向量化,转为numpy格式矩阵---------------------------
"""
from sklearn import linear_model

train_df=df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np=train_df.as_matrix()

y=train_np[:,0]#survival的结果

X=train_np[:,1:]

clf=linear_model.LogisticRegression(C=1.0,penalty='l1',tol=1e-6) #L1正则,惩罚因子1,最终误差在1e-6下
clf.fit(X,y)
model_score=clf.score(X,y) #0.809

"""
------------------对测试集数据进行相同的处理和预测------------------------------

"""

data_test.loc[(data_test.Fare.isnull()),'Fare']=0

tmp_df=data_test[['Age','Fare','Parch','SibSp','Pclass']]
null_age=tmp_df[data_test.Age.isnull()].as_matrix()
X1=null_age[:,1:]
#用同样的特征属性X输入到RandomForestRegressor中,填补年龄空缺
predictedAge=rfr.predict(X1)
data_test.loc[(data_test.Age.isnull()),'Age']=predictedAge

data_test=set_Cabin_type(data_test)

dummies_Cabin = pd.get_dummies(data_test['Cabin'], prefix= 'Cabin')
dummies_Embarked = pd.get_dummies(data_test['Embarked'], prefix= 'Embarked')
dummies_Sex = pd.get_dummies(data_test['Sex'], prefix= 'Sex')
dummies_Pclass = pd.get_dummies(data_test['Pclass'], prefix= 'Pclass')

df_test = pd.concat([data_test, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass], axis=1)
df_test.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True)
df_test['Age_scaled'] = scaler.fit_transform(df_test['Age'], age_scaler_param)
df_test['Fare_scaled'] = scaler.fit_transform(df_test['Fare'], fare_scale_param)

test = df_test.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
#测试模型
predictions=clf.predict(test)
result=pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(),'Survived':predictions.astype(np.int32)})
result.to_csv("logistic_regression_predictions1.csv",index=False)

da=pd.read_csv("logistic_regression_predictions1.csv")




"""
-------------------------通过交叉验证判断模型是否过拟合----------------------------------------
"""
import numpy as np
import matplotlib.pyplot as plt
from sklearn.learning_curve import learning_curve

# 用sklearn的learning_curve得到training_score和cv_score,使用matplotlib画出learning curve
def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, n_jobs=1, 
                        train_sizes=np.linspace(.05, 1., 20), verbose=0, plot=True):
    """
    画出data在某模型上的learning curve.
    参数解释
    ----------
    estimator : 你用的分类器。
    title : 表格的标题。
    X : 输入的feature,numpy类型
    y : 输入的target vector
    ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点
    cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份)
    n_jobs : 并行的的任务数(默认1)
    """
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes, verbose=verbose)

    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)

    if plot:
        plt.figure()
        plt.title(title)
        if ylim is not None:
            plt.ylim(*ylim)
        plt.xlabel(u"训练样本数")
        plt.ylabel(u"得分")
        plt.gca().invert_yaxis()
        plt.grid()

        plt.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, 
                         alpha=0.1, color="b")
        plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, 
                         alpha=0.1, color="r")
        plt.plot(train_sizes, train_scores_mean, 'o-', color="b", label=u"训练集上得分")
        plt.plot(train_sizes, test_scores_mean, 'o-', color="r", label=u"交叉验证集上得分")

        plt.legend(loc="best")

        plt.draw()
        plt.gca().invert_yaxis()
        plt.show()

    midpoint = ((train_scores_mean[-1] + train_scores_std[-1]) + (test_scores_mean[-1] - test_scores_std[-1])) / 2
    diff = (train_scores_mean[-1] + train_scores_std[-1]) - (test_scores_mean[-1] - test_scores_std[-1])
    return midpoint, diff

#plot_learning_curve(clf, u"学习曲线", X, y)

"""
从learning curve上没有发现过拟合现象(overfitting的表现一般是训练集上得分高,
而交叉验证集上要低很多,中间的gap比较大),因此可以再mining些feature来训练
"""

#通过模型系数theta来查看各个属性与结果的相关程度
pd.DataFrame({"columes":list(train_df.columns)[1:],"coef":list(clf.coef_.T)})
"""
正相关和负相关
                 coef      columes
0     [-0.3442288083]        SibSp
1   [-0.104931485646]        Parch
2               [0.0]     Cabin_No
3    [0.902141633979]    Cabin_Yes  有cabin信息获救几率大
4               [0.0]   Embarked_C
5               [0.0]   Embarked_Q
6   [-0.417262701772]   Embarked_S
7     [1.95657801471]   Sex_female  女性获救几率大,正相关
8   [-0.677418530198]     Sex_male  头等舱获救几率大
9    [0.341141757161]     Pclass_1
10              [0.0]     Pclass_2
11   [-1.19414131133]     Pclass_3
12  [-0.523782222235]   Age_scaled  年龄越小获救的几率越大,负相关
13  [0.0844327966037]  Fare_scaled
"""



"""
-------------一般是把linearRegressor作为baseline,然后使用不同的分类器比如SVM、RadomForest、NN等--------

"""


"""
假设现在模型出现overfitting,那我们干脆就不要用全部的训练集,每次取训练集的一个subset,做训练,这样,
我们虽然用的是同一个机器学习算法,但是得到的模型却是不一样的;同时,因为我们没有任何一份子数据集是全的,因此即使出现过拟合,
也是在子训练集上出现过拟合,而不是全体数据上,这样做一个融合,可能对最后的结果有一定的帮助。对,这就是常用的Bagging。
"""

from sklearn.ensemble import BaggingRegressor

train_df=df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*|Mother|Child|Family|Title')
train_np=train_df.as_matrix()

y=train_np[:,0]
X=train_np[:,1:]

clf=linear_model.LogisticRegression(C=1.0,penalty='l1',tol=1e-6)
bagging_clf=BaggingRegressor(clf,n_estimators=10,max_samples=0.8,max_features=1.0,
                             bootstrap=True,bootstrap_features=False,n_jobs=1)
bagging_clf.fit(X,y)


test_df=df.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*|Mother|Child|Family|Title')
predictions=bagging_clf.predict(test)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(), 'Survived':predictions.astype(np.int32)})
result.to_csv("logistic_regression_predictions2.csv", index=False)












  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值