Watson Machine Learningの継続的学習システム( Continuous Learning System )を試してみた


![image](https://qiita-image-store.s3.amazonaws.com/0/108535/8cfd04db-0451-cd08-4943-58a063d01600.png)

# はじめに
先日、Qiitaで「[機械学習案件を納品するのは、そんなに簡単な話じゃないから気をつけて](https://qiita.com/yoshizaki_kkgk/items/fa8b45918445bb3e6dc3)」という記事を拝読しました。機械学習の案件で筆者がご苦労した話・注意すべき点をまとめたもので、1000近く「いいね！」が付いた人気の記事です。その中で成果物の定義や完了基準設定の難しさと共に

> そうなると実運用していくためには、**毎日情報を自動的に収集**して、**予測値を計算**して、その**結果を報告出来る**ような仕組みを作らないといけません。
> これってオフラインで解析していたときとは全く異なるスキルで、**Webによるシステム自動化**の知識が必須になってきます。

と機械学習モデル開発とは別の「実運用（サイクル）のための仕組み」の必要性とオープンソースを使った実装例に言及されていました。
なぜ冒頭でこの記事を引用させて頂いたかというと、今回ご紹介するWatson Machine Learningの**継続的学習システム( Continuous Learning System )**が、**まさに「そういうこと」をやるもの**だから、です。（←人気の記事に乗っかるようでちと気が引けましたが、私がここで「継続的学習の必要性」をあれこれ説くより、上記のご経験を読んでいただくのが「一番わかりやすくて腹落ちする背景説明」だと思ったのです。）

:triangular_flag_on_post: (2018/06/21) 記事を少し手直ししたのですが、ついでにDSXは古いので、新しい名前であるWatson Studioに直しました。

# WMLの継続的学習システム( Continuous Learning System 以下CLS)って何 ?

WMLのCLSとは、何か新しいサービスのアイコンができたわけではなく、WMLに組み込まれた「機能の名称」です。記事「[IBM Cloud上で機械学習モデルを簡単に作れる「Watson Machine Learning」を使ってみた★2017/11 Update](https://qiita.com/ishida330/items/0b60bc6f715df9da641c)」と説明が一部被りますが、WMLは2017/11に下図　右側のオレンジ部分の機能が追加され、**チームでのデータ分析プロジェクトの全ライフサイクルをカバー**できるようになりました。(といっても第一弾に過ぎず、今後も機能拡張は続きます。）この絵の下段の「モニター～フィードバック」の部分をCLSと呼びます。


![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b02810cc-a81e-42de-5962-eaa85ff64b60.png)

下記はイメージ図で一番下の段がCLSです

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/d5124d4f-b342-1055-b125-cdac4e007ee7.png)


CLSが具体的に何をしてくれるかというと、

:one: 新しいデータを使って、現在本番にデプロイされているモデルの性能劣化の有無を評価してくれる
:two: もし性能が劣化していた場合（＝事前に指定したしきい値を下回った場合）、改めて新しいモデルを作ってくれる
:three: 新旧モデルの性能を比較し、新しいモデルのほうが性能が良ければ、古いモデルと入れ替えてくれる
:four: 上記をすべて自動的に行ってくれる

といったものです。

:arrow_right: モデル性能のしきい値は「ROC(Receiver Operating Characteristic)値」または「PR(Precision/Recall)値」のいずれかで設定します
:arrow_right: 現時点ではCLSは「オプション＝そう構成すればやってくれる」という位置付けです。別の言い方をすると、**設定しなければ何も行いません**ので、「知らない間に勝手に本番に新しいモデルがデプロイされてしまった」という事態は起こりません
:arrow_right: より正確に言うと、**CLSは開発環境でトレーニング・データを使って作ったモデルを新しいデータで再評価するもの**であり、評価対象のモデルは必ず本番にデプロイされていなければならないわけではありません。 つまり、モデルが実際に本番にデプロイされていなくても、CLSでの再評価は実行できます。

余談ですが、SPSSでは従来から[Collaboration and Deployment Service. 略称 CADS](https://www.ibm.com/jp-ja/marketplace/spss-collaboration-deployment-services)というオプション製品で同様のことを行えていました。今、WMLはSpark/Pythonなどのオープンな環境下でCADSを一所懸命に追いかけている、といった感じですかね。


# （ちょっと寄り道）そもそも、なんで本番でモデルの性能（精度) が劣化するの？

識者の方には笑われそうですが、初心者の方向けに一応、念のため。
一般に（予測分析のための）モデルは本番にデプロイした後、長期にわたって同一のモデルを利用していると、様々な外部環境の変化によってモデルの精度(正答率)が落ちてくると言われています。性能劣化の要因は

- 時間経過による客層の変化
- 時間経過による顧客の好み・行動の変化
- なんらかの顧客アクションを行ったことによる変化

などがあります。例えば（この後の例で取り上げる）アウトドア・ショップでのテントの購入予測であれば、オン・シーズンである春・夏はよく売れるでしょうが冬になれば売れなくなるでしょう(＝顧客の好み・行動の変化）。にもかかわらず一年中同じモデルで予測していては、「はずれ」が増えてくるのも道理です。また、景気や流行により人気商品は変遷しますし、一年中「ディスカウント・クーポン」のキャンペーンをやっていると顧客が慣れてしまいキャンペーンに反応しなくなる、などのケースもあるでしょう。

そういうわけで「モデルは腐る」ので、**常に最適な結果を得るために、モデルは（新しいデータを入力して）定期的にリフレッシュ・再構築する必要がある**、ってことです。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/86d677a1-cc11-cc5b-50d8-9deb2314c1ba.png)

# CLSの構成と振る舞い
## フィードバック・データ
初期のモデル作成の入力データはCSVでもDBでもOKですが、現時点、フィードバック・データはDb2 Warehouse on cloud(旧名:dashDB)のテーブルとして格納しておく必要があります。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/87369040-5a3d-0cae-3af6-4e5c59a8dbc5.png)

- テーブル名は任意
- カラム構造はモデル作成時のものと同じで、末尾に **_training**　というTIMESTAMP型のカラムを追加
- データは手でコピーしてもよいし、投入のためのAPIもある
- 基本的に本番データなど「新鮮なもの」を入れておく（でないと再評価の意味がない）

## 構成の設定

下記はキモの部分の設定画面の例です(APIを使っても設定できます)

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/c19254d9-d15e-d379-e39a-16064ed4bcf5.png)

この設定で以下の流れに沿ってバッチ形式で性能評価とフィードバックが行われます。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/e7e8ab34-f2d3-1c22-dc9c-fa1ec5795af3.png)

