機械学習アプリ上のプロットを再現したいんですが・・

# はじめに

画面中央に出ている応答と予測を比較するこのプロットです。

<img width="750" alt=”回帰学習器アプリ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/63756e69-8bc4-7287-dd88-a495ccb3b82b.png">

回帰学習器アプリでアルゴリズムを試して精度を検証したはいいが、グラフに表示されるこのグラフの値はどうやって計算しているんだ？　と初めての方は気になると思いますのでまとめておきます。

MATLAB Answers でも、

> アプリの回帰学習器を用いて予測したプロットデータの応答の値を、テキストなどで出力をしたいのですがどうしたらいいですか。（[MATLAB Answers: 「回帰学習器を用いて予​測したプロットデータ​の応答の値の出力」](https://jp.mathworks.com/matlabcentral/answers/481087-?s_eid=PSM_29435)より引用）

とか、

> CSVファイルからインポートしたデータを用いて回帰学習器を使用した時,出力される応答プロットの値と関数を出力するにはどうすれば良いでしょうか．（[MATLAB Answers: 「回帰学習器の応答プロットについて」](https://jp.mathworks.com/matlabcentral/answers/492982-?s_eid=PSM_29435)より引用）

など、アプリ上の結果を再現したい、他にも応用したいという声もあります。


## 環境

MATLAB (R2019b)
Statistics and Machine Learning Toolbox
ここでは R2019b を使っていますが R2019a でもできるはず。


# さて、やってみよう

回帰学習器アプリの基本的な使い方は [回帰学習器アプリにより回帰モデルに学習をさせる](https://jp.mathworks.com/help/stats/train-regression-models-in-regression-learner-app.html?s_eid=PSM_29435) や [回帰モデルのオプションの選択](https://jp.mathworks.com/help/stats/choose-regression-model-options.html?s_eid=PSM_29435) を参照してください。

## まずはデータの準備 

[サンプルプログラム](https://www.mathworks.com/help/stats/train-regression-trees-using-regression-learner-app.html?s_eid=PSM_29435) でも登場する車の燃費データを使ってみます。

```matlab

load carbig
cartable = table(Acceleration, Cylinders, Displacement,...
Horsepower, Model_Year, Weight, Origin, MPG);
```

以下はデータ読み込み時の画面ですが、交差検証（５分割）を選んでいることに注目。

![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/8b428d5c-e6d2-7f98-3486-aa1eac174b96.png)

## モデル学習

好きなモデルでどうぞ。R2019b からはベイズ最適化でパイパーパラメータも調整してしまうボタンもあります。ここでは最初に選ばれている「複雑な決定木」（最小リーフサイズ 4）で学習させます。

それぞれの名称の意味合いについてはこちらが参考になるかもしれません：[MATLAB Answers: 分類学習器の学術論文中での名称](https://jp.mathworks.com/matlabcentral/answers/413840-?s_eid=PSM_29435)

![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/63756e69-8bc4-7287-dd88-a495ccb3b82b.png)

これで冒頭の画面できました。このプロット（応答と予測）を再現します。


## 結果をプログラムで再現してみる

「関数の生成」ボタンから同じ学習を行う関数を出力してみると、処理内容のヒントが見つかります。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/423a0133-de59-d365-0e19-1746381d18a8.png)

「関数の生成」ボタンをクリックすると関数が出てきますが、最後の 3 コマンドにご注目。
5分割の交差検証を実行しています。この結果がプロットされているみたいです。

```matlab

% 交差検証の実行
partitionedModel = crossval(trainedModel.RegressionTree, 'KFold', 5);

% 検証予測の計算
validationPredictions = kfoldPredict(partitionedModel);

% RMSE 検証の計算
validationRMSE = sqrt(kfoldLoss(partitionedModel, 'LossFun', 'mse'));
```

ただ、この生成された関数の冒頭をみてみると

```matlab

function [trainedModel, validationRMSE] = trainRegressionModel(trainingData)
```

と、`trainedModel`（モデル）と `validationRMSE`（RMSE値）は出力しているんですが、`validationPredictions` （検証予測）は出力されていません・・。もったいない。

```matlab

function [trainedModel, validationRMSE, validationPredictions] = trainRegressionModel(trainingData)
```

と書き換えて trainRegressionModel.m として保存します。


ここまでくると、


```matlab

load carbig
cartable = table(Acceleration, Cylinders, Displacement,...
Horsepower, Model_Year, Weight, Origin, MPG);
[trainedModel, validationRMSE, validationPredictions] = trainRegressionModel(cartable);

plot(MPG,'.');
hold on
plot(validationPredictions,'.');
hold off
```

と実行すれば、、

![untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/e38473f7-ec07-0402-b03f-7d70a011e3e1.png)

と出てきます。


## いや、なんかいろいろ違う

見栄えがずいぶん違います。せっかくなのでアプリ上の表示に近づけてみましょう。バージョン R2019a から Figure を取り出せるようになっているのでこれを最大限活用していきます。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/423a0133-de59-d365-0e19-1746381d18a8.png)

今度は「プロットを Figure にエクスポート」ボタンをクリックして

![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/fdf93c10-da1e-b9ba-fb80-238c18680168.png)

こんな Figure が出てきます。ここからさらに「ファイル」->「コード生成」をクリックすれば、この Figure を作る関数を確認できますね。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/54075aeb-0fa2-6a54-d22c-bb4c63c2f699.png)

一部抜粋すると

```matlab

% line を作成
line(XData1,YData1,'DisplayName','真',...
    'Tag','MLearnAppTracePlotTrainingDataTrace',...
    'Parent',axes1,...
    'MarkerSize',18,...
    'Marker','.',...
    'LineStyle','none',...
    'Color',[0 0.447 0.741]);

% line を作成
line(XData2,YData2,'DisplayName','予測',...
    'Tag','MLearnAppTracePlotPredictionsTrace',...
    'Parent',axes1,...
    'MarkerSize',18,...
    'Marker','.',...
    'LineStyle','none',...
    'Color',[0.929 0.694 0.125]);
```

という行が見つかります。プロットに `line` 関数など使ってますが、'MarkerSize' が 18 であること、そして 'Color' 情報も再現には重要。ここの情報を活用します。

```matlab

load carbig
cartable = table(Acceleration, Cylinders, Displacement,...
Horsepower, Model_Year, Weight, Origin, MPG);

[trainedModel, validationRMSE, validationPredictions] = trainRegressionModel(cartable);

plot(MPG,...
    'MarkerSize',18,...
    'Marker','.',...
    'LineStyle','none',...
    'Color',[0 0.447 0.741]);

hold on
plot(validationPredictions,...
    'MarkerSize',18,...
    'Marker','.',...
    'LineStyle','none',...
    'Color',[0.929 0.694 0.125]);
hold off
grid on
```

こんな感じ。実行すると

![untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/185e1ab4-9e55-b837-e1e7-c0550d2eb154.png)

できあがり。


# まとめ

回帰学習器アプリの結果をプログラムで再現する方法を紹介しました。もう 1 つの[分類学習器アプリ](https://jp.mathworks.com/help/stats/classification-learner-app.html?s_eid=PSM_29435)でも同じような作業で、分類結果をプログラムで再現できるはずですので、興味のある方は是非試してみてください。

そして、感の良い人（目の良い人）は気が付いたかもしれませんが、今回紹介したプロットは乱数の影響で同じ結果とはなっていません。そこまで厳密に合わせる場合には

```
rng(0)
```
などで、回帰学習器アプリで学習させる前、プログラムの冒頭で乱数生成器の初期化を試してみてください。