Azure Machine Learningのデザイナーでレコメンデーションの動作を確認する。

# はじめに
Azure Machine Learningの強みとして、自動で機械学習を行い最初のモデルを迅速に得ることが可能なAutoMLやドラッグアンドドロップ中心でコードフリーにモデルの学習が行えるデザイナーという機能が存在します。某案件でAzureでレコメンドができることを紹介してくれと頼まれ、確かにあまりレコメンドのイメージが無かったので調べてみることにしました。

# AutoML
まずはAutoMLから確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/4ae38531-6f78-9c3d-6c88-5159dc615acf.png)
AutoMLはタスクの種類として分類、回帰、時系列予測のみをサポートしているようなので現時点でAutoMLは単純にレコメンドタスクには適用できなさそうです。

# Designer
そこで、デザイナーを確認してみることにします。Azure Machine Learning(classic)の方では確かレコメンドができたような気がしていたのでサンプルを探してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/a9e64fdc-2043-22bf-0f2d-3c36267f5ce7.png)

レコメンドのサンプルとして`Wide & Deep based Recommendation`というレストランのデータに関するレコメンドのサンプルと`Recommendation - Movie Rating Tweets`という映画の評価に関するレコメンドのサンプルがありました。この時点でレコメンド用のモジュールが用意されていることがわかり一安心です。

## Recommendation-Movie Rating Tweets
具体的に中身の方を見ていきましょう。まずはシンプルな`Recommendation-Movie Rating Tweets`から見ていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/67656f68-6d7f-3432-f25e-42bc3479f45d.png)

全体としてはデータ整形⇒データの分割⇒レコメンデーションのための計算⇒評価という流れになっています。入力データはユーザx映画x評価のレコードとMovieIdと映画名を紐づけるマスタが入力になっています。このような形で入力しているのは、このサンプルで使用しているSVD Recommenderの仕様だと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/c95de0c3-d6fa-6d10-53d7-7ca5aed1944d.png)

レコメンデーションにはSVD Recommenderを用いています。理論の詳細については[ドキュメント](https://docs.microsoft.com/ja-jp/azure/machine-learning/algorithm-module-reference/train-svd-recommender)に記載の[論文](https://datajobs.com/data-science-repo/Recommender-Systems-%5BNetflix%5D.pdf)を参照ください。

一部抜粋すると、
>このモジュールを使用すると、単一値分解 (SVD) アルゴリズムに基づいてレコメンデーション モデルをトレーニングできます。
Train SVD Recommender (SVD レコメンダーのトレーニング) モジュールは、ユーザー、項目、評価を表す 3 つの要素からなるデータセットを読み取ります。 これにより、トレーニング済みの SVD レコメンダーが返されます。 その後、トレーニング済みのモデルを使用して、SVD レコメンダーのスコア付けモジュールを使用して評価を予測したり提案を生成したりすることができます。

つまり、[Train SVD Recommender]では入力データに対して行列分解手法SVDを適用し、未評価の部分も値が入ったユーザx映画x評価のマトリクスを取得し、[Score SVD Recommender]でそのマトリクスに基づいた映画の推薦や評価の予測値を返すということです。[Score SVD Recommender]モジュールでは`Rating Prediction`を返すのか、`Item Recommendation`を返すのかが選択可能です。これは協調フィルタリングと呼ばれるタイプのレコメンドになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/1d4280d6-2a0d-f424-1d32-1a489cac4e2d.png)

`Item Recommendation`を選択すると、いくつかの条件を決めることができます(返すアイテムの個数、アイテムの範囲など)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/41c58f6a-f127-8e09-c094-e2d7118a9442.png)

こうして得られた各ユーザに対して推薦すべきアイテムのリストをDBやBlobに流し込み、アプリケーション側から参照することでレコメンドが完了します。

## Wide & Deep based Recommendation - Restaurant Rating Prediction
次にレストランのサンプルを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/1dcd162c-000e-4be5-dd0b-3c6820296fff.png)
こちらは入力が3つあり、[UserId x RestaurantId x 評価]のテーブルと[Userのマスタ]、[Restaurantのマスタ]が入力となっています。つまり、単純にユーザのレストランに対する評価行列だけでなく、レストランの類似度やユーザの類似度もそれぞれの属性から考慮することができるということです。

ユーザのマスタ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/64fb2736-70c5-bfb5-7182-7888907fba6f.png)

レストランのマスタ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/3900241c-91e1-fa26-6b55-c2715b140689.png)

よってこれはコンテンツベースフィルタリングと協調フィルタリングの両方を組み合わせたような手法になっています。詳細は確認していませんが、理論に関してはこちらも[ドキュメント](https://docs.microsoft.com/ja-jp/azure/machine-learning/algorithm-module-reference/train-wide-and-deep-recommender)に記載の[論文](https://arxiv.org/pdf/1606.07792.pdf)をご参照ください。

一部抜粋すると以下のような利点があります。
>このしくみは次のとおりです。ユーザーがシステムの比較的初心者である場合は、ユーザーに関する特徴の情報を使用することによって予測が向上します。このようにしてよく知られた "コールド スタート" の問題に対処します。 ただし、特定のユーザーから十分な数の評価を収集した後は、これらのユーザーに対して、その特徴だけではなく特定の評価に基づいて完全に個人的な予測を行うことができます。 そのため、コンテンツベースの推奨事項から協調フィルタリングに基づく推奨事項へのスムーズな移行があります。 ユーザーまたは項目の特徴を使用できない場合でも、ワイドかつディープなレコメンダーは協調フィルタリング モードで動作します。

つまり、あるユーザが過去に行った評価の数が少ない場合にもユーザやアイテムの類似度から推薦アイテムを導き出すことが可能であり、それによって購入が促され結果的に評価が溜まればそのまま協調フィルタリング手法も適用可能になります。

実際のシステムの場合はユーザ情報や商品情報に関するマスタが存在すると思うのでその情報を有効活用したい場合はこちらのモジュールを用いるのが無難だと思います。この場合も同様に、評価の予測値もしくは推奨アイテムのどちらかを選択できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/cc41135e-7ed4-efb9-d2ff-d02aa1172679.png)

# おわりに
ユーザが商品に対して行った評価のマトリクスが用意できるのであれば入力データを差し替えるだけでこのサンプルが推薦システムとして活用できます。また、評価がほとんどない場合でも、`Wide & Deep Recommender`の方を用いることでコンテンツベースの推薦を実現できます。

現在、デザイナー上で利用可能なレコメンドのためのモジュールはここで紹介した2種類だけなので、そこが物足りない気はします。また、レコメンドの場合はデプロイという概念がなく、単に計算結果を返しているだけなので、ユーザが追加されたり評価が一定以上溜まったタイミングで計算し直す必要があります。よってリアルタイムに近づけば近づくほど計算リソースも必要になってきますのでそこは強化学習なりの別のアプローチが必要かと思われます。