初投稿&Kaggle_Titanic挑戦その1

こんにちは。Kosukeです。初投稿なのでまずは自己紹介を行います。

# 自己紹介
・性別:男
・所属:大学4年生
・興味：映画鑑賞、音楽鑑賞（邦ロックと洋楽）、ゲーム(特にSwitch)、旅行、ちいかわ好き

# Kaggle&SIGNATE挑戦
機械学習および深層学習を実用的に学ぶにあたり、コンペティションに挑戦しています。今回はKaggleのTitanicの死者の予測を行いました。

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

# データ前処理
## データの準備
まず、データを読み込み、ライブラリをインポートします。
```Python
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

# データの読み込み
m_train = pd.read_csv('train.csv')
m_test = pd.read_csv('test.csv')
```

訓練データの中はこんな感じです。
```Python
m_train
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/f120e086-8856-b2df-3cd7-46ab9dcc6f76.png)

使われている変数は以下のとおりです。

| 変数名 | 変数型 | 種類 | 尺度名 |
|:-:|:-:|:-:|:-:|
| Survival  | int  | 生死 (1:生, 0:死) ※目的変数  | なし  |
| Pclass  | int  | チケットのクラス  | 名義  |
| Sex  | char  | 性別  | 名義  |
| Age  | float  | 年齢  | 比例  |
| Sibsp  | int  | 同行していた人の数  | 間隔  |
| Parch  | int  | 同行していた親子の数   | 間隔  |
| Ticket  | char  | チケット番号  | 名義  |
| Fare  | float  | 居客運賃  | 比例  |
| Cabin  | char  | 客室番号  | 名義  |
| Enbarked  | char  | 乗船港 | 名義  |

今回は<b>Survival</b>を目的変数として生死を予測する。<br>

読み込んだ訓練データの要約統計量を可視化させます。
```Python
m_train.describe()
```

以下のように可視化されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/ba6b7b10-c159-bcd7-5036-d4003da82029.png)

## データの修正
生死を予測する際に、訓練データとテストデータの欠損値を補完する必要があります。
まず、それぞれのデータの欠損値を確認します。
```Python
#訓練データの欠損値確認
m_train.isnull().sum()
```
```Python
#テストデータの欠損地確認
m_test.isnull().sum()
```

訓練データにはAgeとCabin、Embarkedに欠損値がありました。
テストデータにはAgeとCabin,Fareに欠損値がありました。

欠損値を確認したので、欠損値を補完します。
```Python
#欠損値補完 AgeとEmbarkedのみ
m_train["Age"]=m_train["Age"].fillna((m_train["Age"].median())) #ageを中央値に補完
m_train["Embarked"] = m_train["Embarked"].fillna("S") #embarkedを一番多いSに補完
m_test["Age"]=m_test["Age"].fillna((m_train["Age"].median())) #ageを中央値に補完
m_train.isnull().sum()
```
```Python
#欠損値補完 Fare
m_test["Fare"]=m_test["Fare"].fillna((m_train["Fare"].median())) #fareを中央値に補完
```

## データの数値化
結果を0,1で表現するダミー変数化と文字列データを数値で表現する数値化を行います。これは主に文字列がデータとして格納されている列を対象にダミー変数に変換されます。
今回はSexがmale,female2通りの結果が出力され、EmbarkedがS,C,Qの3通り出力されたので、これらを数値します。
```Python
#性別をダミー変数化する
m_train["Sex"][m_train["Sex"] == "male"] = 0
m_train["Sex"][m_train["Sex"] == "female"] = 1
m_test["Sex"][m_test["Sex"] == "male"] = 0
m_test["Sex"][m_test["Sex"] == "female"] = 1
m_train
```

次にEmbarkedを数値化します。小さい方からS,C,Qの順で数値化します。
```Python
#Sは0　Cは1 Qは2　に変更する
m_train["Embarked"][m_train["Embarked"] == "S"] = 0
m_train["Embarked"][m_train["Embarked"] == "C"] = 1
m_train["Embarked"][m_train["Embarked"] == "Q"] = 2
m_test["Embarked"][m_test["Embarked"] == "S"] = 0
m_test["Embarked"][m_test["Embarked"] == "C"] = 1
m_test["Embarked"][m_test["Embarked"] == "Q"] = 2
m_train
```

前処理した結果は以下のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/9620e0d0-ddbd-bd9e-a152-9a7d2f57bb0d.png)


# モデル選択と学習
データの前処理が終わったので、モデル選択と学習を行います。

まず、学習に用いる列を選択します。Xを説明変数、Yを目的変数とします。説明変数はPclassとSex,Age,Fare,Embarkedの５つを使います。
```Python
#テストデータと訓練データを分ける
from sklearn.model_selection import train_test_split

