KaggleのTitanicで上位10%のスコアを出す

Kaggleの[Titanic](https://www.kaggle.com/competitions/titanic)で上位10%のスコアを出すことができたため、コードをメモしておきます。
スコア上昇のために[sklearn.ensemble.VotingClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.VotingClassifier.html)を用いたアンサンブル学習を行いました。

https://www.kaggle.com/competitions/titanic

# ライブラリの読み込み
```Python
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
```

# データの読み込み
[pandas.dataframe](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)を用いて、学習データ、テストデータ、提出データをデータフレームとして代入します。
```Python
train = pd.read_csv("/kaggle/input/titanic/train.csv")
test = pd.read_csv("/kaggle/input/titanic/test.csv")
gender_submission = pd.read_csv("/kaggle/input/titanic/gender_submission.csv")
```

# データの可視化
## Survivedの可視化
[seaborn.countplot](https://seaborn.pydata.org/generated/seaborn.countplot.html)を用います。
```Python
sns.countplot(x="Survived", data=train)
plt.show()
```

![__results___11_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/56da5192-74eb-7766-e1f6-8e355fc16e7c.png)

## Survived、Pclass、Age、SibSp、Parch、Fareの関係の可視化
[seaborn.pairplot](https://seaborn.pydata.org/generated/seaborn.pairplot.html)を用います。
```Python
sns.pairplot(train[["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]], hue="Survived")
plt.show()
```

![__results___12_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/0fc7a113-6bd2-f99d-81b3-69809faebadd.png)

## Pclassの可視化
[seaborn.countplot](https://seaborn.pydata.org/generated/seaborn.countplot.html)を用います。

```Python
sns.countplot(x="Pclass", hue="Survived", data=train)
plt.show()
```

![__results___14_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/4af8d995-3674-f0d8-0566-5b9bdac7b651.png)

次に、[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="Pclass",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![__results___15_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/f9b11fcf-2f38-5c93-e357-a7a7fedf7fbf.png)

## Sexの可視化
[seaborn.countplot](https://seaborn.pydata.org/generated/seaborn.countplot.html)を用います。

```Python
sns.countplot(x="Sex", hue="Survived", data=train)
plt.show()
```

![__results___18_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/eab8e4ec-3209-0a29-a460-1763e4882bf3.png)

次に、[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="Sex",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![__results___19_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/4e5ba355-e275-e072-5aad-c06aa0393323.png)

## Ageの可視化
[seaborn.histplot](https://seaborn.pydata.org/generated/seaborn.histplot.html)を用います。
```Python
sns.histplot(data=train.dropna(subset=["Age"]), x="Age", hue="Survived", kde=True)
plt.show()
```

![__results___22_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/3c4d9ae7-8d77-a5e5-c560-daf979ee3d44.png)

## SibSpの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="SibSp",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![__results___24_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/da6a2310-48d1-3585-c9f8-feca12df1e10.png)

## Parchの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="Parch",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![__results___26_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/1385c93d-cb8a-ae5c-ee6d-284181c65d22.png)

## SibSp + Parchの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
train["TotalFamily"] = train["SibSp"] + train["Parch"]

g = sns.catplot(x="TotalFamily", y="Survived", data=train, kind="bar")
g.set_ylabels("Survival rate")
plt.show()
```

![__results___28_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/679ed06c-dceb-04ee-9e58-c154b9a82be2.png)

## Fareの可視化
[seaborn.histplot](https://seaborn.pydata.org/generated/seaborn.histplot.html)を用います。
```Python
sns.histplot(data=train.dropna(subset=["Fare"]), x="Fare", hue="Survived", kde=True)
plt.show()
```

![__results___30_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/8645d6f2-7409-2d40-fc6a-18ae98acfa0b.png)

## Embarkedの可視化
[seaborn.catplot](https://seaborn.pydata.org/generated/seaborn.catplot.html)を用います。

```Python
g = sns.catplot(x="Embarked",y="Survived", data=train, kind="bar")
g = g.set_ylabels("survival rate")
plt.show()
```

![__results___32_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/b435d544-00e0-fd17-fa43-42ed1e4f31df.png)

# データ前処理
## データの読み込み
```Python
train = pd.read_csv("/kaggle/input/titanic/train.csv")
test = pd.read_csv("/kaggle/input/titanic/test.csv")
gender_submission = pd.read_csv("/kaggle/input/titanic/gender_submission.csv")
```
## trainとtestの連結
[pandas.concat](https://pandas.pydata.org/docs/reference/api/pandas.concat.html)を用いて、データフレームを結合します。
```Python
data = pd.concat([train, test], sort=False)
```

## 欠損値の確認
[pandas.isnull](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html)、[pandas.DataFrame.sum](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sum.html)を用いて、欠損値をカウントします。
```Python
data.isnull().sum()
```

## ラベルエンコーディングと欠損値の補完
### Sex
ラベルエンコーディングには[sklearn.preprocessing.LabelEncoder](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html)を用います。
```Python
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
data['Sex'] = le.fit_transform(data['Sex'])
data.head()
```
femaleが0、maleが1となりました。

### Age
欠損値を中央値で置換します。
```Python
data['Age'].fillna(data['Age'].median(), inplace=True)
```

### Fare
欠損値を平均値で置換します。
```Python
data['Fare'].fillna(np.mean(data['Fare']), inplace=True)
```

### Embarked
[pandas.DataFrame.fillna](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html)を用いて欠損値をSで置換した後、ラベルエンコーディングを行います。
```Python
data['Embarked'].fillna(('S'), inplace=True)
data['Embarked'] = le.fit_transform(data['Embarked'])
data.head()
```
Cが0、Qが1、Sが2となりました。

### TotalFamily (SibSp + Parch)の作成
```Python
data["TotalFamily"] = data["SibSp"] + data["Parch"]
```

### Name、PassengerId、Ticket、Cabinの削除
データ分析に用いない列、Name、PassengerId、Ticket、Cabinを削除します。
```Python
delete_columns = ['Name', 'PassengerId', 'Ticket', 'Cabin']
data.drop(delete_columns, axis=1, inplace=True)
```

## 学習データとテストデータの抽出
```Python
train = data[:len(train)]
test = data[len(train):]
```
```Python
y_train = train['Survived']
X_train = train.drop('Survived', axis = 1)
X_test = test.drop('Survived', axis = 1)
```

# 学習
[RandomForestClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html)、[GradientBoostingClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html)、[KNeighborsClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html)、[SVC](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html)、[VotingClassifier](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.VotingClassifier.html)を用いて、学習を行います。

```Python
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, VotingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

clf_rf = RandomForestClassifier(max_depth=2, random_state=0)
clf_gb = GradientBoostingClassifier()
clf_knn = KNeighborsClassifier()
clf_svc = make_pipeline(StandardScaler(), SVC(probability=True))

ensemble_clf = VotingClassifier(estimators=[('rf', clf_rf), ('gb', clf_gb), ('knn', clf_knn), ('svc', clf_svc)], voting='soft')
ensemble_clf.fit(X_train, y_train)
```

予測を行い、予測結果を表示します。
```Python
y_pred = ensemble_clf.predict(X_test)
y_pred[:10]
```
```
array([0., 0., 0., 0., 0., 0., 0., 0., 1., 0.])
```

スコアを表示します。
```Python
ensemble_clf.score(X_train, y_train)
```
スコアは0.8821548821548821でした。

# データの出力
提出データをsubmission.csvとして出力します。
```Python
sub = gender_submission
sub['Survived'] = list(map(int, y_pred))
sub.to_csv("submission.csv", index=False)
```

提出した結果と順位を以下に示します。

![スクリーンショット 2024-01-07 16.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/795b7397-dfec-9c2d-03ef-a60daee52d3f.png)

15994人中1508位（2024年1月7日現在）と、上位10%のスコアを出すことができました。

もう一度同じコードで提出してみました。

![スクリーンショット 2024-01-09 12.20.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569835/1512200e-474a-1297-1c5c-57befdd58074.png)

スコアが0.79425に上昇し、16104人中1276位（2024年1月9日現在）と、上位8%のスコアを出すことができました。

アンサンブル学習によりスコアが上昇することを実感しました。
他のコンペにもアンサンブル学習を用いて挑戦したいです。

# 参考文献
https://qiita.com/upura/items/3c10ff6fed4e7c3d70f0
https://www.kaggle.com/code/sishihara/upura-kaggle-tutorial-01-first-submission
https://ct-innovation01.xyz/DL-Freetime/kaggle-003/
https://qiita.com/kunishou/items/bd5fad9a334f4f5be51c