kaggle入门,跟着牛人博客撸模型
博客地址:
http://blog.csdn.net/han_xiaoyang/article/details/49797143
原文的代码有个小问题,边学边调,收获颇丰。
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
"""
第一步,看数据
1、查看数据基本摘要,知道都有些什么属性,大概是什么
2、通过画图,找关系,了解属性对结果的影响,找特征
"""
data_train = pd.read_csv('/Users/lee/Desktop/ml/titanic/train.csv')
data_test = pd.read_csv('/Users/lee/Desktop/ml/titanic/test.csv')
#1、查看数据摘要
#命令行输入或打印
#data_train.info()
#2、画图,画各种可以想象到的图
fig1 = plt.figure(1) #创建画板,并且指向最后一张纸
fig1.set(alpha = 0.2) #color
plt.subplot2grid((4,2),(0,0)) #rows=2 clos=3 begin at (0,0)
#value_counts()是pandas中的顶级方法,用于任何数组或序列
data_train.Survived.value_counts().plot(kind='bar')
plt.title(u"survived") #标题 unic编码
plt.ylabel(u"number")
plt.subplot2grid((4,2),(0,1))
data_train.Pclass.value_counts().plot(kind='bar')
plt.title('Pclass')
plt.subplot2grid((4,2),(1,0))
data_train.Sex.value_counts().plot(kind='bar')
plt.title('Sex')
plt.subplot2grid((4,2),(1,1))
data_train.SibSp.value_counts().plot(kind='bar')
plt.title('SibSp')
plt.subplot2grid((4,2),(2,0))
data_train.Parch.value_counts().plot(kind='bar')
plt.title('Parch')
plt.subplot2grid((4,2),(2,1))
data_train.Fare.apply(np.round).value_counts().plot(kind='bar')
plt.title('Sex')
plt.subplot2grid((4,2),(3,0))
data_train.Embarked.value_counts().plot(kind='bar')
plt.title('Embarked')
#plt.xlabel(u"x轴")
"""
第二步 数据预处理(特征工程)
1、补全缺失数据
2、无量纲化
3、处理定性特征(哑编码)
特征工程在jasonfreak的博客里写的很多
博客地址:http://www.cnblogs.com/jasonfreak/p/5448385.html
另:要对traindata和testdata做同样的处理
我觉得这里写成函数会比较方便,下一次改进
"""
#1、补全缺失的年龄
from sklearn.preprocessing import Imputer
def set_age_fill(df):
AgeFill = Imputer(axis=1).fit_transform((df.index,df.Age))
df.loc[:,'Age'] = AgeFill[1].T
return df
AgeFill = set_age_fill(data_train)
AgeFill2 = set_age_fill(data_test)
#test 数据fare缺了一个值
def set_fare_fill(df):
AgeFill = Imputer(axis=1).fit_transform((df.index,df.Age))
df.loc[:,'Fare'] = AgeFill[1].T
return df
AgeFill2 = set_fare_fill(data_test)
#Cabin也有缺失,粗略的就用Yes表示有数据,No表示缺失
def set_Cabin_type(df):
#df.loc() 根据标签选取列
#参数为选取规则[行规则,列规则]
df.loc[(df.Cabin.notnull()),'Cabin'] = 'Yes'
df.loc[(df.Cabin.isnull()),'Cabin'] = 'No'
return df
cabinFill = set_Cabin_type(AgeFill)
cabinFill2 = set_Cabin_type(AgeFill2)
# =============================================================================
# #2、哑编码
# from sklearn.preprocessing import OneHotEncoder
# one = OneHotEncoder().fit_transform(data_train)
# 这个方法单独试能运行,不过没在这里面用
# 这里用的另一种
# =============================================================================
#哑编码因子化
#get_dummies()将传入数组做OneHotEncoder
#prefix参数是输出列的名字
dummies_Cabin = pd.get_dummies(cabinFill['Cabin'],prefix='Cabin')
dummies_Embarked = pd.get_dummies(cabinFill['Embarked'],prefix='Embarked')
dummies_Sex = pd.get_dummies(cabinFill['Sex'],prefix='Sex')
dummies_Pclass = pd.get_dummies(cabinFill['Pclass'],prefix='Pclass')
dummies_Cabin2 = pd.get_dummies(cabinFill2['Cabin'],prefix='Cabin')
dummies_Embarked2 = pd.get_dummies(cabinFill2['Embarked'],prefix='Embarked')
dummies_Sex2 = pd.get_dummies(cabinFill2['Sex'],prefix='Sex')
dummies_Pclass2 = pd.get_dummies(cabinFill2['Pclass'],prefix='Pclass')
#合并函数
#axis=1 列拼接
#inplace=True, 直接修改原数组名的数据
df = pd.concat([cabinFill, dummies_Cabin,dummies_Embarked,dummies_Sex,dummies_Pclass],axis=1)
df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'],axis=1,inplace=True)
df2 = pd.concat([cabinFill2, dummies_Cabin2,dummies_Embarked2,dummies_Sex2,dummies_Pclass2],axis=1)
df2.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'],axis=1,inplace=True)
#3、归一化
#还没弄明白为什么StandardScaler后面的参数不可以是一维数组
#这里原文代码运行不了,自己改成这样
from sklearn.preprocessing import StandardScaler
dd = pd.concat([cabinFill['Age'],cabinFill['Fare']],axis=1)
a = StandardScaler().fit_transform(dd)
#!!transform之后的数据是array没有index
#用concat操作之后的df没有叫Age的列
#df = pd.concat([df,a],axis=1)
df['Age'] = a[:,0]
df['Fare'] = a[:,1]
dd2 = pd.concat([cabinFill2['Age'],cabinFill2['Fare']],axis=1)
a2 = StandardScaler().fit_transform(dd2)
df2['Age'] = a2[:,0]
df2['Fare'] = a2[:,1]
"""
第三步、撸出一个Baseline
1、提取特征字段
2、用traindata训练模型
3、预测
这里用的Logistic Regression,这一步做出来的是BaseLine,作为后续改进的参考
"""
from sklearn.linear_model import LogisticRegression
#1、提取特征字段转换为numpy
#filter 参数regex 指用正则表达式筛选
train_df = df.filter(regex='Survived|Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
test_df = df2.filter(regex='Survived|Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
#转化为矩阵形式
train_np = train_df.as_matrix()
#y 存活结果
y = train_np[:,0]
#x 特征值
X = train_np[:,1:]
#2、训练模型
# 参数penalty 解决过拟合的惩罚项,默认l2
# C 正则化参数
# l1是在l2正则化之后还过拟合,或者想要让不重要的特征系数归零,让模型系数稀疏化的时候使用
# tol 容忍度
# solver 优化方法
# 1)liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
# 2)lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# 3)newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
# 4)sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候,SAG是一种线性收敛算法,这个速度远比SGD快。
# 注:从上面的描述可以看出,newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。
# http://blog.csdn.net/code_caq/article/details/72027012
clf = LogisticRegression(C=1.0,penalty='l1',tol=1e-6)
# clf 即为模型
clf.fit(X,y)
#3、预测
predictions = clf.predict(test_df)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(),'Survived':predictions.astype(np.int32)})
result.to_csv('/Users/lee/Desktop/ml/titanic/result.csv',index=False)
"""
第四步、评估Base Line
接下来要对Baseline进行升级,升级前要评估、检测
1、相关系数分析
2、交叉验证(重要)
3、分析badcase
4、过拟合、欠拟合检查
"""
#1、看相关系数
#命令行输入或者print
pd.DataFrame({'cloumns':list(train_df.columns)[1:],'coef':list(clf.coef_.T)})
#可能是我前面处理age和fare不一样,所以得到的系数和原文有差距,不过不大
#2、交叉验证
#通过交叉验证检查模型的准确度
#命令行输入或者print
#第一个参数是分类器,cv是不同的交叉验证方法,int对象用5
from sklearn import model_selection
model_selection.cross_val_score(clf,X,y,cv=5)
#3、数据分割,人工查看bad case
#从bad case和属性的实际意义出发,再找特征
#找到新特征,再来一遍一二三四
split_train, split_cv = model_selection.train_test_split(df,test_size=0.3,random_state=0)
train_df = split_train.filter(regex='Survived|Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
#生成模型
clf = LogisticRegression(C=1.0,penalty='l1',tol=1e-6)
clf.fit(train_df.as_matrix()[:,1:],train_df.as_matrix()[:,0])
#预测
cv_df = split_cv.filter(regex='Survived|Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
predictions = clf.predict(cv_df.as_matrix()[:,1:])
origin_data = data_train
bad_cases = origin_data.loc[origin_data['PassengerId'].isin(split_cv[predictions != cv_df.as_matrix()[:,0]]['PassengerId'].values)]
#4、检验学习曲线,看交叉验证是否过拟合或者欠拟合
from sklearn.model_selection import learning_curve
#自定义函数
#计算training_score 和 cv_score 并把结果画图
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,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('Samples')
plt.ylabel('Score')
#坐标轴反向
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='trainScore')
plt.plot(train_sizes,test_scores_mean,'o-',color='r',label='crossScore')
#参数loc 调整legend的位置
plt.legend(loc='best')
plt.draw()
plt.gca().invert_yaxis()
#不理解这两个值是干嘛的
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
#midpoint,diff = plot_learning_curve(clf,u"学习曲线",X,y)
"""
第五步、升级——模型融合(重要)
模型融合是指:采用多个模型进行预测,输出最靠谱的那一个
模型不够数据来凑,数据不够数学来凑
"""
#模型融合 ensemble
#当不会用多个模型的时候,可以通过数据
#不同的数据训练出来的模型不同
from sklearn.ensemble import BaggingRegressor
train_df = df.filter(regex='Survived|Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np = train_df.as_matrix()
y = train_np[:,0]
x = train_np[:,1:]
clf = LogisticRegression(C=1.0,penalty='l1',tol=1e-6)
#应用到BaggingRegressor中
#参数 n_estimators 子模型的个数
#max_samples 从x_train抽取去训练基估计器的样本数量。int 代表抽取数量,float代表抽取比例
#bootstrap 决定样本子集的抽样方式(有放回和不放回)
bagging_clf = BaggingRegressor(clf,n_estimators=20,max_samples=0.8,max_features=
1.0, bootstrap=True,bootstrap_features=False,n_jobs=1)
bagging_clf.fit(x,y)
test = df2.filter(regex='Age|SibSp|Parch|Fare|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
predictions = bagging_clf.predict(test)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(), 'Survived':predictions.astype(np.int32)})
result.to_csv('/Users/lee/Desktop/ml/titanic/ensemble.csv',index=False)
网友评论