ディープラーニングと機械学習の回帰を、実測値と予測値の関係のグラフで比較したかった

### DeepLearningで出てくるグラフは

今、この本を勉強しています。
<a target="_blank" href="https://www.amazon.co.jp/gp/product/4274226409/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4274226409&linkCode=as2&tag=gnbunincomple-22&linkId=aeaa467c5817d6ecce2f4d4922ab5efb">動かしながら学ぶPyTorchプログラミング入門</a>
いつもDeepLearningでサンプルとして出てくるグラフはこんなグラフです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/294bac1c-b857-f89e-2cac-ef13418e7b96.png)

ミニバッチでの計算で、Epochの回数とLossのデータで、予測がうまくいっているかどうかを見るグラフが出てきます。これはこれで良いのだけど、・・・・。


最初のところに回帰のサンプルプログラムがついているのですが、ここでも、上のグラフしか出てきません。
`scikit-learn`の機械学習からやり始めた私は、ディープラーニングでは、実測値と予測値のこういうグラフをなぜ書かないんだろうといつも疑問に思っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/851403c1-309e-05bf-282a-a1e2b03c01c9.png)

同じグラフで描かないと、機械学習とディープラーニングの回帰の比較の可視化ができません。

そう思ったので、ディープラーニングの`PyTorch`の勉強しながら、グラフを描いてみました。

### 参考にしたプログラムは
[動かしながら学ぶ PyTorchプログラミング入門](https://www.ohmsha.co.jp/book/9784274226403/)の中の第３章「糖尿病の予後予測」のプログラムをベースに、データをボストンの家の価格のデータセットに変更して使用しました。
元のプログラムは、
https://www.ohmsha.co.jp/book/9784274226403/　
の　Section3-3.ipynb　です。

変更点のみ、以下にプログラムを書いていきます。

###ボストンの家の価格のデータセットをディープラーニングで回帰する
「動かしながら学ぶ PyTorchプログラミング入門」の第三章の糖尿病のデータセットのディープラーニング回帰からボストンのデータセットに変更する変更点は以下のところのみです。
基本は、`diabetes`　→　`boston`　に変更することで、データセットを変更します。

```Python
#元のサンプルプログラムの次の部分を変更
#サンプルプログラム
#データセットの読み込み
from sklearn.datasets import load_diabetes
diabetes = load_diabetes()

# データフレームに変換
df = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
# 1年後の進行度の追加
df['target'] = diabetes.target

# データセットの可視化
sns.pairplot(df, x_vars=diabetes.feature_names, y_vars='target')
plt.show()

# データセットの読み込み
diabetes = load_diabetes()
data = diabetes.data  # 特徴量
label = diabetes.target.reshape(-1, 1)  # 一年後の糖尿病の進行度

# ハイパーパラメータの定義
D_in = 10  # 入力次元: 10

#上の部分を下記のように変更
#基本的にdiabetes　→　boston　に変更する
#ボストンの家のデータセットへ変更
#データセットの読み込み
from sklearn.datasets import load_boston
boston= load_boston()

# データフレームに変換
df = pd.DataFrame(boston.data, columns=boston.feature_names)
# 1年後の進行度の追加
df['target'] = boston.target

# データセットの読み込み
boston = load_boston()
data = boston.data  # 特徴量
label = boston.target.reshape(-1, 1)  # ボストンの家の価格

# ハイパーパラメータの定義
D_in = 13  # 入力次元: 13

```
注意点は、入力の特徴量が、糖尿病のデータセットが１０に対し、ボストンの家の価格のデータセットが１３であるので、ディープラーニングの入力の次元も変更する必要があるところである。

これで、ボストンのデータセットで回帰計算ができます。
計算はＧＰＵ（cuda）で計算しています。
結果は次のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/a22577c2-c06e-28fb-2aec-38d49620c335.png)

精度がいまいちですけど、グラフを描きたいだけなので、このまま次にいきます。

##ボストンの家のデータセットでランダムフォレスト回帰
これは簡単です。
`scikit-learn`の計算はとっても簡単だと思います。


```Python
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt

rg = RandomForestRegressor(n_jobs=-1, random_state=0)
rg.fit(train_data,train_label)
test_predict = rg.predict(test_data)
rg_scorer = r2_score(test_label, test_predict)  
print('ランダムフォレストのR2：{:.3g}'.format(rg_scorer))

plt.scatter(test_label, test_predict)
plt.xlabel("measured_value")
plt.ylabel("predict_value")
plt.show()

#ランダムフォレストのR2：0.724

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/5b84c257-d8cc-2408-208f-f6f3cd166edc.png)

見慣れたグラフを描きました。

##Pytorchのディープラーニングでグラフを描くためには

ポイントは、予測結果は、gpu（cuda）で扱うための`tensor`形式になっているため、それをcpuで扱える形式に戻して、さらに`numpy`にする必要があります。`.to('cpu').detach().numpy().copy()` この部分です。

```Python
#予測結果のグラフ
import numpy as np
# ディープラーニングを評価モードに設定
net.eval()

#tesonr形式になっているtestデータセットの特徴量データをdevice（gpu：cuda）に送る。
data = test_x.to(device)

#gpuに送ったデータを評価モードのＤＬで予測する
y_pred = net(data)

#ここでy_predは、gpu（cuda）で計算するtensor形式なので、これをcpuで扱うnumpyに戻す必要がある。
#.to('cpu')で、gpuからcpuモードに戻す
# .detach().numpy().copy()で、tensor形式からnumpy形式に戻して、コピーする
y_pred_cpu = y_pred.to('cpu').detach().numpy().copy()


from sklearn.metrics import r2_score
dl_scorer = r2_score(test_label, y_pred_cpu)  
print('ディープラーニングのR2：{:.3g}'.format(dl_scorer))

#ディープラーニングのR2：0.718
```

`PyTroch`で使うデータは、`numpy`から`tensor`形式へ変更し、CPUで計算するか、GPUで計算するかで異なってきます。予測結果を`matplotlib`でグラフで書くためには、'tensor'形式から`numpy`へ、GPUからCPUへ戻す必要があります。
これは１行で書けます。
`y_pred_cpu = y_pred.to('cpu').detach().numpy().copy()`
`to('cpu')`で、gpuからcpuモードに戻す
`detach().numpy()`で、`numpy`形式に戻す。


`numpy`に戻れば、後は、ランダムフォレストの結果とディープラーニングの結果を合わせてグラフにするだけです。

##DeepLearningとRandomForestの結果の比較


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/7ce92c83-812c-38ac-96c4-044e13b9367e.png)

`Pytorch`のディープラーニングの設定が適当なので、あまり精度はよくありませんが、これでランダムフォレストとディープラーニングの比較の可視化ができました。