参考,机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾 http://www.cnblogs.com/zhizhan/p/5238908.html
机器学习(二) 如何做到Kaggle排名前2% http://www.jasongj.com/ml/classification/
一、认识数据
1.把csv文件读入成dataframe格式
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
def get_titanic_data():
train_data =pd.read_csv("../data/titanic/train.csv")
test_data = pd.read_csv("../data/titanic/test.csv")
return train_data, test_data
train_data, test_data = get_titanic_data()
2.data_train.info()
3.data_train.describe()mean
字段告诉我们,大概0.383838的人最后获救了,2/3等舱的人数比1等舱要多,平均乘客年龄大概是29.7岁
4.认识数据
看每个/多个属性和最后的survived之间关系
1.获救人数1/3
2.3等舱获救人数最多
3.年龄都有
头等舱年龄集中偏大
4.S口岸登船人数最多,SCQ递减
5.考虑不同舱位等级,获救情况不同?头等舱获救比例最高,2等舱50%,3等舱最低
年龄
登船口岸
性别?lady first
性别和舱位?
6.了解堂兄弟,亲人数目对于获救影响,1,2,3个亲属比无亲属以及亲属太过更容易获救
cabin缺失值太多,首先根据是否缺失对获救概率影响
import matplotlib.pyplot as plt
Survived_0 = data_train.Pclass[data_train.Survived==0].value_counts()
Survived_1 = data_train.Pclass[data_train.Survived==1].value_counts()
df=pd.DataFrame({u'获救':Survived_1, u'未获救':Survived_0})
df.plot(kind='bar',stacked=True)
plt.title(u"各乘客等级的获救情况")
plt.xlabel(u"乘客等级")
plt.ylabel(u"人数")
plt.show()
进行特征选择时,判断每一个特征(连续,离散,相等,数目,考虑派生特征)对幸存值的影响,去除关联特征
二、数据预处理
1.RF拟合丢失的年龄数据
from sklearn.ensemble import RandomForestRegressor
def set_missing_ages(df):
#把已有数值型特征取出来丢进Random Forest Regressor中
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即目标年龄
y = known_age[:,0]
#x即特征属性值
X = known_age[:,1:]
#fit到RandomForestRegressor中
rfr = RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1)
rfr.fit(X,y)
#用得到的模型进行未知年龄结果预测
predictedAges = rfr.predict(unknown_age[:,1::])
#用得到的预测结果填补原缺失数据
df.loc[(df.Age.isnull()),'Age']=predictedAges
return df,rfr
2.将Cabin列,填充为空(NO)非空(YES)
def set_Cabin_type(df):
df.loc[(df.Cabin.notnull()),'Cabin']="Yes"
df.loc[(df.Cabin.isnull()),'Cabin']="No"
return df
data_train,rfr = set_missing_ages(data_train)
data_train=set_Cabin_type(data_train)
3.类目型的特征因子化#one-hot编码
转为’Cabin_yes','Cabin_no'Pclass_1,Pclass_2,pclass_3
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')
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,implcae=True)
4.scaling,将一些变化幅度较大的特征化到[-1,1]之内。
import sklearn.preprocessing as preprocessing
scaler = preprocessing.StandardScaler()
age_scale_para = scaler.fit(df['Age'])
df['Age_scaled']=scaler.fit_transform(df['Age'],age_scale_param)
fare_scale_param = scaler.fit(df['Fare'])
df['Fare_scaled']=scaler.fit_transform(df['Fare'], fare_scale_prram)
三、建模----逻辑回归
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即Survival结果
y = train_np[:,0]
#x即特征属性值
X = train_np[:,1:]
#fit到RandomForestRegressor中
clf = linear_model.LogisticRegression(C=1.0,penalty='11',tol=1e-6)
clf.fit(X,y)
四、test_data也需要预处理
结果预测
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("/Users/Hanxiaoyang/Titanic_data/logistic_regression_predictions.csv", index=False)
五、系统优化
1.年龄分段,
老人小孩受照顾,5岁一个年龄段
未考虑name和ticket
name中包含title?
ticket是否相同,相同为同一家人更容易幸存,不同幸存率低?
去掉关联特征(兄弟,父母),增加派生特征(title)?
2.将model系数和feature关联
pd.DataFrame({"columns":list(train_df.columns)[1:], "coef":list(clf.coef_.T)})
数值正的越大越正相关,负的越大越负相关
3.交叉验证
将train数据做交叉验证
from sklearn import cross_validation
#简单看看打分情况
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6)
all_data = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
X = all_data.as_matrix()[:,1:]
y = all_data.as_matrix()[:,0]
print cross_validation.cross_val_score(clf, X, y, cv=5)
4.将bad case人眼审核,发现信息
根据训练数据和交叉验证数据不断尝试
# 分割数据,按照 训练数据:cv数据 = 7:3的比例
split_train, split_cv = cross_validation.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 = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6)
clf.fit(train_df.as_matrix()[:,1:], train_df.as_matrix()[:,0])
# 对cross validation数据进行预测
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_train = pd.read_csv("/Users/HanXiaoyang/Titanic_data/Train.csv")
bad_cases = origin_data_train.loc[origin_data_train['PassengerId'].isin(split_cv[predictions != cv_df.as_matrix()[:,0]]['PassengerId'].values)]
bad_cases
5.考虑过拟合欠拟合learning curve
六、模型融合
有一堆在同一份数据集上训练得到的分类器(比如logistic regression,SVM,KNN,random forest,神经网络),
那我们让他们都分别去做判定,然后对结果做投票统计,取票数最多的结果为最后结果。
如果模型出现过拟合现在,一定是在我们的训练上出现拟合过度造成的对吧。
不要用全部的训练集,每次取训练集的一个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即Survival结果
y = train_np[:, 0]
# X即特征属性值
X = train_np[:, 1:]
# fit到BaggingRegressor之中
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6)
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 = df_test.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("/Users/HanXiaoyang/Titanic_data/logistic_regression_bagging_predictions.csv", index=False)