LoginSignup
35
24

More than 3 years have passed since last update.

Amazon Personalizeでやらかさないための使い方とLamdbaでの使用方法

Last updated at Posted at 2019-06-19

Amazon Personalize の一般提供を開始!

先日Amazon Personalizeの一般提供を開始しました。
プレビューの段階からお試しで使っていたので作成の一連の流れを説明していきます。
今回はユーザーに商品を推薦するモデルとエンドポイントの作成を行います。
APIGatewayLambdaを使用してAPIも作成しました。

Amazon Personalize の一般提供を開始

課金体系(絶対に最初に目を通す!!!)

料金
データ取り込み 0.05 USD/GB
トレーニング 0.24 USD/トレーニング時間
レコメンデーション
最初の 20K TPS-時間まで 0.20 USD/1 TPS-時間のリアルタイムレコメンデーション
次の 180K TPS-時間 0.10 USD/1 TPS-時間のリアルタイムレコメンデーション
200K TPS-時間以上 0.05 USD/1 TPS-時間のリアルタイムレコメンデーション

やらかしてしまった(大量のリクエストには気をつけて!!!)

後に記述しますがboto3を使用してレコメンドを取得します。
調子に乗ってAPIを叩きまくってしまった結果がこれです。
image.png

pose_zetsubou_man.png
やらかしました。3124.7$って何円だっけ?(約33万円)思考停止です。

ユーザーがおよそ3万人いたのでどんな商品が推薦されるのか知りたくてこんなコードを書いたらなってしまいました。

len(users)
# およそ3万
for user in users:
    recommend_item = personalizert.get_recommendations(
        campaignArn="<Campaign ARN>",
        userId=user['user_id'],)

personalizert = boto3.client(
    'personalize-runtime',
    region_name='ap-northeast-1')

のちに記述しますが、エンドポイント設定のTPSの上限値を低く設定して入れば回避できていました。(激しく後悔)

1. データを用意する

Amazon Personalizeにデータを読み込ませる際、S3にアップロードされたcsvファイルを使用します。
必要なデータ(ファイル)は以下の3つ(データセットの説明)
私はRedshiftからデータを取得し、pandas等を利用してcsvファイルを作成しました。

  • ユーザーIDと商品IDが紐づいているデータ
  • ユーザーIDにユーザー情報が紐づいているデータ
  • 商品IDに商品情報が紐づいているデータ

それぞれ必須フィールドや予約キーワードがあります。

ユーザーIDと商品IDが紐づいているデータの例

ユーザーID、商品ID、購入時刻のUNIX時間が格納されているファイル

user_item.csv
USER_ID,ITEM_ID, TIMESTAMP
582,456,1477897643
582,458,1477897643
582,490,1472037749
601,855,1472033257
601,451,1472033257
601,451,1472033257
602,454,1472033266
..................

USER_IDITEM_IDTIMESTAMPが必須フィールドです。 予約語としてEVENT_TYPEEVENT_VALUEが用意されています。AWSのドキュメントを読んでみた感じでは,EVENT_TYPEは購入方法(ネット購入や店舗購入)などのデータ、EVENT_VALUEは商品の値段などのデータを入れるフィールドだと感じました。

ユーザーIDにユーザー情報が紐づいているデータの例

ユーザーID、年齢、性別が格納されているファイル

user.csv
USER_ID,AGE,GENDER
180,71,male
185,55,female
332,30,female
352,51,male
365,22,female
..................

USER_IDが必須フィールドで残りのAGEGENDERデータセットの説明を真似しました。

商品IDに商品情報が紐づいているデータの例

商品ID、商品名、商品カテゴリーIDが格納されているファイル

item.csv
ITEM_ID,ITEM_NAEM,CATEGORY_ID
461,歯ブラシ(青),1
693,オールスパイス ,10
112,赤ワイン,9
113,白ワイン,9
369,キャンドル(10本入),6
867,三角帽,15
..................

ITEM_IDが必須フィールドで残りのITEM_NAEMCATEGORY_IDはこれもデータセットの説明をまねしてみました。フィールドを増やしても問題なさそうです。

2. S3にファイルをアップロードし、バケットポリシーを設定する

PersonalizeからS3にアクセスするためにバケットポリシーを作成します。

{
    "Version": "2012-10-17",
    "Id": "PersonalizeS3Bucket AccessPolicy",
    "Statement": [
        {
            "Sid": "PersonalizeS3BucketAccessPolicy",
            "Effect": "Allow",
            "Principal": {
                "Service": "personalize.amazonaws.com"
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<作成したバケット名>",
                "arn:aws:s3:::<作成したバケット名>/*"
            ]
        }
    ]
}

2.データをインポートする

作成したcsvファイルをS3にアップロードしたら、Personalizeのコンソール画面からDataset groupsを作成します。
スクリーンショット 2019-06-12 14.13.54.png

csvファイルのヘッダ名と同じようにSchema definitionを編集します。
スクリーンショット 2019-06-12 14.25.10.png

IAM service roleは今回は既存の物を使用しましたが、ここでも作成できます。
Data locationにS3のパスを書いてインポート開始です。
スクリーンショット 2019-06-12 14.29.21.png

