SPSS CADSで数値予測モデル・モニタリング①スクリプトで判定

SPSS CADSでカテゴリ値の予測については標準の機能で劣化検知を検知する、[モデル・モニタリング](https://qiita.com/kawada2017/items/43ea5d0a4589f402d9eb
)が可能です。

しかしながら、回帰などの数値予測のモデルにはこの機能が基本的には使えません。

二つの実現方法があります。
1. [Modelerスクリプトをつかってメトリクスから判定](https://qiita.com/kawada2017/items/14da0f87164e19674039)
1. [ダミーモデルを作って判定](https://qiita.com/kawada2017/items/5cc02756336317b8d4cb)

この記事では１の方法で実現してみます。

# メトリクスを算出するストリーム

数値予測のモデルにはMAPE、RMSE、R2乗などの評価メトリクスがあります。モデルの評価に使いたいメトリクスをストリームで算出します。
この例ではMAPEを算出してみます。

これは「濃度」を予測するモデルになっています。
以下で「abs(濃度 - '$E-濃度')/濃度」の平均を計算して、[MAPEを算出](https://qiita.com/416nishimaki/items/913e50090d3fee9ba19a)しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/bedd37ec-7d94-2e84-2011-e78bbf56ca9b.png)

以下のように「0.176」という結果がでました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/736b7aa1-4e88-9987-6f4f-7a5fc82fbd41.png)

このストリームのソースをフィードバックデータである「sensornew.csv」にして実行すると「0.211」という結果がでました。MAPEが劣化したことがわかります。これを検知してみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ebe1268a-cc6d-bc08-4d46-f9ef0bc168c5.png)

# メトリクスによってEXITコードを変えるModelerスクリプト
MAPEをメトリクスにして、ModelerのExitコードを切り替えるスクリプトを書きます。

まずMetricsのテーブルのIDを取得します。
そして、ストリーム・プロパティの「実行」タブにいって以下のスクリプトを貼り付けます。その際に、tablenode=stream.findByID("id8DAXZY53J45")に先ほどのテーブルIDを入れます。
実行すると「デバッグ」タブにMAPEの値が返ってきます。
「このスクリプトを実行」にチェックをつけて保存しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ef733f6f-8e7b-37c9-bb80-ca871787d2ec.png)

```python
import modeler.api
stream = modeler.script.stream()

# テーブルノードを実行
tablenode=stream.findByID("id8DAXZY53J45")

# 実行結果を取得
results = []
tablenode.run(results)
tableoutput = results[0]

# テーブル出力の内容を読み出し
tablecontent = tableoutput.getContentModel("table")
# テーブル内の値を読み出し
tablecontent = tableoutput.getContentModel("table")
metrics=tablecontent.getValueAt(0, 0)
print(metrics)
#メトリクスを基に劣化を判断
if metrics<=0.2:
    modeler.script.exit(0)
else:
    modeler.script.exit(100)
```

肝の部分は以下です。getValueAt(0, 0)でテーブルノードからメトリクスの値を取り出して、if文で0.2を超えたらexitコード100を返すという動きをしています。

```python
metrics=tablecontent.getValueAt(0, 0)
#メトリクスを基に劣化を判断
if metrics<=0.2:
    modeler.script.exit(0)
else:
    modeler.script.exit(100)
```

# モニタリングをするCADSジョブの作成
CADSのジョブを作り、ジョブ変数に「FILENAME」をつくりデフォルトは「sensorhist.csv」としておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9b03d54b-08d4-29e0-fd81-4f930d652988.png)


先ほどのストリームを配置します。
そして、Modeler Serverやコンテンツ・リポジトリ―サーバーとそれらのログイン情報を設定し、「ストリームの実行」を選んでおきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/19396159-225b-71f4-b57a-586df9877153.png)


そして、「データファイル」タブで入力ファイルを「${JobVariable.FILENAME}」で設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/975622a2-98c7-b150-0382-527295c1bdbb.png)

次に劣化ありの処理を作ります。本当はメールを送りたいところですが、今回のテスト環境ではメール発信ができなかったので、ダミーで「echo "ng"」を行う「全般」ステップを配置しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9eaa858e-23b2-b5a6-d548-f5644d1a7a8b.png)

そして、「条件付き」リレーションシップをつけ、条件には「completion_code == 100」を入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d59ea12d-4fff-1b77-4e80-7ef3917e7ec0.png)

これで先ほどのModelerスクリプトの「modeler.script.exit(100)」の場合に「劣化あり」のステップに進むことになります。

# テスト実行
ジョブをオプションありで実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b63b6556-17ad-0a4d-930a-94b882081b24.png)

FILENAMEは「sensorhist.csv」のまま実行します。MAPEは「0.176」になるはずなので、「劣化なし」になるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/28b15863-af9c-f837-3b56-7c6200c2e6f5.png)

結果は成功でした。modeler.script.exit(0)だったので、「劣化あり」になりませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/eef40a72-1b9a-9dce-06cc-4376b92a4800.png)


次にFILENAMEは「sensornew.csv」で実行します。今度は、MAPEは「0.211」になるはずなので、「劣化あり」になるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/45a13cea-0d8d-13e7-d204-6adc5b98b476.png)

「劣化あり」のステップが実行されていますので、正しく判定ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1c33c834-1322-5c89-aef8-866a0840c788.png)

しかしながら、この方法には一つ注意点があります。
それはジョブ全体の実行結果としては「失敗」扱いになってしまうことです。
運用でジョブが「失敗」なることをIT部門で監視している場合には、モデルの劣化であり、システム上の問題ではないのですが、監視に引っかかってしまうことになります。運用上ITとしては「劣化」の問題であれば無視するような運用が必要です。

# 環境とサンプル
* 環境
    * SPSS Modeler 18.4
    * SPSS CADS 8.4
    * Windows Server
* サンプルストリームとデータ

https://github.com/hkwd/spssmodelerscript/raw/master/240321scriptExec/scriptexec.str

https://raw.githubusercontent.com/hkwd/spsssample/master/240321CADSMLOpsContinous/sensorhist.csv

https://raw.githubusercontent.com/hkwd/spsssample/master/240321CADSMLOpsContinous/sensornew.csv

# 参考
#### 精度分析回帰の指標
https://qiita.com/kawada2017/items/bc543f0f1bb401854c0e#%E7%B2%BE%E5%BA%A6%E5%88%86%E6%9E%90%E5%9B%9E%E5%B8%B0%E3%81%AE%E6%8C%87%E6%A8%99

#### SPSS Modeler スクリプトでテーブルのデータを読み取る #SPSS - Qiita 
https://qiita.com/kawada2017/items/c883678b08032f4f3954
#### SPSS CADSのジョブでmodeler scriptを実行する

https://qiita.com/kawada2017/items/356858165e0d0989fb1d