前回の記事の続きです。
前回の記事では、主にデータの可視化を行ない、特徴量を確認しました。
今回は、モデルを学習しsubmitまでしていきます。
特徴量エンジニアリング
ここでは実際に、読み込んだデータをアルゴリズムで学習するための形に変換していきます。
Sexカラム
Sexカラムには、maleとfemakeといった文字列が入っており、そのままでは処理が難しいので数値に変換します。
data = pd.concat([train, test], sort=False)
data['Sex'].replace(['male', 'female'], [0, 1], inplace=True)
Embarkedカラム
EmbarkedカラムはS、C、Qという文字列が入っていたので、数値に変換します。
data['Embarked'].fillna(('S'), inplace=True)
data['Embarked'] = data['Embarked'].map({'S': 0, 'C': 1, 'Q': 2}).astype(int)
Fareカラム
Fareカラムには欠損値があったので、平均値で補完します。
data['Fare'].fillna(np.mean(data['Fare']), inplace=True)
Ageカラム
Ageについては、平均値よりも中央値で補完した方が良さそうです。
data['Age'].fillna(data['Age'].median(), inplace=True)
新しい特徴量の作成
前回の記事でも扱いましたが、EDA(探索的データ解析)の結果、家族の人数が生存率に影響を与える可能性があることがわかりました。
そこで、新しい特徴量として以下を作成することとします。
Parch + SibSp + 1 = FamilySize
それぞれ同乗者の数を表していたので、1を足しています。
data['FamilySize'] = data['Parch'] + data['SibSp'] + 1
train['FamilySize'] = data['FamilySize'] [: len(train)]
test['FamilySize'] = data['FamilySize'] [len(train):]
# 念の為可視化
sns.countplot(x='FamilySize', data=train, hue='Survived')
前回の記事では1人で乗船したか、2人以上で乗船したかでFamilySizeとしていました。
同様に、1人で乗船しているかどうかが重要であるので、1人で乗船したことだけを示すIsAloneカラムを作ります。
data['IsAlone'] = 0
data.loc[data['FamilySize'] == 1, 'IsAlone'] = 1
train['IsAlone'] = data['IsAlone'][:len(train)]
test['IsAlone'] = data['IsAlone'][len(train):]
ロジスティック回帰
特徴量エンジニアリングを一通り行ったので、実際にアルゴリズムにかけていきます。 学習用のデータtrainとテスト用データtestを作ります。
delete_columns = ['Name', 'PassengerId', 'SibSp', 'Parch', 'Ticket', 'Cabin', 'FamilySize', 'IsAlone']
data.drop(delete_columns, axis=1, inplace=True)
train = data[:len(train)]
test = data[len(train):]
y_train = train['Survived']
X_train = train.drop('Survived', axis=1)
X_test = test.drop('Survived', axis=1)
scikit-learnでロジスティック回帰を実行します。
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(penalty='l2', solver='sag', random_state=0)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
y_pred
#実行結果
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0.,
0., 1., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0.,
0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0.,
0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
0., 0., 0., 1., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 1., 0., 0.,
0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.,
0., 0., 0., 0., 1., 0., 1., 0., 0., 1., 0., 1., 1., 0., 0., 0., 1.,
0., 0., 0., 1., 0., 0., 1., 0., 0., 0.])
予測値が出たので、submitしてみます。
# 予測結果をcsvファイルに落とし込み
gender_submission['Survived'] = list(map(int, y_pred))
gender_submission.to_csv('submission.csv', index=False)
この段階でのscoreは0.66507
まだまだ伸ばせそうなので、次回以降の記事でトライしてみます。