前回の記事でGAになったばかりのAmazon Personalizeの使い方の解説をしました。 ただ、前回の記事では実際にアプリケーションから利用するところ、つまりWeb APIとして公開するところまでは書くことができませんでした。
ということでこの記事では、Serverless Frameworkと組み合わせることで半日でレコメンドAPIを公開する方法を書きたいと思います。
基本的なワークフローの解説については下の記事を参照してください。
またコード全体はGitHubにアップロードしており、記事の最後に記載しています。
それでは早速レコメンドAPIを作成していきましょう。
環境
まず前提として下記の環境を想定しています。これらの環境がない場合はインストール or アップデートしておいてください。
- Python: 3.7
- serverless-framework: 1.45.1
- boto3: 1.9.169
構成図
全体の構成図は下記のようになります。 複雑に見えるかもしれませんが、CloudFormation、API Gateway、Lambda部分は全てServerlessいい感じにやってくれるので作業としてはそんなに複雑ではないと思います。
プロジェクト作成&boto3の最新版利用
まず、Serverlessプロジェクトを作成します。
注意点としてAmazon Personalizeを利用するにはboto3の最新版が必要なので serverless-python-requirements
をインストールしておきます。
sls create -t aws-python3 -n serverless-amazon-personalize-example # boto3を最新版にするための準備 sls plugin install -n serverless-python-requirements pipenv install boto3 # Pipfileを作成するのでもOKです。
またboto3の最新版を使うために設定ファイルに下記のような設定を行います。
これは serverless-python-requirements
がデフォルトだとboto3のデプロイを除外してしまうためです。
serverless.yml
custom: pythonRequirements: usePipenv: true noDeploy: [pytest, jmespath, docutils, pip, python-dateutil, setuptools, s3transfer, six]
boto3の最新版をLambda Layerとしてデプロイする方法もあります。 そちらを使いたい方は下記の記事を参考にしてみてください。
- SageMakerとServerlessを組み合わせて、お手軽にscikit-learnの機械学習APIを作る - フリーランチ食べたい
- Lambda Layerを使ってデプロイを高速化する - フリーランチ食べたい
これでServerless側の事前準備は終了です。
Amazon Personalize準備
Amazon Personalize側の準備をしていきます。
一応前回の復習ですが、Amazon Personalizeには下記のようなリソースがあります。
それぞれが、
- Dataset Group: レコメンドアプリケーションのプロジェクト
- Datasets: データ
- Solutions: モデル
- Recipes: アルゴリズム
- Campaigns: 予測API
を表しています。
予測に必要なのはCampaignのARN のみです。今回は前回の記事と同じように条件で学習を行いCampaignのARNを出力するスクリプトを用意しました。
# データをダウンロード wget -N http://files.grouplens.org/datasets/movielens/ml-100k.zip unzip -o ml-100k.zip mv ml-100k data rm ml-100k.zip # データの読み込み/学習/予測準備 python scripts/train.py # => campaign_arn: arn:aws:personalize:xxxx....
実行するとCampaignのARNが出力されます。 データのアップロードから学習、予測準備まで行うので時間は20~30分くらいかかると思います。
Serverlessを使ってAPI作成
それではServerlessを使ってAPIを作成していきましょう。ポイントだけ抜粋して説明します。詳細な設定ファイルが見たい方は記事の最後までスクロールしてGitHubを見てください。
やることはシンプルで、次の2つです。
CAMPAIGN_ARN
という環境変数に今出力されたCampaignのARNを設定functions.events.http
にAPIのための設定
設定ファイルは次のようになります。
provider: environment: CAMPAIGN_ARN: arn:aws:personalize:... # 今出力されたCampaignのARNを入力 iamRoleStatements: - Effect: Allow Action: - "personalize:*" Resource: "*" functions: get_reccomendation: handler: handler.get_reccomendation events: - http: path: get/{user_id} method: get request: parameters: paths: user_id: true
呼び出されるPythonスクリプトは次のようになります。 pathParameters
からパラメータを読み取って、Amazon PersonalizeのAPIを呼び出すだけの単純な処理です。
handler.py
import json import os import boto3 CAMPAIGN_ARN = os.environ.get("CAMPAIGN_ARN") def get_reccomendation(event, context): user_id = event['pathParameters']['user_id'] # string personalize_runtime = boto3.client('personalize-runtime') recommendations_response = personalize_runtime.get_recommendations( campaignArn = CAMPAIGN_ARN, userId = user_id # stringでない場合はcastする必要がある ) item_list = recommendations_response['itemList'] response = { "statusCode": 200, "body": json.dumps(item_list) } return response
これで、あとはデプロイするだけです。 エンドポイントが出力されます。
sls deploy # 略 # endpoints: # GET - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/get/{user_id} # 略
作成されたエンドポイントにuser_idを適当に 384
と設定してリクエストを送ってみましょう。
curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/get/384 [{"itemId": "879"}, {"itemId": "264"}, {"itemId": "343"}, ...]
無事レコメンドされたItemId(映画のID)が返ってきました🍻 後はアプリケーション側でItemのマスタと紐付ければレコメンドAPIとして使えると思います。
さいごに
Amazon PersonalizeとServerless Frameworkを組み合わせて素早くレコメンドAPIを作成する方法を紹介しました。簡単にAPIが作成できるのは大きなメリットですね。
気になった点としてはAmazon PersonalizeがCloudFormationに対応していないことです。対応すればCloudFormationだけでレコメンドエンジンを作ることも可能(!)ではないでしょうか。
またUser属性やItem属性に情報を入れた場合の結果の違いや、他のタイプのアルゴリズムを使うと結果がどう変わるのかなどは、実際にプロダクトに使ってみて試したいと思います。また何か知見が得られたらブログにまとめますね!
今回使ったコードはすべてGitHubに上げています。 github.com