今週、Amazon PersonalizeがGAになりました。東京リージョンでも使うことができます。
この記事ではAmazon Personalizeの概要、使い方の解説を行います。PythonのAWS SDKを使ってレコメンドアプリケーションを作成していきます。
また事前準備のS3やIAM Roleの作成で、AWSの公式ドキュメントだと手作業が発生しているのですが、それだと大変なので一発で構築できるCloudFormationも紹介します。
最初に触った感想
少し触ってみたのですが、以下の点で非常に良いと思いました。
- 学習・予測(レコメンド取得)が全てサーバーレスで行える
- 事前に準備されているアルゴリズムはDeep Learningベースで多く、それ以外も高度なもの
逆に以下のような不満な点もありました。
- 用語が機械学習で一般的に使うものとかけ離れていて混乱する
- ARNを引数に渡す処理が多く、CloudFormationで管理したいがまだ対応していない
1つめの不満点はこの記事で図解して解説してみました。2点目はCloudFormationに対応するのを待ちたいですね。
Amazon Personalizeとは
レコメンデーションアプリケーションを簡単に構築できるマネージドサービスです。 AWSの同様の機械学習サービス、Amazon SageMakerにも似ていますが、下記のような違いがあります。
- レコメンデーションアルゴリズムに特化している(データ形式/出力が制限されている)
- モデルの学習も稼働もサーバーレス(サーバーを意識する必要がない)
標準的なレコメンデーションに特化したサービスです。
Amazon Personalizeの構成
Amazon Personalizeはそれぞれの用語にクセがあって最初理解し辛いので、登場人物を図にまとめました。
この図に記載した通り、より一般的な言葉に直すと
- Dataset Group: レコメンドアプリケーションのプロジェクト
- Datasets: データ
- Solutions: モデル
- Recipes: アルゴリズム
- Campaigns: 予測API
になると思います。
またそれぞれの登場人部の関係性は次のようになります。
これだけだと理解するのが難しいと思うので、とりあえず一通り手順を試してみて、この図を改めて見てもらうのがいいかもしれません。
Amazon Personalizeでレコメンドアプリケーションを作成する手順
Amazon Personalizeでレコメンドアプリケーションを作成するには下記の手順を作業する必要があります。
- 事前準備1: RoleやS3バケットを作成する
- 事前準備2: 使うデータをダウンロードする
- データセットグループを作成する
- データセットに学習データのインポートを行う
- ソリューションを作成する
- キャンペーンを作成する
- レコメンドを行う
この順番でそれぞれの手順を書いていきたいと思います。
もしこの記事でわからないことがあったり、もっと詳細が気になった方はドキュメントを参照してください。
環境
- Python: 3.7
- boto3: 1.9.168
- botocore: 1.12.168
事前準備1: RoleやS3バケットを作成する
Amazon Personalizeの利用に際して事前に必要なAWSのリソースは次の2つです。
- S3バケット
- IAMロール
手作業がなくて済むようにこれらを作成するCloudFormation設定ファイルを書きました。
https://github.com/ikedaosushi/python-sandbox/blob/master/az-personalize/cloudformation.yml
この設定ファイルをもとにCloudFormationのStackを作成します。
STACK_NAME=amazon-personalize-example-stack REGION=ap-northeast-1 TEMPLATE_FILE=file://cloudformation.yml aws cloudformation create-stack \ --stack-name $STACK_NAME \ --region $REGION \ --template-body $TEMPLATE_FILE
これで事前準備1が完了しました。
CloudFormationで作成したリソースは、下記のように取得して以降で使用しています。
stack = boto3.resource('cloudformation').Stack(STACK_NAME) STACK_NAME = "amazon-personalize-example-stack" outputs = {o["OutputKey"]: o["OutputValue"] for o in stack.outputs} S3_BUCKET_NAME = outputs["S3BucketName"] IAM_ROLE_ARN = outputs["IAMRoleArn"]
事前準備2: 使うデータをダウンロードする
もう1つの準備として使うデータをダウンロードして手元に用意します。 今回はレコメンド用のテストデータとしてよく用いられるMovieLensを使います。 AWSのドキュメンテーションでも使われています。
wget -N http://files.grouplens.org/datasets/movielens/ml-100k.zip unzip -o ml-100k.zip rm ml-100k.zip
これで準備完了です。
データセットグループを作成する
それではAmazon Personalizeでアプリケーションを作成していきましょう。本当はこれ以降もS3バケットやIAMロールと同じようにCloudFormationで作成できればよかったのですが、まだAmazon Personalizeが対応していないのでPythonで作成していきます。
Amazon Personalizeを使うにあたり、まずレコメンドアプリケーションプロジェクトの単位となるデータセットグループを作成します。
以降のコードでは下記のように作成したboto3のAmazon Personalizeのクライアントを使うことを前提とします。
personalize = boto3.client('personalize') personalize_runtime = boto3.client('personalize-runtime')
次のようにデータセットグループを作成します。
create_dataset_group_response = personalize.create_dataset_group( name = "amzon-personalize-example-dataset-group" ) dataset_group_arn = create_dataset_group_response['datasetGroupArn']
実行するとデータセットグループが作成されます。
データセットに学習データのインポートを行う
次にデータセットに学習するデータのインポートを行います。 下記の3ステップで行っていきます。
- データセットのSchemaを作成する
- データをSchemaに合わせて加工し、S3にアップロードする
- データセットを作成し、S3からデータセットに読みこむジョブを作成する
データセットのSchemaを作成する
データセットにデータを読み込むにはSchemaを作成する必要があります。
公式のチュートリアルでは、映画に対するユーザーの評価であるRatingを使用していないのですが、今回はより実際に即するために使用した例にしたいので必須のフィールドである、 USER_ID
、 ITEM_ID
、TIMESTAMP
に加えて EVENT_TYPE
、 EVENT_VALUE
を作成しておきます。この2つのフィールドも予約語として決まっています。
schema = { "type": "record", "name": "Interactions", "namespace": "com.amazonaws.personalize.schema", "fields": [ { "name": "USER_ID", "type": "string" }, { "name": "ITEM_ID", "type": "string" }, { "name": "EVENT_TYPE", "type": "string" }, { "name": "EVENT_VALUE", "type": "string" }, { "name": "TIMESTAMP", "type": "long" } ], "version": "1.0" } create_schema_response = personalize.create_schema( name = "amzon-personalize-example-schema", schema = json.dumps(schema) ) schema_arn = create_schema_response['schemaArn']
実行するとデータセットのSchemaが作成されます。
データをSchemaに合わせて加工し、S3にアップロードする
今、作成したSchemaに合わせてデータを加工し、S3にアップロードします。
filename = "amazon-personalize-example" data = pd.read_csv('./ml-100k/u.data', sep='\t', names=['USER_ID', 'ITEM_ID', 'RATING', 'TIMESTAMP']) # Amazon Personalizeに合わせた形に整形 data["EVENT_VALUE"] = data["RATING"] data["EVENT_TYPE"] = "rating" data = data[['USER_ID', 'ITEM_ID', 'EVENT_TYPE', 'EVENT_VALUE', 'TIMESTAMP']] # csvファイルとして書き出し data.to_csv(filename, index=False) # アップロード boto3.Session().resource('s3').Bucket(S3_BUCKET_NAME).Object(filename).upload_file(filename)
加工したデータは下記のようになります。
EVENT_TYPE
には種類を EVENT_VALUE
には値を入れます。
Rating以外の例としては、クリックの回数や閲覧回数などが考えられます。
データセットを作成し、S3からデータセットに読みこむジョブを作成する
まずAmazon Personalize上にデータセットを作成します。
dataset_type = "INTERACTIONS" create_dataset_response = personalize.create_dataset( name = "amazon-personalize-dataset", datasetType = dataset_type, datasetGroupArn = dataset_group_arn, schemaArn = schema_arn ) dataset_arn = create_dataset_response['datasetArn']
S3からデータセットに読みこむジョブを作成します。
create_dataset_import_job_response = personalize.create_dataset_import_job( jobName = "amazon-personalize-dataset-import-job", datasetArn = dataset_arn, dataSource = { "dataLocation": f"s3://{S3_BUCKET_NAME}/{filename}" }, roleArn = IAM_ROLE_ARN ) dataset_import_job_arn = create_dataset_import_job_response['datasetImportJobArn']
インポートジョブが完了するとデータセットが作成されます。
ポイントとしては User-item interaction
と書いてある行のデータセットのみが作成されていて User
と item
と書いてある行のデータセットは空になっていることです。これは上のスクリプトで dataset_type = "INTERACTIONS"
と指定したからで他に USER
ITEM
と指定できて、それぞれ下記のような情報を付与できるようです。これらは必須ではないので今回は作成しません。
ユーザー — このデータセットではユーザーに関するメタデータを提供します。これには、年齢、性別、ロイヤリティメンバーシップなど、パーソナライゼーションシステムで重要なシグナルとなる情報が含まれます。 アイテム — このデータセットでは、アイテムに関するメタデータを提供します。これには、価格、SKU タイプ、可用性などの情報が含まれます。
ソリューションを作成する
それではデータセットが準備できたので、ソリューションを作成します。 ソリューションという名前ですが、モデルを学習させるパート、と理解して問題ありません。
ソリューションを作成するには、今作成したデータセットの指定とレシピの指定をする必要があります。レシピとは学習するアルゴリズムのことです。事前準備したもの、あるいは自分でカスタマイズしたものも使うことができるようです。
コンソールから使えるアルゴリズムを確認することができます。
それぞれのアルゴリズムを詳しく知りたい場合は、公式ドキュメントを参照してください。 パッと見た感じ、ほとんどがDeepLearningを使ったアルゴリズムのようです。
事前定義済みレシピの使用 - Amazon Personalize
今回は、階層型リカレントニューラルネットワーク (HRNN) を使います。 ソリューションを作成します。
recipe_arn = "arn:aws:personalize:::recipe/aws-hrnn" create_solution_response = personalize.create_solution( name = "amazon-personalize-dataset-solution", datasetGroupArn = dataset_group_arn, recipeArn = recipe_arn ) solution_arn = create_solution_response['solutionArn']
「ソリューションのバージョンを作成する」ことがモデルを学習させることにあたるようです。 バージョンを作成します。
create_solution_version_response = personalize.create_solution_version(
solutionArn = solution_arn
)
solution_version_arn = create_solution_version_response['solutionVersionArn']
学習にはしばらく時間がかかります。(10~20分)
完了するとコンソール上でソリューションがActiveなことを確認できます。
ソリューションの詳細を見るとバージョンもActiveになっています。
キャンペーンを作成する
学習が完了したらレコメンドを行うためのキャンペーンを作成します。
create_campaign_response = personalize.create_campaign( name = "amazon-personalize-dataset-campaign", solutionVersionArn = solution_version_arn, minProvisionedTPS = 1 ) campaign_arn = create_campaign_response['campaignArn']
これだけです。簡単ですね。 完了するとコンソールからもキャンペーンが作成され、Activeになっていることが確認できます。
レコメンドを行う
それではレコメンドを行ってみましょう。適当にユーザーIDを選んで呼び出してみます。
user_id = 384 get_recommendations_response = personalize_runtime.get_recommendations( campaignArn = campaign_arn, userId = str(user_id) ) item_list = get_recommendations_response['itemList'] title_list = [item_maps[int(item["itemId"])] for item in item_list] print(f"Recommendations: {json.dumps(title_list, indent=2)}")
出力結果は下記の通りです。
Recommendations: [ "George of the Jungle (1997)", "Murder at 1600 (1997)", "Devil's Own, The (1997)", "Spawn (1997)", "Volcano (1997)", "Crash (1996)", "G.I. Jane (1997)", .... ]
ユーザーID: 384に対するレコメンドされた映画のリストを取得できました。
今回は USER_PERSONALIZATION
タイプのアルゴリズムであるHRNNを使ったのでレコメンドされた映画に順位関係(よりレコメンドされる)はありません。 SEARCH_PERSONALIZATION
を使えば映画内のレコメンド順位が得られるようです。
アルゴリズムのタイプによって呼び出しに必要なデータが下記のように変わってきます。
以上でレコメンドアプリケーションを作成することができました。
さいごに
GAになったばかりのAmazon Personalizeの解説とCloudFormationとPythonでレコメンドアプリケーションを実際に学習/デプロイする方法をまとめました。 実際にWebApplicationとして使いたい場合はLambdaと組み合わせるのが良いと思います。 そんなときにServerless Frameworkが便利なので次の記事でWebApplication APIの作成方法をまとめます。
※追記: 書きました
使ったコードはGitHubにあげてあります。Jupyter Notebookへのリンクですが、同じディレクトリにCloudFormationの設定ファイルなどもあります。
またレコメンドアルゴリズム自体の入門記事は以前書いたので興味のある方はこちらもご覧ください🙏