ダッシュボードをみるとCreate in progressになっています。
この調子でUser dataItem dataも作成していきます。
スクリーンショット 2019-06-12 14.35.40.png

User dataを作成
スクリーンショット 2019-06-12 14.57.48.png

Item dataを作成
スクリーンショット 2019-06-12 14.53.04.png

3. solutionsを作成する

データのインポートが全て終了したらsolutionsを作成します。
スクリーンショット 2019-06-12 15.07.50.png

Automatic(AutoML)にチェックを入れるとインポートしたデータから適したモデルを作成します。
割と時間かかりました(1時間以上はかかった気がします)。
モデルをトレーニングするためのレシピの一覧
今回はaws-hrnnaws-hrnn-metadataを使用していきます。
スクリーンショット 2019-06-12 15.11.47.png

4. campaignを作成する

campaignの名前、solutionを設定、スループットの下限を設定して作成(30分くらい)。

(重要!)スループットの下限はなるべく少なくした方がいいです。DynamoDBのキャパシティーと同じ感じです。私はこの値をテキトーに200にして、エンドポイントを叩きまくってしまった結果高額な請求がきてしまいました。

スクリーンショット 2019-06-12 16.20.39.png

5. レコメンドしてみる

campaignの作成が完了するとレコメンドのテストがコンソール画面上から行えるので適当なユーザーIDでテストしてみます。
スクリーンショット 2019-06-12 16.35.56.png
商品IDが複数推薦されます。画面では表示しきれてないですが25件推薦されました。

6. boto3から実行する

とりあえずローカルの環境から取得できるか、試してみました。

main.py
import boto3

if __name__ == "__main__":

    personalizert = boto3.client('personalize-runtime', region_name='ap-northeast-1')

    response = personalizert.get_recommendations(
        campaignArn="<Campaign ARN>",
        userId='<User ID>',)

    for item in response['itemList']:
            print (item['itemId'])

注意点

ローカルのaws-cliにpersonalize-runtimeがない場合があるのでサービスを追加する必要があります。
各サービスのjsonをダウンロードしてaws-cliにセットするだけなのですぐできました。

AWS CLI のセットアップ

7. APIを作成する

SeverlessFrameWorkを使用してAPIを作成しました。

コードなど

serverless.yml
service: personalize-test

provider:
  name: aws
  runtime: python3.7
  stage: stg
  region: ap-northeast-1
  profile: test

functions:
  recommend:
    handler: src/handler.get_recommend
    events:
      - http: GET /{user_id}
handler.py
import json
import boto3


def get_recommend(event, context):
    user_id = event['pathParameters']['user_id']
    personalizert = boto3.client('personalize-runtime', region_name='ap-northeast-1')

    response=personalizert.get_recommendations(
        campaignArn="<Campaign ARN>",
        userId=str(user_id),)

    item_list = []

    for item in response['itemList']:
        item_list.append(item['itemId'])

    body = {
        'item_list': item_list
    }

    response = {
        'statusCode': 200,
        'isBase64Encoded': False,
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps(body)
    }

    return response

問題発生

sls deployでデプロイをしたらAPIのエンドポイントが表示されるのでcurlで試してみたところInternal Server Errorが返って来ました。
CloudWatchのログを見た所以下のログが出ました。

[ERROR] UnknownServiceError: Unknown service: 'personalize-runtime'. .....

内容としてはboto3personalize-runtimeというサービスはないとのこと。githubのissueにもあがっていました。
解決策としてはamazon-linux上で最新のboto3をインストールし、zipで固めてLamdbaのLayerとしてboto3を使用するとのことでした。
AmazonPersonalizeはつい最近一般公開されたばかりでLambdaのboto3の対応が間に合っていないんですかね。

以前の記事(pandasをLambdaのLayerとして追加する)で似たようなことを行なったので同様にzipファイルを作成しました。
作成したzipファイルはgithubにあげましたので使用される人がいれば使ってみてください。

いざ再び

$ curl https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/stg/242 | jq 
{
  "item_list": [
    "2200399000000",
    "4580118279049",
    "4580168655268",
    "4580216370631",
    "4571243110208",
    "4512442005292",
    "2400040256128",
    "4954540129232",
    "2430002732278",
    "4512442005490",
    "4982757911630",
    "4997640091030",
    "4997640092105",
    "4512442005179",
    "4976631605029",
    "2400040918354",
    "2401020995907",
    "4536361026251",
    "2430002792463",
    "4573222000029",
    "2430000383120",
    "4580127310146",
    "4571243110130",
    "4539427300012",
    "2430000362002"
  ]
}

返ってきたー!これで既存のアプリケーションへの利用もできそうです。

終わりに

今回でAmazon Personalizeの課金体系を身をもって感じたのでみなさんも気をつけてください。 それでもAmazon Personalizeは簡単にレコメーンデーションを作成するとても素晴らしいAIサービスなのでご利用は計画的に。
今回はEvent trackersは使用しませんでしたが、Event trackersを使用すればリアルタイムにレコメンデーションをすることができるので知見がたまり次第紹介しようと思っています。

ユーザーインタラクションイベントの記録

35
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
24