- 「min_feedback_data」以上の件数が蓄積されないと評価は行いません（1件しかないのに評価しても仕方ないですからね! )
- 評価とは、現在のモデルにフィードバック・データを適用し、ROC値(またはPR値)を算出することです
- **AUTO_RETRAIN**がALWAYSなら常に新しいモデルを作ります(トレーニングします）
- **AUTO_RETRAIN**がCONDITIONALLYの場合は、指定した「しきい値（threashhold)」を下回ったら「劣化している」と判定し、新しいモデルを作ります。（この段階では現在のモデルの性能と比較するわけではありません）
- **AUTO_DEPLOY**がALWAYSなら常に新しいモデルを自動的にデプロイします
- **AUTO_DEPLOY**がCONDITIONALLYなら「現在のモデルのROC値(またはPR値）」と新モデルの値を比較し、新モデルのほうが優れている場合にのみ新しいモデルを自動的にデプロイします

一点、はじめの性能評価(evaluate)の起動自体はどうすればいいの、という点ですが、①UIからボタンを押して起動　②[APIから起動](http://watson-ml-api.mybluemix.net/#!/Published32Models/evaluateModel)　のいずれかで、どちらにせよ現時点(2017/12)では「**要求した時点で１回だけ**」実行されます。本来はジョブのスケジューラーがあればいいのですが、生憎、現時点では未実装です。（今後出てくる予定と聞いていますので、ご安心ください。）ゆえに現時点で定例運用として回すのであれば②のAPIを叩く仕組みを何らかの方法で定期的に実行することになるでしょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b57da427-a6df-9b7a-c0d5-387cfae19b6d.png)

# Watson Studio上のUIでCLSをやってみる
:warning: 残念ながらCLSは「ずっと無料」の**ライト・アカウントではお試しいただけません。**CLSではフィードバック・データはDb2 Warehouseに格納する必要があるのですが、2018/06月現在、Db2 Warehouseはライトアカウントの対象になっていないためです。 とはいえDb2 Warehouseは1GBまでは無料枠があるので、通常アカウントに移行しても無料で試すことは可能です。
:warning:(2018/06/21追記) [@makaishi2](https://qiita.com/makaishi2)さんから頂いた情報ですが、**Db2のライトプランではダメ**で、あくまでDb2 Warehouse [^1] である必要があるそうです。（技術的には同じようなものだと思うのですが、チェックしているらしい）
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/e75f601e-372d-bf87-b460-76e4a53fae72.png)

[^1]: 単なるネタですが、Db2Warehouseと通常のDb2で、ロゴの縦横が違うのをご存知でしたか?前者はカラムナーなので縦、後者は通常なので横になってます。


ではやってみます。

### シナリオ
シナリオは記事「[IBM Cloud上で機械学習モデルを簡単に作れる「Watson Machine Learning」を使ってみた★2017/11 Update](https://qiita.com/ishida330/items/0b60bc6f715df9da641c)」で使ったテントの購入予測とします。

- 同記事の内容に沿って、ウイザードを使ってモデルが完成してデプロイされた状況を開始点とします。（モデルの作成手順は割愛します）
- 追加でDb2 WHoCのインスタンスを作成し、Watson Studio上の「DataService-Connection」でコネクションを定義しておきます。

### フィードバック・テーブルの作成

Db2 WHoCで以下のように末尾に_trainingカラムが追加されたテーブルを作成しておきます。

:warning: (2018/04/09追記) 今しがた下記DDLを新しいDB2 Warehouse on Cloudで実行したら「SQL20521N  "_" の付近の条件付きコンパイル・ディレクティブの処理中にエラーが発生しました。 理由コード = "7"。」でエラーになりました。調べた結果、「_training」を「"_training”」とダブル・クオートで囲んだらうまくいきましたので、下記を直しておきます。(仕様変わった?) なお[ドキュメントの記述](https://console.bluemix.net/docs/services/PredictiveModeling/pm_service_api_spark_learning_system.html#continuous-learning-system)によると、今は事前にテーブルを作成しておく必要は無く、ウイザード上でテーブル名を指定すれば「あれば利用、なければ自動的に作成」してくれるようです。ので「事前作成」は必須ではなくオプションです。

>フィードバック表が存在しない場合、当サービスによって作成されます。表が存在する場合、スキーマが検証されてトレーニング表のスキーマと一致しているか確認され、_training という名前の列が表に付加されます。この追加列は、リトレーニング・プロセスでコンシュームされたレコードをマークするために使用されます

```sql
CREATE TABLE DASH11528.TENT_FEEDBACK_DATA							
(							
	IS_TENT VARCHAR(5),						
	GENDER VARCHAR(1),						
	AGE SMALLINT,						
	MARITAL_STATUS VARCHAR(11),						
	PROFESSION VARCHAR(12),						
	"_training" TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP						
)							
ORGANIZE BY COLUMN;							

```

### モデルの準備

今回は実験なので、まず[GoSales_Tx_LogisticRegression.csv](https://dataplatform.ibm.com/exchange/public/entry/view/ba9a3008817bbf458eea4980294e618b)の先頭100件、300件を抜いたCSVを用意し、各々モデルを作っておきました。（筆者の今月の予測数が逼迫してきたので不本意ながら少ない件数でやってます）モデルの性能は以下のような感じです。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b0907d68-df84-1298-34c6-5dbe9ed55d2e.png)

100件のCSVで作ったモデル(TENT_100)のROCは0.68、300件のCSVで作ったモデル(TENT_300)のROCは0.50でしたので、TENT_100の方が性能が良いです。よって、TENT_300のモデルを本番にデプロイし、ROCのしきい値を0.7にしておけば、TENT_300に100件のフィードバックデータを適用したときに 0.68 < 0.7でしきい値を下回ったことになり、再トレーニングが期待できます。この流れでやってみます。

### CLSを構成する

Watson Studio上でTENT_300のモデルを開き、「Evaluate」タブの下部「Configure Performance Monitoring」をクリック。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/03aaade4-9af3-d4b5-a11f-9e7cf5d72e46.png)

構成パネルです。
① 評価基準はareaUnderROCを選び、敷居値を0.7にします
② MINのレコード件数は(今回は)10とします(100件で起動させるため)
③ Auto Retrainは「when model performance is below threshold」にします。今回は「ROCが0.7を下回ったら」の意味になります。
④ Auto Deployは「when model performance is better than previous version」を選びます。今回は「モデル TENT_300よりTENT_100の方が性能が良ければデプロイせよ」の意味になります。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/4d980d4e-ef4c-c6f0-64ec-b8c13a7167d5.png)

⑤をクリックすると別パネルが開くので、で先程作ったフィードバック・データを格納するテーブルを選択します。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/92e1ac75-0a6e-25d6-6721-7fa93342a5b4.png)

戻ると以下のようになります。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/d9575233-d4b5-757f-fd14-3e5f203e2b0e.png)

