POS のダミーデータを作って Amazon Personalize を使って商品レコメンドを予測してみる
はじめに
おはようございます、もきゅりんです。
Amazon Personalize (以下 Personalize) がどんなものかを調べている際、例えばこんなデータだったらどうなるの?といった疑問が湧いたので試してみました。
本稿は、Personalize にこんなデータを入力したらこんな結果出てくるのではないだろうか?(いいや、出てこない) の検証を通じて Personalize の理解を進めるブログです。
機械学習に詳しい方々、 Personalize に詳しい方々に特に目新しい情報はないと思います。
Personalize 全然知らん、でも使ってみたい、興味ある、という人が対象です。
なお、 Personalize の使用方法については特に説明しません。
カスタムデータセットを使ってコンソールでポチポチしていっただけです。
ソリューションについてはレシピを aws-user-personalization
をデフォルトで設定しています。
使い方については、弊社ブログに多数ありますのでご参考下さい。
本稿での学び
- Personalize でレコメンドされるアイテムを予測する(人為的に狙わせる)のは素人にはかなり困難。
-
まずは、重要と思われる特徴量を増やしたり、モデルのトレーニングには不要と考えられるデータを省くなど、モデルの評価メトリックを大きくするためにできそうなことに専念する。
-
比較ベースラインとなる Popularity-Count レシピの評価メトリクスを超えることが第一目標。
-
その上で、結果に不要なものをフィルタリングおよび追加検証していく、が基本的な使い方。
検証内容
本稿での検証内容です。
前提となるデータは以下のとおりです。
- POSデータは、購入日時と店舗ID、商品ID、商品名、商品数、顧客ID、性別(男女)、年齢が取得できているとしています。(店舗IDは全く利用していません。)
- POSデータのユーザーは、1099レコードで、20~60代、男女でそれぞれ5人ずついるとしています。(Personalize を利用するための最低限の条件となるデータを作成してます)
- POSデータのアイテムは、適当な商品名となる、20アイテムです。
- 期間は2022/8/1 ~ 2022/8/31の1ヶ月間としています。
データイメージ
データの売上個数ランキング
ランキング | アイテムID | 売上個数 |
---|---|---|
1 | 5 (ハエ叩き) | 154 |
2 | 2 (ジーパン) | 153 |
3 | 4 (ゴルフクラブ) | 142 |
データの表示回数ランキング
ランキング | アイテムID | 表示回数 |
---|---|---|
1 | 4 (ゴルフクラブ) | 73 |
2 | 5 (ハエ叩き) | 68 |
3 | 2 (ジーパン) | 67 |
このデータを使って以下2つの検証をします。
- ex1 各世代、性別、年齢ごとに売れてる商品を1つも買ってないユーザーがいる、人気商品をレコメンドするかどうか
- ex2 明らかに似た傾向を持ってるユーザーがいる、そのユーザーを参考に購入していない人気商品をレコメンドするかどうか
ex1 の特徴量を USER_ID(string)、ITEM_ID(string)、TIMESTAMP(long) と USER_ID(string)、ITEM_ID(string)、TIMESTAMP(long) 、GENDER(string)、AGE(int) の2つで対応しました。 *1
ex2 の特徴量を USER_ID(string)、ITEM_ID(string)、TIMESTAMP(long) と USER_ID(string)、ITEM_ID(string)、TIMESTAMP(long) 、GENDER(string)、AGE(int) と ITEM_ID(string)、TIMESTAMP(long) 、ITEM_COUNT(int)、GENDER(string)、AGE(int) の3つで対応しました。
結果として、ex1 は前者のモデルが、 ex2 最初と最後のモデルが甲乙つけがたかったため、それらの検証結果を、それぞれ ex1-1, ex2-1, ex2-3 としています。
またそれらのモデルにキャンペーン作成時に Emphasis on exploring less relevant items をデフォルト(0.3)から 0 に変更させて生成したものに + (e.g. ex1-1+) が付いています。
以上で検証内容の説明は終わりです。
検証まとめ
検証結果のまとめです。
- User-Personalization レシピ結果
ユーザーID | 期待した結果 | ex1-1 | ex1-1+ | ex2-1 | ex2-1+ | ex2-3 | ex2-3+ |
---|---|---|---|---|---|---|---|
1 | 1 (ヌンチャク) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
6 | 2 (ジーパン) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
11 | 3 (ソバ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
16 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
21 | 5 (ハエ叩き) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
26 | 6 (コスメ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
31 | 7 (雑誌) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
36 | 8 (パジャマ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
41 | 9 (ゴージャスバッグ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 9 (ゴージャスバッグ) | 9 (ゴージャスバッグ) |
46 | 10 (洗濯バサミ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 9 (ゴージャスバッグ) |
- Popularity-Count レシピ結果
ユーザーID | ex1pop | ex2-1pop | ex2-3pop |
---|---|---|---|
1 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
6 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
11 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
16 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
21 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
26 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
31 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
36 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
41 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
46 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
期待した結果にはできませんでした。
何となくですが、モデルの評価がベースラインとなる Popularity-Count レシピの評価メトリクスを超えていかないと、各人に対するレコメンドは各人に合わせて変化しないような気がしました。(全く根拠はありません)
検証方法
各検証の内容です。
1 各世代、性別、年齢ごとに売れてる商品を買ってないユーザーいるけど、その商品をレコメンドするかどうか
どんな状況か、言葉で説明するよりも表で見た方が分かりやすいと思います。
例えば、20代男性間ではヌンチャクが売れているとします。しかし、ユーザーIDが1である対象者はヌンチャクを買っていません。
このような状況が各世代で発生しているとしています。
このようなデータを用いて、各世代・性別で売れているアイテムはレコメンドされるのでしょうか。
レコメンドされるのかい、されないのかい、どっちなんだいっ?!
1 結果と考察
され....
なあーーい!
かすりともしない。
ex1-1のモデルの評価メトリクス
ex1-2のモデルの評価メトリクス
GENDER と AGE を入れることでモデルの評価メトリクスが下がってしまいました。
ex1-popの評価メトリクス
どうも比較水準となる、Popularity-Count レシピの評価メトリクスと大差がない感じです。
(つまり優れたモデルではなさそうです)
そもそも機械学習でレコメンドといえば、協調フィルタリングだよね、じゃあとりあえず傾向が類似するようなユーザー作ってみるぞ!
ということで、いそいそとデータを手動で修正します。
2 明らかに似た傾向を持ってるユーザーが1人いるけど、そのユーザーを参考に商品をレコメンドするかどうか
下の図を見て頂ければ判る通り、横並びのユーザー同士の傾向はかなり似てると思います。
(オマケの節で見るように、実際に相関係数は高いです)
(ヌンチャク買って欲しいなー)
(ジーパン買って欲しいなー)
このようなデータを用いて、似たような傾向を持っていて売れているアイテムはレコメンドされるのでしょうか。
されるのかい、されないのかい、どっちなんだいっ?!
2 結果と考察
され....
るー!
のが1つだけあった。
けど、これは偶然と思われる。
そもそも単純な「相関分析」を応用した協調フィルタリングですら、非常に似通っているユーザー1人の評価にレコメンドは依存するわけではなく、類似していると考えられる複数ユーザーの評価からも影響します。
レコメンデーションの取得 - Amazon Personalize のユーザー パーソナライゼーション レコメンデーション スコアリングの仕組み に参考となる数式があります。
自分はまるで詳しくないのですが、機械学習でレコメンドによく利用される協調フィルタリングにもさまざまなタイプが存在し、またそれらを組み合わせたハイブリッドも利用されているようです。
データが巨大になればなるほど、各特徴量が複雑に影響し合って、出力されるレコメンドを予測するのも(素人には)かなり困難になるわけです。
かすってくれたら嬉しいなーと思いましたが、無駄な徒労でした。
ex2-1のモデルの評価メトリクス
ex2-1-popの評価メトリクス
ex2-2のモデルの評価メトリクス
GENDER
と AGE
を入れることで評価は下がってしまっています。
ex2-3のモデルの評価メトリクス
ex2-3-popの評価メトリクス
どうも比較水準となる、Popularity-Count レシピの評価メトリクスの方が高そうな感じです。
Popularity-Count レシピによるレコメンドの影響はかなり大きい気がします。
(つまり、レコメンドにおいて全体的に売れている商品の影響力は大きい)
検証結果を再掲します。
検証結果(再掲)
User-Personalization レシピ結果
ユーザーID | 期待した結果 | ex1-1 | ex1-1+ | ex2-1 | ex2-1+ | ex2-3 | ex2-3+ |
---|---|---|---|---|---|---|---|
1 | 1 (ヌンチャク) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
6 | 2 (ジーパン) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
11 | 3 (ソバ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
16 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
21 | 5 (ハエ叩き) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 4 (ゴルフクラブ) | 4 (ゴルフクラブ) |
26 | 6 (コスメ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
31 | 7 (雑誌) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
36 | 8 (パジャマ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 3 (ソバ) |
41 | 9 (ゴージャスバッグ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 9 (ゴージャスバッグ) | 9 (ゴージャスバッグ) |
46 | 10 (洗濯バサミ) | 5 (ハエ叩き) | 5 (ハエ叩き) | 2 (ジーパン) | 2 (ジーパン) | 3 (ソバ) | 9 (ゴージャスバッグ) |
Popularity-Count レシピ結果
ユーザーID | ex1pop | ex2-1pop | ex2-3pop |
---|---|---|---|
1 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
6 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
11 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
16 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
21 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
26 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
31 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
36 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
41 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
46 | 4 (ゴルフクラブ) | 5 (ハエ叩き) | 5 (ハエ叩き) |
データの売上個数ランキング
ランキング | アイテムID | 売上個数 |
---|---|---|
1 | 5 (ハエ叩き) | 154 |
2 | 2 (ジーパン) | 153 |
3 | 4 (ゴルフクラブ) | 142 |
データの表示回数ランキング
ランキング | アイテムID | 表示回数 |
---|---|---|
1 | 4 (ゴルフクラブ) | 73 |
2 | 5 (ハエ叩き) | 68 |
3 | 2 (ジーパン) | 67 |
さいごに
自分で温かみのあるデータを作って、仮説と結果を見比べることで、疑問を感じて Personalize に触れることで理解が深まった気がします。
レコメンドロジック、難しい、と。
引き続き、機会があったら Personalize を触っていきたいと思います。
以上です。
どなたかのお役に立てたら幸いです。
オマケ
あまりにレコメンドがかすりもしないので、実際に古典的な協調フィルタリングを Google Colab で実装して試してみました。
Pythonでレコメンドシステムを作る(ユーザベース協調フィルタリング) - け日記 を参考としました。
ほら、どう考えても隣同士のユーザーは類似してるよね。
じゃあレコメンドはどうなるんだいっ?!
あーーー。3番目がヌンチャクかー。洗濯バサミが1番かー。
脚注
- Emphasis on exploring less relevant items、Exploration item age cutoff はデフォルト値です。 ↩