【初心者】機械学習のデータを分析および視覚化を調べてみた

# 背景・目的
私は、現在データエンジニアリングを生業としています。普段は、データ基盤の構築や、パフォーマンスチューニングなどビックデータに関する業務に従事しています。
ビックデータの収集や、蓄積、分析などの環境構築の経験はそこそこありますが、機械学習による予測や分類などのスキルは持ち合わせていませんでした。
今まで機械学習を避け続けてきましたが、一念発起し学ぼうと思います。

学び方としては、AWS Certified Machine Learning – Specialty（以降、ML試験という。）の勉強を通して、理解を深めていきます。ML試験のガイドの第２分野に、探索的データ解析が登場しましたのでそこから学びたいと思います。

今回は、**グラフ化**について学びたいと思います。

> 2.3 機械学習のデータを分析および視覚化する
> ・ グラフ化 (散布図、時系列、ヒストグラム、ボックスプロット)

なお、過去の機械学習の調べてみたシリースは下記にまとめています。
- 2.探索的データ分析
- 2.1.モデリング用のデータをサニタイズおよび準備する
    - [【初心者】探索的データ解析とは何かを調べてみた](https://qiita.com/zumax/items/52c97307bf18f407bb6e)
    - [【初心者】データのスケーリングを調べてみた](https://qiita.com/zumax/items/ca7184dcf4e7fd242128)
    - [【初心者】データの拡張を調べてみた](https://qiita.com/zumax/items/0727e329f3322897d3e7)
    - [【初心者】データアノテーションを調べてみた](https://qiita.com/zumax/items/d0da86b68b05b99cb23e)
- 2.2.特徴エンジニアリングを実行する
    - [【初心者】特徴量エンジニアリングについて調べてみた](https://qiita.com/zumax/items/3b6e771ef1fcaf3edd91)
    - [【初心者】特徴量エンジニアリング（データのビニング）について調べてみた](https://qiita.com/zumax/items/dc0c86736dd5362cf118)
    - [【初心者】特徴量エンジニアリング（トークナイゼーション）について調べてみた。](https://qiita.com/zumax/items/5286c51ecc0a81b66b87)
    - [【初心者】特徴量エンジニアリング（外れ値）について調べてみた](https://qiita.com/zumax/items/2a07f6d3502fc9a16a44)
    - [【初心者】特徴量エンジニアリング（合成データ）について調べてみた](https://qiita.com/zumax/items/654eae53dae77f222433)
    - [【初心者】特徴量エンジニアリング（ダミー変数[One-Hotエンコーディング]）について調べてみた](https://qiita.com/zumax/items/de5cef1ac4a281400764)
    - [【初心者】特徴量エンジニアリング（次元低減）について調べてみた](https://qiita.com/zumax/items/d92342c3da94020eedec)

- 機械学習プロセス
    - [【初心者】AWS Machine Learning Lensを整理する](https://qiita.com/zumax/items/93f9635b3be51fe483e1)

# まとめ
- seabornは可視化ライブラリで様々なグラフを描ける。

# 概要
今回は、codexaさんの[seaborn 徹底入門！Pythonを使って手軽で綺麗なデータ可視化８連発](https://www.codexa.net/seaborn-python/)を元に整理したいと思います。

## 可視化の必要性
データの可視化が必要な理由は、以下のとおりです。
- そのデータを生み出している事象をより正確に理解する。
- 機械学習での予測を用いる際に、使うべきデータを適切に選んだりするため。

そのためにはまず、**データを可視化して大きな特徴を掴み、データ同士の相関を知る**ことが必要とのことです。

## どうやるのか
Pythonでデータを可視化するには、Pandasでデータを集計・加工し、その上でmatplotlibやseabornというライブラリで可視化します。

## seabornの特徴
- しーぼーんという。
- Pythonの可視化ライブラリ
- 内部でmatplotlibが動作している。
- 洗練された図を描く言上でき、matplotlibと比べて少ないコードで図が掛ける。
- ただし、matplotlibのユーザのほうが多い。

## データセットの確認
ライブラリをインポートする。
```
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

```

データセットは、titanicを利用します。
```
df = sns.load_dataset('titanic')
```

最初の5行を利用します。
```
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/d66025d7-a1bc-a632-892b-0e4c2a5f43b3.png)

## 棒グラフを描く　−複数の項目の値を比較する−
- `sns.catplot`は性別や年齢の分布を見るようにカテゴリごとに分布を比較する場合に用いる。
    - kindで用いた手法を指定する。
    - xに可視化したい変量を指定し、dataにその変量を持つデータフレームを指定
    - kindにはcountを指定する。

```
sns.catplot(x="pclass", data=df, kind="count")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/df289340-6203-2e7b-a4f1-b1dd55c06c68.png)

## ヒストグラムを描く　−ひとつの変量の分布を可視化する−
- ヒストグラムは、ある一つの変量を複数の階級（bin）に分け、それぞれの階級にいくつのデータが含まれるのかを棒グラフの形で表現したもの。
- `sns.distplot`を使用する。
    - 引数には、PandasのSeries、Numpyの1d-array、Pythonのリストを指定する。
```
sns.distplot(df['age'])
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/7b3435a2-3439-5319-d89a-f9ca5a8d00bd.png)
- 20代前半の人が多い。
- 幅4で全部で20階級(bin)を持っている。階級の数は指定しない場合自動的に決まる。binsを指定することもできる。
- KDE(カーネル密度推定)と呼ばれる手法で計算された確率密度関数を削除する場合は、kde=Falseを指定する。以下に示す。

```
sns.distplot(df['age'], kde=False)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/96ea98e9-9252-c67d-4853-36ccf0371d61.png)

## 箱ひげ図を描く　−基本統計量を可視化する−
- 多くの基本統計量を可視化できるのが箱ひげ図の特徴です。
- 四分位数を用いて、外れ値を特定でききる。
- `sns.catplot`を使用して、kind='box'を指定します。

```
sns.catplot(x='sex', y='age', data=df, kind='box', hue='survived')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/0cb52031-7f38-e61f-4309-3385c58d035f.png)

- kindを`box`から`boxen`を指定することで、より詳細な情報を得られる表示方法に変えることが出来ます。

```
sns.catplot(x='sex', y='age', data=df, kind='boxen', hue='survived')
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/be5d6281-b1ad-e7d5-bec9-526476d43632.png)

## 棒グラフを描く　−平均値を可視化する−
- カテゴリーごとの平均値にのみに興味がある場合は、`sns.catplot`で`kind='bar'`を指定することで棒グラフで平均値の比較ができる。
```
sns.catplot(x='sex', y='age', data=df, kind='bar', hue='survived')
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/1a0c6ab7-7807-ddff-8643-553a4a00a816.png)

- `estimator=np.median`を指定することで中央値の比較が可能になる。
```
sns.catplot(x='sex', y='age', data=df, kind='bar', hue='survived', estimator=np.median)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/4d86670c-94b3-118a-6921-78883d9d2f1d.png)

## scatter plotを描く　−分布を詳細に表示する−
- 一つのデータを一つの天として表示します。
- `sns.caplot`でkindを指定なしの場合のデフォルト。
```
sns.catplot(x='sex', y='age', data=df)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ea834951-81ca-2d7b-f098-a3a6b7c719e9.png)

- 上記だと多くの点が集中し分布が確認しづらくなる箇所がある。
- swarm plotを使う。`kind='swarm'`を使う。

```
#swarm plotの表示
sns.catplot(x='sex', y='age', data=df, kind='swarm')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/0f484c8f-ed94-a09e-d2f1-987f0f0102cc.png)

- ラベルごとの分布を見る。
- `hue='survived'`を指定する。
```
sns.catplot(x='sex', y='age', data=df, kind='swarm', hue='survived')
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/2c62af35-2e2d-209f-fbcf-9f3927cde170.png)

- 女性は生存の割合が高く、男性は10歳以下での生存の割合が高い事がわかる。

## ヴァイオリンプロットを描く　−scatter plotを滑らかにし、箱ひげ図を加える−
- 箱ひげ図は中央値、最大値、最小値を比較するのに向いているが、分布の様子を比較することが出来ない。
- `kind=’violin’` を指定することでバイオリン図を表示できる。

```
sns.catplot(x='sex', y='age', data=df, kind='violin', hue='survived')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ee9cc964-5f55-76c7-665f-ab686fbce24d.png)


- `split=True` を指定すると、hue をラベルごとに結合させた形にすることができます。

```
sns.catplot(x='sex', y='age', data=df, kind='violin', hue='survived', split=True)
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/adff4e76-f211-0571-5cbd-f05333c79dcd.png)

## 散布図を描く　−二つの数量データの関係を可視化する−
- 年齢(age)と運賃(fare)のように2つの数量データの関係性をみるには散布図を利用します。
- 散布図は、横軸と縦軸それぞれに1つずつ変量を対応させ、各データをプロットしたものです。
- `sns.scatterplot` で描くことができ、引数は以下のように指定します。
    - x=横軸, y=縦軸, data=データフレーム

```
sns.scatterplot(x='age', y='fare', data=df)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/6700df88-c958-e22f-bce7-ced844fe32a6.png)

- 散布図の上と右に、各変量のヒストグラムを併せて表示する方法として、`sns.jointplot` があります。
- 各々の変数単独の分布を同時に確認できるのが特徴。
- 上記の散布図では、データが密集し見づらくなった。
- 引数に`kind='hex'`を指定して、データの密度を色の濃淡で表現します。
- 散布図とヒストグラムを同時に表示する。

```
sns.jointplot(x='age', y='fare', data=df, kind='hex')
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ca361846-863e-cfa1-8fbd-41c5ba57f6e8.png)

- 年齢が20歳〜30歳で安いチケットを持っている乗客が多い
- 高いチケットをもっている客がかなり少ない

## 散布図行列を描く　−全ての変量の組の関係を可視化する−
- sns.scatterplot を用いることで2つの変量の散布図を描くことができますが、関係性を確かめたい変量がいつも2つしかないとは限らない。
- つ以上の変量がある場合に、それぞれの関係を1組ずつ可視化するのは面倒.
- `sns.pairplot`でまとめて散布図を描くことができる。
- 各散布図は行列の形式に並べられて、これを散布図行列と呼ぶ。
- データに多くの変量が含まれている場合、個別の散布図を描く前に`sns.pairplot`を使用してまとめて散布図をみると、どの変量間の関係性が重要そうであるか検討をつけることが可能です。
- irisデータセットを使用して確認する。

```
df2 = sns.load_dataset('iris')
df2.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/4826b180-831a-70f6-522c-271b16be3089.png)

- `sns.pairplot` は引数としてDataFrameを受け取ります。

```
sns.pairplot(df2)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/c88db993-9a1a-38e8-eb43-1112ed301260.png)

- 全ての変量の組み合わせについて、散布図が書かれていることが分かりました！
- 対角線上には、それぞれの変量についてのヒストグラムが描かれている。
- 引数に`hue`を指定することで、ラベル毎に色付けできる。アヤメの種類を示す`species`を指定する。

```
sns.pairplot(data=df2, hue='species')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/bdb42bd5-1085-031e-5903-2179c26353a9.png)

# 考察
説明変数を探す際に事前にデータセットを確認すると思いますが、seabornを使いグラフ化しざっくりと確認することが出来ます。
また、はじめにpairplotを使用してざっくりと各変数ごとの組み合わせを確認し、その後各変数について詳細を確認することで効率よく探すことができます。


# 参考
https://www.codexa.net/seaborn-python/

https://seaborn.pydata.org/examples/index.html