これで構成は完了ですので「Save」。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/5a37503e-c838-d09f-a58e-a5138e6a308f.png)

では実際にフィードバック・データをDb2 WHoCに追加しましょう。「add feedback data」をクリックして、CSVをアップロードします。
:arrow_right: データは事前に何らかの方法で入れておいても結構です。その場合は「New evaluation」をクリックすると評価が始まります
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/04c37769-bc63-f1c9-3be3-bc1a6ac273d2.png)

データのアップロードが終わると以下のポップアップが出るので「New evaluation」ボタンを押すと評価が始まります。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/5ab50ae2-54bc-854c-1009-4888a83540f9.png)

進行状況が表示されます。(完了まで2-3分かかります）

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/195fa8c2-156d-afa5-b66e-8aac0e7cf76c.png)

完了しました。一応、期待通り新しいモデルが本番にデプロイされました。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/fdc7daf9-28cf-24d4-f17b-2a4754a412e6.png)

下記のように再評価の結果はグラフで時系列に見られます。当初ROC値が0.502でした。フィードバック・データでの再評価の結果は0.50としきい値0.7を下回ったので再トレーニングが開始されました。結果、0.514と当初の0.502より上回ったので新しいモデルがデプロイされました。(上記で「一応」と書いたのは、当初、100件からモデルを作ったときには性能が0.68だったからです。当初のモデル構築とCLSのモデル再構築では何か違いがあるのかもしれませんが、今は情報が無くわかりません。わかったら追記しますが、今は結果オーライ、ということで　:smirk: )

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/9459defb-273f-fbc7-0b52-d4d006c2f853.png)

