1. 加载数据
由于针对训练数据集、测试数据集均要做空值填充、编码转换、离散化、归一化等处理,因此可以加载训练数据集、测试数据集对其统一进行处理。
train_file = r'datasets/train.csv' test_file = r'datasets/test.csv' data = pd.read_csv(train_file,index_col='PassengerId') data_sub = pd.read_csv(test_file,index_col='PassengerId') data_copy = data.copy() del data_copy['Survived'] data_all = pd.concat([data_copy,data_sub]) #数据合并
data_all.info() #查看数据情况
输出
<class ‘pandas.core.frame.DataFrame’>
Int64Index: 1309 entries, 1 to 1309
Data columns (total 10 columns):
Pclass 1309 non-null int64
Name 1309 non-null object
Sex 1309 non-null object
Age 1046 non-null float64
SibSp 1309 non-null int64
Parch 1309 non-null int64
Ticket 1309 non-null object
Fare 1308 non-null float64
Cabin 295 non-null object
Embarked 1307 non-null object
dtypes: float64(2), int64(3), object(5)
memory usage: 112.5+ KB
2. 特征工程
(1)填充空值
需要填充空值的字段包括:Age
、Fare
、Embarked
三个字段,其中使用众数填充Embarked``Age
的空值 ,使用均值填充Fare``Age
的空值。
由于Name
里有Mr,Mrs,Miss等称谓,可使用称谓对应的年龄的均值来填充Age
的空值。
#填充Fare与Embark空值 Embarked_mode = data_all.Embarked.mode()[0] #计算众数 data_all.Embarked=data_all.Embarked.fillna(Embarked_mode) #众数填充 Fare_mean = data_all[data_all.Pclass == 3].Fare.mean() #计算均值 data_all.Fare=data_all.Fare.fillna(Fare_mean) #均值填充 #根据Title填充Age空值 def get_title(name): title_search = re.search("([A-Za-z]+)\.",name) if title_search: return title_search.group(1) return "" data_all['Title'] = data_all.Name.apply(get_title) for title in data_all[data_all.Age.isnull()].Title.unique(): title_age_mean = data_all[data_all.Title == title].Age.mean() data_all.loc[data_all.Age.isnull()*data_all.Title == title,'Age'] = title_age_mean
(2)Age空值离散化
#年龄离散化 bins=[0,14,30,45,60,80] cats=pd.cut(data_all.Age.as_matrix(),bins) data_all.Age=cats.codes
(3)Fare归一化
使用StandardScaler
方法对Fare归一化处理
scaler=StandardScaler() data_all.Fare=scaler.fit_transform(data_all.Fare.values.reshape(-1,1))
(4)形成新属性FamilySize
data_all['FamilySize'] = data_all.Parch + data_all.SibSp
(5)One-Hot Encoding
针对Embarked
(‘S’, ‘C’, 'Q’三个取值)、Pclass
(1,2,3三个取值)字段,若简单的将其映射为数值0 , 1 , 2 0,1,20,1,2,训练时模型会认为该属性的数据具有线性特征。
机器学习中,一般将离散型特征(标称属性、序数属性)的每个取值都看成一种状态,若该特征中有N NN个不相同的取值,可通过One-Hot Encoding(独热编码),将其转换为N NN个状态,只有一个状态位值为1 11,其他状态位都是0 00,即将其转换为N NN个二元特征。使得模型具有较强的非线性能力。
对于Sex
、Pclass
、Embarked
属性使用pd.get_dummies
方法,将其转换为One-hot向量,如将Embarked
转换为[ 1 , 0 , 0 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 1 ] [1,0,0],[0,1,0],[0,0,1][1,0,0],[0,1,0],[0,0,1],
对于Cabin
,将其展开为两个属性:数据中Cabin
值为空的Cabin_null取值为1,Cabin_nnull
取值为0;Cabin
值不为空的Cabin_null
取值为1,Cabin_nnull
取值为0。
Sex_dummies = pd.get_dummies(data_all.Sex, prefix= 'Sex') Pclass_dummies = pd.get_dummies(data_all.Pclass,prefix= 'Pclass') Embarked_dummies = pd.get_dummies(data_all.Embarked,prefix= 'Embarked') data_all['Cabin_null'] = np.array(data_all.Cabin.isnull()).astype(np.int32) data_all['Cabin_nnull'] = np.array(data_all.Cabin.notnull()).astype(np.int32)
各个特征(属性)的处理总结如下
属性名 | 处理方式 |
Pclass | 形成One-Hot向量 |
Name | 未处理 |
Sex | 形成One-Hot向量 |
Age | 根据称谓填充空值后,离散化 |
SibSp | 形成新属性FamilySize |
Parch | |
Ticket | 未处理 |
Fare | 归一化 |
Cabin | 形成One-Hot向量 |
Embarked | 形成One-Hot向量 |
构建训练数据:
data_all = pd.concat([data_all, Sex_dummies, Pclass_dummies,Embarked_dummies], axis=1) feature = [ 'Age','Fare','FamilySize','Cabin_null','Cabin_nnull','Sex_female','Sex_male','Pclass_1','Pclass_2','Pclass_3','Embarked_C','Embarked_Q','Embarked_S'] X = data_all.loc[data.index][feature] y = data.Survived
3. 模型训练
(1)组合分类器
组合分类器将多个不同类型的分类器(例如逻辑回归,SVM,随机森林)的预测结果进行组合,将多数分类器输出的结果作为最终的预测结果(hard voting classifier)。如果所有的分类器都能够预测类别的概率(拥有predict_proba方法),可将平均概率最高的结果作为最终的预测结果(soft voting classifier)通常比hard voting classifier效果好。
(2)参数优化
机器学习中的一项主要工作是参数优化(俗称“调参”)。sklearn提供了GridSearchCV
方法,它网格式的自动遍历提供的参数组合,通过交叉验证确定最优化结果的参数(可通过best_params_
属性查看)。
本文使用的分类器包括:随机森林、支持向量机、GBDT和神经网络。
from sklearn.model_selection import GridSearchCV, StratifiedKFold kfold = StratifiedKFold(n_splits=10) clf_RF = RF() rf_param_grid = {"max_depth": [None], "max_features": [1, 3, 10], "min_samples_split": [2, 3, 10], "min_samples_leaf": [1, 3, 10], "bootstrap": [False], "n_estimators" :[100,300,500], "criterion": ["gini"]} gsRF = GridSearchCV(clf_RF,param_grid = rf_param_grid, cv=kfold,scoring="accuracy", n_jobs= 4, verbose = 1) gsRF.fit(X,y) rf_best = gsRF.best_estimator_ clf_SVC = SVC(probability=True) svc_param_grid = {'kernel': ['rbf'], 'gamma': [ 0.001, 0.01, 0.1, 1], 'C': [1, 10, 50, 100,200,300, 1000]} gsSVC = GridSearchCV(clf_SVC,param_grid = svc_param_grid, cv=kfold, scoring="accuracy", n_jobs= 4, verbose = 1) gsSVC.fit(X,y) svm_best = gsSVC.best_estimator_ clf_GB = GB() gb_param_grid = {'loss' : ['deviance'], 'n_estimators' : [100,300,500], 'learning_rate': [0.1, 0.05, 0.01], 'max_depth': [4, 8], 'min_samples_leaf': [100,150], 'max_features': [0.3, 0.1]} gsGB = GridSearchCV(clf_GB,param_grid = gb_param_grid, cv=kfold, scoring="accuracy", n_jobs= 4, verbose = 1) gsGB.fit(X,y) gb_best = gsGB.best_estimator_ clf_MLP = MLP() mlp_param_grid = {'hidden_layer_sizes' : [100,200,300,400,500], 'activation' : ['relu'], 'solver' : ['adam'], 'learning_rate_init': [0.01, 0.001], 'max_iter': [5000]} gsMLP = GridSearchCV(clf_MLP,param_grid = mlp_param_grid, cv=kfold, scoring="accuracy", n_jobs= 4, verbose = 1) gsMLP.fit(X,y) mlp_best = gsMLP.best_estimator_ votingC = VotingClassifier(estimators=[('clf_GB', gb_best), ('clf_RF', rf_best),('clf_SVC', svm_best), ('clf_MLP',mlp_best)],voting='soft', n_jobs=4) votingC = votingC.fit(X, y)
4. 模型部署
使用predict
方法预测,将生成的结果文件在Kaggle页面点击Submit Predictions进行提交,Kaggle会给出准确率和排名。
X_sub = data_all.loc[data_sub.index][feature] #提取测试数据特征 y_sub = votingC.predict(X_sub) #使用模型预测数据标签 result = pd.DataFrame({'PassengerId':data_sub.index,'Survived':y_sub}) result.to_csv(r'D:\[DataSet]\1_Titanic\submission.csv', index=False)