对kaggle不做过多介绍 都知道这是一个数据挖掘的圣地,泰坦尼克号事件也不多做介绍,马上进入正题
这个问题,分类,也就是撸模型,之后进行一步一步的优化
做机器学习,一上来直接撸出来最完美的模型几乎不可能,只能先构建一个baseline model之后在进行优化
首先拿到两组数据,一组模型训练数据,一组测试数据
train数据里面会告诉你那些人是未获救那些人是获救,而且是每份数据都会告诉你,一眼能看出来是监督式学习问题,分类问题
简单看一下数据,有这些内容
Passengerid 乘客id
Pclass 舱位等级
Name 姓名
Sex 性别
Age 年龄
SibSp 同胞数
Parch 父母与孩子人数
Ticket 船票信息
Fare 票价
Cabin 客舱位
Embarked 登船港口
大概字段信息就是这样子,大致看下数据,发现乘客id没啥卵用,乘客姓名也没啥卵用。有用的信息也就是 舱位等级,性别,年龄,同胞数,父母孩子数,船票信息,票价,船舱位,登船港口这9个数据
分析数据
numpy分析数据,pandas处理数据
先倒入库,并且读取数据
import numpy as np
import pandas as pd
train_data = pd.read_csv('train.csv')
>>>train_data.info()
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
突然发现 居然有两组数据(年龄,船舱位)有残缺,先放着,待会儿在看
先看看性别对存活率的影响
data_sex_0 = train_data.Sex[train_data.Survived == 0].value_counts()
data_sex_1 = train_data.Sex[train_data.Survived == 1].value_counts()
data_sex = pd.DataFrame({'获救':data_sex_1,'未获救':data_sex_0})
data_sex.plot(kind='bar',stacked=True)
看来性别对获救率影响挺大,是个非常重要的数据,待会儿创建模型不能忘了这组数据
看看舱位等级对存活率的影响
data_pclass_0 = train_data.Pclass[train_data.Survived==0].value_counts()
data_pclass_1 = train_data.Pclass[train_data.Survived==1].value_counts()
data_pclass = pd.DataFrame({'获救':data_pclass_1,'未获救':data_pclass_0})
data_pclass.plot(kind='bar',stacked=True)
原来1等舱的人存活概率那么大,三等舱的人存活概率那么小
再来看看这些乘客的年龄分布情况
data_age_0 = train_data.Age[train_data['Survived']==0].value_counts()
data_age_0 = data_age_0.sort_index()
data_age_1 = train_data.Age[train_data['Survived']==1].value_counts()
data_age_1 = data_age_1.sort_index()
data_age = pd.DataFrame({'获救':data_age_1,'未获救':data_age_0})
data_age_plot()
比较直观的看出来,曲线中间很多人未获救,获救几率较大的人群在老人和孩子中,可是这么重要的数据竟然有残缺,待会儿要对这组数据进行补全一下
刚才还有一组数据残缺非常大,对,就是Cabin这组
来看看这组数据
data_cabin_know = train_data.Survived[pd.notnull(train_data.Cabin)].value_counts()
data_cabin_unknow = train_data.Survived[pd.isnull(train_data.Cabin)].value_counts()
data_cabin = pd.DataFrame({'know Cabin':data_cabin_know,'unknow Cabin':data_cabin_unknow})
data_cabin.plot(kind='bar',stacked=True)
可以看出来 有没有记录Cabin对存活率影响还是挺大的 待会儿创建model 要记得加上这组数据
现在看看同胞 父母孩子数量对存活率的影响吧,计算方式和上面雷同,得到的图形分别是下面俩
好吧,这两组数据貌似没有明显的影响,看起来很一般,创建baseline的时候可以不用,最后优化的时候可以考虑添加进去这两组数据
Ticket先不做考虑,Fare 和 Embarked做出来的图:
貌似票价贵的 存活率高一点
貌似也没有特别明显的规律,能看出来S口登船的人比较多 仅此而已?
处理数据
好了,大致数据看完了,比较明显的就是女性,一等舱,老人小孩,已知船舱,票价贵 这些存活率比较高,其他的到真没看出来啥
刚才又一个很重要的数据 Age 有一部分残缺 试着将这部分数据补全,在构建baseline的时候,将age作为重要信息填进去
#需要提取的数据 包括特征值
age_df = train_data[['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)
#用得到的rfr模型进行未知年龄的预测
predictedAges = rfr.predict(unknown_age[:,1::])
#用预测到的数据填补缺失的数据
train_data.loc[(df.Age.isnull()),'Age'] = predictedAges
还有一个残缺非常严重的数据 Cabin 由于这部分数据残缺太过严重 就没办法补全了 简单的将数据分为Know 和 Unknow吧
train_data.loc[(df.Cabin.notnull()),'Cabin'] = 'Yes' train_data.loc[(df.Cabin.isnull(),'Cabin')] = 'No'
ok,数据整理基本完成了,在构建model之前,需要将数据进行特这个因子化 具体什么是特征因子化 自己查 不赘述
dummies_Cabin = pd.get_dummies(data_train['Cabin'],prefix='Cabin')
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')
现在将因子化之后的数据 和 train 数据放到一起,待会儿使用
df = pd.concat([data_train,dummies_Cabin,dummies_Embarked,dummies_Sex,dummies_Pclass],axis=1)
还有一部分不需要的数据和特征因子的参数数据,如果这些数据在构建model的时候加进去,可能会作为noise参杂入结果中,所以将这些数据删掉
df.drop(['Pclass','Name','Sex','Ticket','Cabin','Embarked'],axis=1,inplace=True)
现在查看一下数据
数据字段太多,后面有一部分数据没有截进来
重点是,Age和Fare这两组数据差值太大,这样的数据去构建baseline的话 很容易造成数据不收敛 做出来的model有误这样的情况,所以现对这两组数组做一个scale
#对变化幅度过大的数据进行scaling,避免造成不收敛的情况
scaler = preprocessing.StandardScaler()
age_scale_param = scaler.fit(df['Age'].values.reshape(-1,1))
df['Age_scaled'] = scaler.fit_transform(df['Age'].values.reshape(-1,1),age_scale_param)
fare_scale_param = scaler.fit(df['Fare'].values.reshape(-1,1))
df['Fare_scaled'] = scaler.fit_transform(df['Fare'].values.reshape(-1,1),fare_scale_param)
现在再来看看数据
现在好多了,这样的数据进行构建model才保险
构建Logistic Regression回归模型
也没多难,先提取需要的数据,在构建随机数森林,将train中的整理好的数据和Survived进行Fit,就可以得到回归模型
不多说,直接上代码
train_df = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np = train_df.as_matrix()
# y是Survival结果
y = train_np[:,0]
# x是特征属性值
x = train_np[:,1:]
#将结果fit到随机生成树中 先构建随机树森林 之后拟合
clf = linear_model.LogisticRegression(C=1.0,penalty='l1',tol=1e-6)
#此时的clf就是拟合出来的baselinear 最终生成数据就利用这个clf
clf.fit(x,y)
现在的clf就可以predict test数据了。不过重点是在对test数据进行predict之前,需要对数据进行预处理,就像之前对train数据进行处理的那样。
整个预处理过程整理就是这样子
#对test数据进行预处理 之后倒入生成的模型中进行测试
data_test = pd.read_csv('test.csv')
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()
#x是特征值 根据train特征值生成的模型进行填补缺失数据
x = null_age[:,1:]
predictedAges = rfr.predict(x)
data_test.loc[(data_test.Age.isnull()),'Age'] = predictedAges
#将Cabin有无记录分为两类 之后对数据进行因子化
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)
#对Age和Fare两项数据进行scale
df_test['Age_scaled'] = scaler.fit_transform(df_test['Age'].values.reshape(-1,1),age_scale_param)
df_test['Fare_scaled'] = scaler.fit_transform(df_test['Fare'].values.reshape(-1,1),fare_scale_param)
#对需要的数据进行提取test = df_test.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
预处理完成之后,就可以predict一下,生成数据了
利用之前的baseline model
predictions = clf.predict(test)
这样就算完成了整个的预测,最后一步将其写入csv文件就ok
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(),'Survived':predictions.astype(np.int32)})
result.to_csv('baseline.csv',index=False)
这只是建立了一个基础的模型, 要知道刚才还有一些数据没有用上,比如ticket,id,name 优化model的时候可以考虑加入他们