はじめに
これは,mediba Advent Calendar 2020 23日目の記事です.
medibaの野崎です.
現在は,バックエンドエンジニアとして au Webポータル などのプロダクトの担当し,バックエンドアプリケーションやインフラ範囲の運用を行っています.
また,兼務でテクノロジーセンターにて,TechLeadチームにも所属しています.
※参考:2020年度エンジニア組織について | mediba Creator × Engineer Blog
AWS Lambda の新機能 – コンテナイメージのサポート | Amazon Web Services ブログ
今月発表されたAWS Lambdaのコンテナイメージサポートされました.
Lambda 関数を最大 10 GB のコンテナイメージとしてパッケージ化し、デプロイできるようになりました。
とあるように, これまでより大きなサイズのパッケージが出来るようになり,
機械学習のモデルや自然言語処理(NLP)で利用する辞書データなどをコンテナに含めることが出来そうです.
そこで本記事では,訓練済みのWord2vecモデルをコンテナ内に含めAWS Lambda上で動かしてみます.
作る機能としては,入力したワードに対して類似したワードとその類似度(0~1の範囲の値)を返却するもので,これをAPI経由で呼び出せるようにします.
訓練済みのWord2vecモデルは,類似したワードを返却する部分で使います.
全体像としては,図のような形になります.
背景
なぜ今回このような検証を行うかを背景ですが,
au Webポータルではニュース記事の配信を行っているプロダクトがあり,
この機能としてニュース記事に対して自然言語処理(NLP)を施して提供しているものいくつかあります.
現在このシステムはEC2上で構築されていますが,
今後はコンテナ化あるいはサーバレス化への変更を検討しています.
この検討の一環として,掲題のような内容を思い立ちました.
実施した手順
AWS サーバーレスアプリケーションモデル - アマゾン ウェブ サービス
今回はAWS Lambdaのフレームワークとして,SAMを利用します.
1. sam init
以下のバージョンで進めていきます.
$ sam --version
SAM CLI, version 1.13.2
samプロジェクトの初期化を行います.
$ sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
What package type would you like to use?
1 - Zip (artifact is a zip uploaded to S3)
2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 2
Which base image would you like to use?
1 - amazon/nodejs12.x-base
2 - amazon/nodejs10.x-base
3 - amazon/python3.8-base
4 - amazon/python3.7-base
5 - amazon/python3.6-base
6 - amazon/python2.7-base
7 - amazon/ruby2.7-base
8 - amazon/ruby2.5-base
9 - amazon/go1.x-base
10 - amazon/java11-base
11 - amazon/java8.al2-base
12 - amazon/java8-base
13 - amazon/dotnetcore3.1-base
14 - amazon/dotnetcore2.1-base
Base image: 3
Project name [sam-app]: sam-wiki-entity-vectors
以下のようなプロジェクトが出来ます.
※以降の作業で含めるディレクトリ,ファイルも記載してあります.
.
├── README.md
├── __init__.py
├── events
│ └── event.json
├── hello_world
│ ├── Dockerfile
│ ├── __init__.py
│ ├── app.py
│ ├── requirements.txt
│ └── tohoku_entity_vector // 2. モデルの取得で作成するディレクトリ
│ ├── entity_vector.model.bin
│ └── entity_vector.model.txt
├── samconfig.toml // 7. sam deployで作成される
├── template.yaml
└── tests
├── __init__.py
└── unit
├── __init__.py
└── test_handler.py
2. モデルの取得
今回は東北大学 乾・岡崎研究室にて公開されている訓練済みのモデルを使わせていただきます.
上記サイトより以下の2つのファイルを取得し,samプロジェクト内にtohoku_entity_vector
ディレクトリを作成しこれらを格納します.
- バイナリファイル (
entity_vector.model.bin
) - テキストファイル (
entity_vector.model.txt
)
$ du -h hello_world/tohoku_entity_vector
2.6G
これらのファイルサイズは2.6GB
ありました.
3. コードの変更
プロジェクト内の以下のファイルを変更します.
requirements.txt
以下を追加します,
gensim
Gensimは,大規模コーパスを用いたトピックモデリング,文書インデックス作成,類似性検索のためのPythonライブラリです.
Dockerfile
COPY箇所を以下のように修正します.
tohoku_entity_vector/
もcopy対象に加えて,モデルもDockerコンテナに含めます.
COPY app.py requirements.txt tohoku_entity_vector/ ./
app.py
以下のように修正します.
import os
import json
from gensim.models import KeyedVectors
def lambda_handler(event, context):
word = event.get('queryStringParameters').get('word')
model = KeyedVectors.load_word2vec_format(
'./entity_vector.model.bin', binary=True)
result = model.most_similar('[' + word + ']')
return {
"statusCode": 200,
"body": json.dumps(result, indent=2, ensure_ascii=False),
}
most_similar
は,入力したワードに対して類似したワードとその類似度(0~1)を類似度順に返却します.
gensim.models.Word2Vec.most_similar
template.yaml
Globals
の項,メモリとタイムアウト値を変更します.
Globals:
Function:
Timeout: 900
MemorySize: 10240
どちらも上記クォータの上限まで上げてみます.
4. sam build
dockerを起動した状態で,以下のコマンドを実行します.
$ sam build
5.ローカルでの動作の確認
ローカル環境にて以下のコマンドで,apiのテストが行えます.
$ sam local start-api
ブラウザで以下のようにリクエストします.
クエリパラメータで入力した川崎フロンターレ
という入力に対して,
類似したワードとして,ジュビロ磐田
大分トリニータ
といったワードとその類似度が期待通り返却されました.大丈夫そうです.
6.ECRリポジトリの作成
以下のコマンドで,DockerイメージをPUSHする用のECRリポジトリを作成します.
aws ecr create-repository --repository-name repository-name
7.sam deploy
#初回
$ sam deploy --guided
#2回目以降
$ sam deploy
初回のデプロイでは,--guided
オプションをつけることによりデプロイ設定を選択していきます.samconfig.toml
が作成されます.
2回目以降のデプロイでは,このファイルを元にデプロイされます.
deploy
コマンドで,ECRへのimageのpushとAWS Lambdaへの関数のデプロイが行われます.
8.動作の確認
まずはECRのイメージを確認します.
PUSHされており,1.8GBほどあることが確認できます.
次に,APIの確認を行います.
今度はクエリパラメータで入力したFCバルセロナ
という入力を行い,
類似したワードとして,レアル・マドリード
ACミラン
といったワードとその類似度が期待通り返却されました.期待通りです.
APIのレイテンシは10sec程度でした.
機械学習システムのデザインパターン
本記事を執筆して知ったのですが,
メルカリ様にて,機械学習システムのデザインパターンを公開されていました.
機械学習システムの設計パターンを公開します。 | メルカリエンジニアリング
具体的なパターン別に,ユースケースや利点難点などが整理されています.
今回の構成は,Web single pattern | ml-system-design-pattern
こちらのパターンになりそうです.
まとめ
- Word2vecモデルをAWS Lambdaで動かしてみました
- Word2vecモデルをコンテナに内包出来るようになり,アプリケーションの開発が単純になりました
- これまでAWS Lambdaでサイズな大きなファイルを扱う場合は,EFSなどのサービス連携が必須でした
- AWS Lambdaの
関数のメモリ割り当て
を,どのように最適化するか検討が必要です