seed=0
#データ処理
X = m_train.drop(['Survived'], axis=1)
X = m_train[["Pclass", "Sex", "Age", "Fare","Embarked"]]
y = m_train[["Survived"]]
X
```

次にXを学習データとテストデータに分割します。
```Python
train_X, test_X, train_y, test_y  = train_test_split(X, y, test_size=0.3, random_state=seed)
```
テストデータの分割も完了したので、学習を行います。今回は決定木とランダムフォレストを用いて学習させます。

## 決定木
```Python
# モデル作成のためのライブラリ
from sklearn.ensemble import RandomForestClassifier

# モデル作成に役立つライブラリ
from sklearn.model_selection import train_test_split

# 性能指標(正解率)
from sklearn.metrics import accuracy_score

# モデルの作成と評価(RandomForestClassifier)
rfc = RandomForestClassifier(random_state=0)
rfc.fit(train_X, train_y)
y_pred = rfc.predict(test_X)
score = accuracy_score(test_y, y_pred)
score
```

正解率は<b>0.8171641791044776</b>になりました。

## ランダムフォレスト
```Python
# 決定木モデルの作成
# ライブラリのインポート
from sklearn.tree import DecisionTreeClassifier

dtc = DecisionTreeClassifier(random_state=0)

# 学習
dtc.fit(train_X, train_y)

# 予測
y_pred = dtc.predict(test_X)

# 精度の計算
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(test_y, y_pred)
print('Accuracy:', accuracy)
```

正解率は<b>0.7947761194029851</b>になりました。

# 提出データの作成
正解率はランダムフォレストが高いので、そのモデルを採用します。
提出データを作成するにあたり、テストデータをfloat型に変換します。
```Python
X_test = m_test[["Pclass", "Sex", "Age", "Fare","Embarked"]].astype(float)
X_test
```
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/6843d36f-e8a5-569a-c4fd-97fa25bd84ae.png">

X_testを予測するためにもう一度欠損値を確認します。
```Python
X_test.isnull().sum()
```
欠損値はいずれも0です。
次にデータを予測します。
```Python
# 予測
y_pred_submit = rfc.predict(X_test)
y_pred_submit
```

予測値を求めることができたので、データ提出作業に入ります。
まず、提出サンプルを読み込み、PassengerIDを抽出します。
```Python
submit_sample = pd.read_csv('submit.csv')
```

```Python
submit = pd.DataFrame(data = {'PassengerId': submit_sample['PassengerId'], 'Survived': y_pred_submit})
submit
```
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1226429/950ed1e3-6baf-7748-e622-98c71ff15992.png">

```Python
submit.to_csv('submit_titanic.csv', index=False)
```

提出完了しました。Scoreは0.76555だったので、まだまだ調整する必要があります。ハイスコアを目指すようにその他の目的変数の使用や最適なモデル作成、最適なハイパーパラメータの選択を行って精度を上げます。

# まとめ
このようにKaggleを用いてデータの予測を行いました。最初は不慣れだった点もあり精度が低かったが、何回も繰り返していくうちに機械学習の手法をアウトプットでき、他のコンペにもスキルを適用できるのではないかと感じます。具体的には、機械学習の知識だけではなく、データの前処理や特徴量エンジニアリング、モデルの選択や学習、評価などデータ分析で必要となる基本的なスキルを取得することができます。その際、KaggleとSIGNATEでデータ分析に挑戦していきます。