AWSでAIサービスを使ってみる〜第11回Personalize編〜

##Personalizeとは
>personalizeはレコメンデーション機能です。過去の購入履歴から顧客の好みを分析して顧客に気に入ってもらえそうな品物を提案します。

personalizeは次のように使います
①データの登録
・購入履歴等のデータをデータセット"と言います。

②ソリューションの構築
・データセットを用いた機械学習を行い、レコメンデーションを作成するための仕組みをを"ソリューション"と言います。

③キャンペーンの作成
・レコメンデーションを取得するために、ソリューションを公開します。ソリューションを公開する仕組みのことを"キャンペーン"と言います。

④レコメンデーションの取得
キャンペーンを使って、指定したユーザに対するレコメンデーションを取得します。

#####それでは実際にレコメンデーション機能を試してみましょう！

##使用するデータを前準備する
データの準備を行います。今回personalizeに必要なデータとして"購入履歴のデータ"と商品名を表示するために"アイテムのテキストファイル"用意します。

まず、購入履歴のデータを作成します。
(購入履歴のデータ条件として①最小で1000件の履歴、②2種類以上のアイテムを購入したユーザが、25人以上含まれていることが条件です。)

データの条件を満たすために乱数でuser_id,item_id,timestampを作成します。
(参考:[Amazon Personalizeでユーザの商品購入動向をもとにレコメンドしよう　〜フルマネージド機械学習サービスの素晴らしさとは〜](https://qiita.com/G-awa/items/7d18441737eb49906725))

以下がデータ作成ファイルになります。

```generate_data.py
import random
for i in range(10000):
  user_id = random.randrange(1,200)
  item_id = random.randrange(1,100)
  timestamp = random.randrange(886324817, 1086324817)
  print(str(user_id) + ',' + str(item_id) + ',' + str(timestamp))
```
ここでは細かな解説は省きますが。forで10000人分の購入履歴を作成
内容として1~200までのユーザ、1~100までのアイテム、timestamp(1970.1.1からの秒数)を作成

```
$ python generate_data.py >> data.csv
```
data.csvが出力されたら、1行目にUSER_ID,ITEM_ID,TIMESTAMPを追記して下さい。

```data.csv
USER_ID,ITEM_ID,TIMESTAMP
34,73,904649386
5,99,935674270
189,27,888559101
32,26,967717511
4,39,903661240
91,91,1063766187
132,32,1080580095
98,41,1013572384
77,54,1063375613
115,73,924382270
95,48,1026078188
....
#10000行目まで
```


次に商品IDの表示のみより商品名も表示された方がわかりやすいため、商品名も表示するための商品名のテキストファイルを作成します。

```item.txt
赤色ネズミ
赤色ウシ
赤色トラ
赤色ウサギ
赤色リュウ
赤色ヘビ
赤色ウマ
赤色ヒツジ
赤色サル
赤色トリ
赤色イヌ
赤色イノシシ
青色ネズミ
青色ウシ
青色トラ
青色ウサギ
青色リュウ
...
銀色イノシシ

赤いスイトピー
青い珊瑚礁
白いパラソル
小麦色のマーメイド
```

今回は100点の商品ということで
・十二支が8色で96種類
・残り4点は色繋がりで松田聖子さんをシングルを添えてみました(笑)

これで前準備は完了です。

##データを登録する
データをpersonalizeに登録するプログラムの全体

```pers_create_dataset.py
import boto3
import json
import time

personalize = boto3.client('personalize')
#辞書型のスキーマ定義
schema_json = {
  "type": "record",
  "name": "Interactions",
  "namespace": "com.amazonaws.personalize.schema",
  "fields": [
    {
      "name": "USER_ID",
      "type": "string"
    },
    {
      "name": "ITEM_ID",
      "type": "string"
    },
    {
      "name": "TIMESTAMP",
      "type": "long"
    }
  ],
  "version": "1.0"
}

schema_arn = personalize.create_schema(
  name='Personalize_TestSchema', schema=json.dumps(schema_json))['schemaArn']
print('schema ARN:', schema_arn)

group_arn = personalize.create_dataset_group(
  name='Personalize_TestGroup')['datasetGroupArn']
print('dataset group ARN:', group_arn)

start = time.time()

status = ''
while status not in ['ACTIVE', 'CREATE FAILED']:
  status = personalize.describe_dataset_group(
    datasetGroupArn=group_arn)['datasetGroup']['status']
  time.sleep(10)
  print('{:7.2f} {}'.format(time.time()-start, status))

dataset_arn = personalize.create_dataset(
  name='Personalize_TestDataset', datasetType='interactions',
  schemaArn=schema_arn, datasetGroupArn=group_arn)['datasetArn']
print('dataset ARN:', dataset_arn)

```

ここまでで定番のimport boto3とサービスクライアント作成は省略！
ここからは部分部分分けて解説します。

###スキーマの作成

```pers_create_dataset.py
#辞書型のスキーマ定義
schema_json = {
  "type": "record",
  "name": "Interactions",
  "namespace": "com.amazonaws.personalize.schema",
  "fields": [
    {
      "name": "USER_ID",
      "type": "string"
    },
    {
      "name": "ITEM_ID",
      "type": "string"
    },
    {
      "name": "TIMESTAMP",
      "type": "long"
    }
  ],
  "version": "1.0"
}

#スキーマ作成(create_schema())
schema_arn = personalize.create_schema(
  name='Personalize_TestSchema', schema=json.dumps(schema_json))['schemaArn']
print('schema ARN:', schema_arn)

```
・辞書とリストを使って、変数schema_jsonにUSER_ID、ITEM_ID、TIMESTAMPを代入しスキーマを定義します。
その後create_schemaメソッドを用いて、スキーマを作成します。
nameは任意でschemaは先程のschema_jsonをjson.dumpでJSON形式の文字列に変換し出力します。

###データセットグループの作成
次にデータセットグループを作成します。

```pers_create_dataset.py
#データセットグループを作成
group_arn = personalize.create_dataset_group(
  name='Personalize_TestGroup')['datasetGroupArn']
print('dataset group ARN:', group_arn)

start = time.time()
status = ''
while status not in ['ACTIVE', 'CREATE FAILED']:
  status = personalize.describe_dataset_group(
    datasetGroupArn=group_arn)['datasetGroup']['status']
  time.sleep(10)
  print('{:7.2f} {}'.format(time.time()-start, status))
```

create_dataset_groupメソッドでデータセットグループを作成します。
その後データセットグループが作成されるまで待ちます。
それまでwhile文とnot in演算子を用いてdescribe_dataset_groupメソッドでデータセットの情報が'ACTIVE'か'CREATE FAILED'になるまで取得し続けます。
途中経過の情報は.formatメソッドを表示され{:7.2f}は時間経過の全体を7桁、小数部分を2桁で表示することを表します。

###データセットの作成

```pers_create_dataset.py
dataset_arn = personalize.create_dataset(
  name='Personalize_TestDataset', datasetType='interactions',
  schemaArn=schema_arn, datasetGroupArn=group_arn)['datasetArn']
print('dataset ARN:', dataset_arn)
```

最後にcreate_datasetメソッドでデータセットを作成します。
datasetTypeではinteraction,users,itemsと選択出来ますが今回はinteractionsで行きます。

##データセットの登録の実行

```
python pers_create_dataset.py
```

登録ファイルを実行するとデータセットグループの作成の進捗が表示され、無事であれば少々お待ちいただくとデータセットが登録されます。
これは私がよくあったエラーですが、すでにスキーマやデータグループのみPersonalizeに作成されてしまっている場合は、Personalizeのコンソールでスキーマやデータセットグループを削除し、スキーマ名やデータセットグループ名を変更して実行していただければうまくいくかと思います。

##まとめ
Personalizeは実際のおすすめ商品がわかるまでまだボリュームがあるため何回に分けて紹介します。

##参考文献
この記事は以下の情報を参考にして執筆しました。

[Amazon Personalizeでユーザの商品購入動向をもとにレコメンドしよう　〜フルマネージド機械学習サービスの素晴らしさとは〜](https://qiita.com/G-awa/items/7d18441737eb49906725)

[AWSでつくるAIプログラミング入門](https://www.amazon.co.jp/AWS%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B-AI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E6%9D%BE%E6%B5%A6-%E5%81%A5%E4%B8%80%E9%83%8E/dp/4798059056)