【初心者】機械学習の分類・回帰の実装方法を試してみた

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

学び方としては、AWS Certified Machine Learning – Specialty（以降、ML試験という。）の勉強を通して、理解を深めていきます。ML試験のガイドの第3分野に、第 3 分野: モデリングから学びたいと思います。

今回は、**機械学習の用途や種類**について学びたいと思います。

> 3.1 ビジネス上の課題を機械学習の課題として捉え直す
> 機械学習を使用する/使用しないタイミングを判断する
> 教師あり学習と教師なし学習の違いを知る

なお、過去の機械学習の調べてみたシリースは下記にまとめています。
- 2.探索的データ分析
- [2.1.モデリング用のデータをサニタイズおよび準備する](https://qiita.com/zumax/items/d763d39e42520016b241)
    - [【初心者】探索的データ解析とは何かを調べてみた](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)
- 2.3 機械学習のデータを分析および視覚化する
    - [【初心者】機械学習のデータを分析および視覚化を調べてみた](https://qiita.com/zumax/items/1879441180372858d006)
    - [【初心者】機械学習のクラスタリングを調べてみた](https://qiita.com/zumax/items/41f1366f4f1a00eee1f0)
    - [【初心者】機械学習のクラスタリング（エルボー法）を調べてみた](https://qiita.com/zumax/items/f72941a10a6b9460c5de)
    - [【初心者】機械学習の用途やジャンルを学ぶ](https://qiita.com/zumax/items/b0849a8b21d6a4a1fddb)
- 機械学習プロセス
    - [【初心者】AWS Machine Learning Lensを整理する](https://qiita.com/zumax/items/93f9635b3be51fe483e1)

# まとめ
|分類と回帰 |アルゴリズム |
|:-- |:-- |
|分類 |svm |
| | K近傍法|
| |ロジスティック回帰 |
|回帰 | Lasso|
| |Ridge |
| |LinReg |

- scikit-learnでは、以下の特徴がある。
    - アルゴリズムが豊富、使いやすい
    - チートシートにより簡単に適切な手法を選択できる
    - サンプルデータセットが用意されている
    - 解説が丁寧
- 以下の機能がある。
    - 回帰
    - 分類
    - クラスタリング
    - 次元削減
    - データの前処理
    - モデルの評価と選択

# 概要
codaxaさんの[scikit-learn 入門：6つの機能と分類・回帰の実装方法を徹底解説！](https://www.codexa.net/scikit-learn-intro/)を元に学びたいと思います。ありがとうございます。
ここでは、scikit-learnの4つの特徴と6つの機能について整理し、回帰と分類の実装をします。

## scikit-learnとは？
- OSSの機械学習ライブラリ。
- Numpy、SciPy、matplotlibなどのPythonライブラリ上で動作する。
- 手軽に機械学習の前処理、モデリング、評価指標の算出など行える。

## 4つの特徴
### ①アルゴリズムが豊富、かつ使いやすい
- 回帰、分類、クラスタリング、次元削減など、あらゆるアルゴリズムが揃っている。

### ②アルゴリズムチートシートを参考に、簡単に適切な手法を選択できる。
- どのアルゴリズムを使えばよいかチートシートでわかる。
    - 以下のチートシートで、スタートからYes/Noで二択の選択肢でデータにあったアルゴリズムを選択できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/47ccdcf5-fd1a-0a38-cf11-3d56525efbe5.png)

### ③サンプルのデータセットが用意されている
- scikit-learnにはサンプルのデータセットが用意されている。
- scikit-learnに用意されているデータセットは使いやすいように整形されているため、前処理に余計な手間がかからない。

### ④公式サイトの解説が丁寧で便利
- ユーザガイドは、各アルゴリズムについて、仕組み、モジュール、実装例が載っている。

## scikit-learnの６つの機能
### 回帰
- 回帰とは、二種類ある教師あり学習のうちの一つ。
- データセットを学習して新たな入力に対する出力の数値を予測する手法。
- 例
    - 過去の気象データと位置情報を学習し、その地点の翌日の気温を予測する際には回帰を行う。
    - ボストンの住宅価格のデータセットを用いて、まちの犯罪率、高速道路へのアクセスの良さなどのデータから土地の住宅価格を予測する

### 分類
- 分類とは、回帰ともう一つの教師あり学習。
- データを学習して、新たな入力に対する出力のラベルを予測する手法。
- 例
    - 気象データと位置情報を学習し、その地点の翌日の天気（晴れ、曇、雨、雪）を予測する。
    - アヤメのデータセットを用いて、アヤメの花びらやがくの大きさから、そのアヤメがどの種類なのか予測する。

### クラスタリング
- 教師なし学習の一つ。
- クラスタリングとは、データの特徴から関連の深いデータや似通ったデータを見つけて、クラスターに分ける（グルーピングする）手法。
- 例
    - 企業の購買データの分析などに応用されて、クラスタリングの結果に基づいて顧客に商品をレコメンドする。

### 次元削減
- 教師なし学習の一種。
- データセットの特徴量同士の関係を学習し、より完結かつ効率的に特徴量の情報を表現することなど目的に、新たな特徴を計算で導出して特徴量の数を削減する手法。
- 次元削減することで、コンピューターの性能不足を補う。
- 主成分分析や、因子分析などで次元削減を行うことができる。

### データの前処理
- データの数値変換。
- 標準化（データの平均を0、標準偏差を1にする）

### モデルの評価と選択
- 各種評価指標を簡単に算出したり、ハイパーパラメータをチューニングしたりするための機能が備わっている。

# 実践
## 事前準備
### ライブラリ・データセットの準備
```
import pandas as pd
import sklearn
from sklearn.datasets import load_iris, load_boston
```
- アヤメのデータセットと、ボストンの住宅価格のデータセットをインポートする。

## 分類の実装(アヤメのデータセット)
- アヤメの種類の予測を行う。データを読み込んで中身を確認する。

### データの確認と分割
#### データセットの確認
```
iris = load_iris()

iris_features = pd.DataFrame(data = iris.data, columns = iris.feature_names)
iris_features.head()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/452056fb-3b2f-f11e-d06a-163cb86fa9ea.png)

#### 基本統計量を確認。
```
iris_features.describe()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/6a6f2a45-e101-95a4-5089-f4a9496f0619.png)

- 明らかにおかしいデータが含まれないか確認する。
- 上から順に
    - データ数
    - 平均値
    - 標準偏差
    - 最小値
    - 第1四分位
    - 中央値
    - 第3四分位
    - 最大値

#### 特徴量に欠損値がないか確認
```
iris_features.isnull().sum()
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a78bc0cb-49b3-97ee-3279-854d013893c9.png">

- nullはない。

#### ラベルの確認
- ラベールをシリーズに格納し、ラベルごとのデータ数を表示する。
```
iris_label =pd.Series(iris.target)
 
iris_label.value_counts()
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/2c4d9ed9-8f1a-5885-ee8c-35c9cfe08770.png">

- 0〜2までのラベルで50個づつ。

#### データを訓練データとテストデータに分割
- model_selectionモジュールのtrain_test_splitメソッドで、データを訓練データとテストデータに分割する。
- 引数には、以下を指定する。
    - 特徴量
    - ラベル
    - テストデータにする割合
    - 再現性を持たせるための乱数生成のシードを指定するrandom_state引数
```
from sklearn.model_selection import train_test_split
features_train, features_test, label_train, label_test = train_test_split(iris_features, iris_label,test_size =0.5, random_state=0)
```
- 確認する。
```
print(features_train.shape)
print(features_test.shape)
print(label_train.shape)
print(label_test.shape)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ea0f61ee-5f83-d570-29eb-96ec4e345938.png)

### svm（サポートベクターマシン）で学習と予測
- モジュールをインポートし、学習。
```
from sklearn import svm

Linsvc = svm.LinearSVC(random_state=0, max_iter=3000)

Linsvc.fit(features_train,label_train)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/6892916f-bd7f-82e0-57c4-86fb6642beb4.png)

- アヤメのデータを予測する。LinerSVCのインスタンスのpredictメソッドを用いる。
```
label_pred_Linsvc = Linsvc.predict(features_test)
print(label_pred_Linsvc)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/3c0115bd-dfd9-0b30-eb87-01511c8fcb9c.png)

```
from sklearn.metrics import confusion_matrix
print('confusion matrix = \n', confusion_matrix(y_true = label_test, y_pred = label_pred_Linsvc))
print('accuracy = ', Linsvc.score(features_test,label_test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/d621d036-104b-8421-3e49-8f9099c9018b.png)


### K近傍法で学習と予測
```
from sklearn.neighbors import KNeighborsClassifier
 
Kneighbor = KNeighborsClassifier(n_neighbors=5)
 
Kneighbor.fit(features_train,label_train)

label_pred_KNeighbor = Kneighbor.predict(features_test)
print(label_pred_KNeighbor)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ca5a35d9-5fa7-7483-9e20-71de05cb1a2d.png)

```
from sklearn.metrics import confusion_matrix
print('confusion matrix = \n', confusion_matrix(y_true = label_test, y_pred = label_pred_KNeighbor))
print('accuracy = ', Kneighbor.score(features_test,label_test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f806f415-a883-1ac2-3cf3-425ad2bbf474.png)

### ロジスティック回帰で学習と予測
```
from sklearn.linear_model import LogisticRegression
 
LogReg = LogisticRegression(random_state=0)
 
LogReg.fit(features_train,label_train)
 
label_pred_LogReg = LogReg.predict(features_test)
print(label_pred_LogReg)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/64be1964-7bac-2f3a-aefe-121fa2154b82.png)

```
from sklearn.metrics import confusion_matrix
print('confusion matrix = \n', confusion_matrix(y_true = label_test, y_pred = label_pred_LogReg))
print('accuracy = ', LogReg.score(features_test,label_test))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/efaaca6f-4659-dd9d-cf3a-009a1b53ecb0.png)

### 最後に
K近傍法が96%で最も性能が良い。

## 回帰とモデル選択の実装（ボストン住宅価格データセット）
- ボストンの住宅価格に関するデータセットを用いて、回帰を行い、住宅価格を予測する。

### 事前準備

#### データセットの確認
```
boston = load_boston()
 
boston_features = pd.DataFrame(data = boston.data, columns = boston.feature_names)
boston_features.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a805188c-0496-b7bd-5c80-f85ae02433d6.png)

- データの意味は以下の通り。
    - CRIM 町の人口あたり犯罪率
    - ZN 25000平方フィート以上の住宅地の割合
    - INDUS 町ごとの非小売業の土地の割合
    - CHAS Charles川に関するダミー変数(川に接していたら1、そうでなければ0)
    - NOX 一酸化窒素濃度（1000万分の1）
    - RM 住居当たりの平均部屋数
    - AGE 1940年より前に建設された物件の割合
    - DIS ボストンの5つの雇用センターまでの重み付けされた距離
    - RAD 放射状高速道路へのアクセスしやすさ
    - TAX 10000ドル当たりの固定資産税総額
    - PTRATIO 町ごとの生徒と教師の比率
    - B   1000(Bk – 0.63)^2 ※Bkは町の黒人比率
    - LSTAT 低所得の人々の割合

#### 基本統計量を表示
```
boston_features.describe()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/cf938d18-341f-ba16-0fa1-660439bfa934.png)

#### 欠損値の確認
```
boston_features.isnull().sum()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a1be8454-10a1-1cc2-c97d-86d6d97f5fb6.png)

#### ターゲットの基本統計量を確認
```
boston_target = pd.Series(data = boston.target)

boston_target.describe()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ac4b9e74-b504-d00e-72bd-756fd1e8b8f8.png)

- 最小値と最大値で10倍の差がある。

### データを学習データとテストデータに分割
```
from sklearn.model_selection import train_test_split
features_train, features_test, target_train, target_test = train_test_split(boston_features, boston_target,test_size =0.5, random_state=0)
```
### Lassoで学習と予測
```
from sklearn.linear_model import Lasso
 
Lasso = Lasso(alpha=0.1,random_state=0)
 
Lasso.fit(features_train,target_train)
 
target_pred_Lasso = Lasso.predict(features_test)
print(target_pred_Lasso)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/7fd16491-6ed2-f5bc-f1a1-58ebc20b573d.png)

```
print("R-squared : ",Lasso.score(features_test,target_test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/dc4ec24a-5138-1a6a-a720-3e9c1d0e1744.png)

### Ridgeで学習と予測
```
from sklearn.linear_model import Ridge
 
Ridge = Ridge(alpha=0.5,random_state=0)
 
Ridge.fit(features_train,target_train)

target_pred_Ridge = Ridge.predict(features_test)
print(target_pred_Ridge)
 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/4bfb38aa-6856-dc59-f2b0-4b10776ed877.png)

```
print("R-squared : ",Ridge.score(features_test,target_test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/f36ff8b3-db59-c154-f1bc-2fd7e45e4046.png)

### LinRegで学習と予測
```
from sklearn.linear_model import LinearRegression

LinReg = LinearRegression()

LinReg.fit(features_train,target_train)

target_pred_LinReg = LinReg.predict(features_test)
print(target_pred_LinReg)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/3fd7d9ae-692b-2b28-90df-dc20add4aed8.png)
```
print("R-squared : ",LinReg.score(features_test,target_test))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/cacc581c-20bf-ce9c-01ed-0aad3344ad36.png)

## クロスバリデーション
- モデルの評価と選択の機能
- データセットを訓練データとテストデータに分割してモデルに学習させてスコアを出すプロセスを複数回繰り返し、すべてのスコアの平均で性能を測り、より一般的な予測性能が高いモデルを選択する手法。
- たまたま、モデルに不利な形でデータセットが分割されたために性能が低くなったケースを回避できる可能性がある。

### Lassoモデルでクロスバリデーションを行う
```
from sklearn.model_selection import ShuffleSplit, cross_val_score
 
cv = ShuffleSplit(n_splits=5, test_size = 0.2, random_state=0)
 
scores = cross_val_score(Lasso, boston_features, boston_target, cv=cv)
 
print(scores)
print("R-squared_Average　: {０:.2f}".format(scores.mean()))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/e28aae1e-12ea-ce3a-37af-4de5e6e36269.png)


```
scores = cross_val_score(Ridge, boston_features, boston_target, cv=cv)

print(scores)
print("R-squared_Average　: {０:.2f}".format(scores.mean()))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ded6c844-8ebd-9343-44a6-0e2dadc3c2dd.png)

```
scores = cross_val_score(LinReg, boston_features, boston_target, cv=cv)
 
print(scores)
print("R-squared_Average　: {０:.2f}".format(scores.mean()))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/394846b0-8619-a8dd-3700-e03eacc6d644.png)


# 参考
https://www.codexa.net/scikit-learn-intro/