:warning: ちなみにモデルが本番にデプロイされていない状況でCLSを実行してみたのですが、メッセージ上は「New Version Deployed」となりますが、新しいバージョンが作られるだけで強制的にデプロイされるわけではなさそうなので、ご安心ください。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/e09e15df-f3b9-8639-490f-13b0a62b79d3.png)

### CLSの評価の起動について

前にも述べましたが、現在(2017/12)はCLSの処理の起動自体は①UIからボタンを押して起動　②[APIから起動](http://watson-ml-api.mybluemix.net/#!/Published32Models/evaluateModel)　のいずれかで、どちらにせよ「**要求した時点で１回だけ**」実行されます。スケジューラが早く出てきてほしいですね。

以上「やってみた」でした。

# 余談: Liteプランでの予測件数の上限について

筆者は未だ旧TrialアカウントなのでDb2 WHoCが使える=CLSが実行できているのですが、feedback_dataの再評価時にはLiteプランの制約である「月5000回までの予測」が適用されるようです。当初、フィードバック・データに10,000件入れて評価しようとしたら以下のように怒られてしまいました。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/e5f7e3cd-520f-abea-836f-2df7e8a081c5.png)

結果、枠がもったいないので100件に減らした次第です。最初のモデル構築時は60,000件入力してもOKだったのに、再評価の時だけこの制約が適用されるって、どうよ？と思いますが、これが仕様なのかは今はわかりません。まあTrialアカウントは基本、廃止されているので小さい話ですが。ただ、先に述べたように現時点ではCLSを使うならStandardアカウントにアップグレードする必要がありますが、その場合でも「お勉強」フェーズでは無用な課金を避けるために、あまり大量のフィードバックデータを入れないほうがいいかもしれません。（このあたりは後で情報が入手出来たら追記します。)

ちなみにWMLでのリソース利用状況は以下のように見ることができます。（Watson StudioではなくてWMLのほうです）

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/a02ef231-841c-1928-bb49-4c880c185873.png)



# APIでもできます
今回はWatson StudioのUIでやってみましたが、同様のことをすべてAPIを使って自動化することも可能です。ご興味のある方はサンプルとしてPythonのNotebook [From spark ml model to learning system with python](https://dataplatform.ibm.com/analytics/notebooks/57bd0753-ccee-42bd-9d11-099a981e4fbe/view?access_token=40b77775b209dab516811a695ba1d5dbcab2dfb260c910daf3d985c9d4570325)が提供されており、Watson Studio上でそのまま実行できるので、試してみてください。

# 参考文献 
お披露目ブログ: [Machine learning should happen constantly](https://www.ibm.com/blogs/bluemix/2017/10/lifelong-machine-learning-automation-can-help-models-get-smarter-time/)

ドキュメント [Continuous learning system](https://console.bluemix.net/docs/services/PredictiveModeling/pm_service_api_spark_learning_system.html#continuous-learning-system)

[APIで実行するときのサンプルNotebook](https://dataplatform.ibm.com/analytics/notebooks/57bd0753-ccee-42bd-9d11-099a981e4fbe/view?access_token=40b77775b209dab516811a695ba1d5dbcab2dfb260c910daf3d985c9d4570325) 

以上です.　Have Fun with Machine Learning ! :sun_with_face: