Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CyberAgent AI事業本部2024年度MLOps研修実践編 / MLOps Practice

CyberAgent AI事業本部2024年度MLOps研修実践編 / MLOps Practice

CybagerAgent AI事業本部 2024年度新卒研修 MLOps 実践編で使用したスライドです。
ハンズオンで使用したGitHub Repository: https://github.com/hosimesi/aws-mlops-practice

同年度のMLOps研修資料はこちらです。
(1/4) CyberAgent AI事業本部2024年度MLOps研修Container編: https://speakerdeck.com/szma5a/container-for-mlops
(2/4) CyberAgent AI事業本部2024年度MLOps研修基礎編: https://speakerdeck.com/nsakki55/mlops-basic
(3/4) CyberAgent AI事業本部2024年度MLOps研修応用編: https://speakerdeck.com/tyaba/mlops-handson
(4/4) CyberAgent AI事業本部2024年度MLOps研修実践編: https://speakerdeck.com/hosimesi11/mlops-practice

Keita Hoshii

May 30, 2024
Tweet

More Decks by Keita Hoshii

Other Decks in Technology

Transcript

  1. ©2024 CyberAgent Inc. Distribution prohibited 自己紹介 干飯 啓太(ほしい けいた) 職種:

    ML Engineer/Data Scientist 所属: AI Shift 最近のタスク: • LLMを使った要約プロダクトの開発・立ち上げ • MLOps(GKE・Argo Workflows) 3 @hosimesi11_ @hosimesi
  2. ©2024 CyberAgent Inc. Distribution prohibited アジェンダ 5 1. MLOps 2.

    事前準備 3. 推論サーバの自動更新 4. ログの収集と継続的な学習 5. サニティチェック 6. カナリアリリース 7. メトリクスの可視化 8. まとめ
  3. ©2024 CyberAgent Inc. Distribution prohibited 今日使う技術 6 ECS ECR S3

    StepFunctions ALB AWS DynamoDB Route 53 Cloud Map Redshift Grafana Fluentd Prometheus その他 Lambda
  4. ©2024 CyberAgent Inc. Distribution prohibited 今日使う技術 7 Linter/Formatter/Test • tox

    ◦ 仮想環境上でのタスク自動化ツール • pytest ◦ テストフレームワーク • mypy ◦ 静的型チェック • ruff ◦ Rust製のリンター兼フォーマッター
  5. ©2024 CyberAgent Inc. Distribution prohibited 皆さんに作ってもらうもの 8 • 学習パイプラインの並列実行 •

    推論サーバの自動更新・バージョニング • デプロイ前のサニティチェック • カナリアリリース • 学習ログ基盤 • 機械学習のモニタリングシステム
  6. ©2024 CyberAgent Inc. Distribution prohibited MLOps研修前半で扱った領域 10 • コンテナ •

    実験管理 • CI/CD/CT • 学習パイプライン構築 • 推論サーバ構築 重要な部分をMLOps研修前半で扱いました
  7. ©2024 CyberAgent Inc. Distribution prohibited MLOpsはこれだけで十分? 11 • コンテナ •

    実験管理 • CI/CD/CT • 学習パイプライン構築 • 推論サーバ構築 全てすごく大事だが、実務では十分?
  8. ©2024 CyberAgent Inc. Distribution prohibited DevOpsとは 13 ChatGPTによると DevOpsは、ソフトウェア開発(Dev)と運用(Ops)を統合するための概念・実践・文化のことを 指します。これは、開発と運用の間のコミュニケーションとコラボレーションを強化し、製品のリ

    リースと新機能の更新をより迅速かつ頻繁に行うことを可能にすることを目指しています。 DevOpsの主な目標は、組織の効率性と生産性を向上させることです。これは、自動化、継続的イン テグレーション(CI)、継続的デリバリー(CD)、マイクロサービス、コンテナ化、クラウドコン ピューティングなどの技術を活用して達成されます。 DevOpsの採用により、開発と運用のチームは一緒に働くことで、問題を早期に特定し、解決策を迅 速に実装することが可能となります。これにより、製品の品質が向上し、顧客満足度が向上するとと もに、組織全体の生産性と効率性が向上します。
  9. ©2024 CyberAgent Inc. Distribution prohibited MLシステムがある意義 14 • DSPにおけるCTR・CVR予測モデル ◦

    枠の価値に対して最適な入札をすることで利益を最大化 • 広告クリエイティブの効果を推定 ◦ 広告効果の高いクリエイティブ制作を効率化 • ボイスボットの音声認識・自然言語理解 ◦ 精度とUXを向上させ複雑なタスクに応用 ビジネス価値を最大化すること そのために、機械学習をより迅速にスケールアップする必要がある
  10. ©2024 CyberAgent Inc. Distribution prohibited MLシステムはなぜ難しい? 15 • 継続的に学習しないと精度が劣化する ◦

    時間、データの変化でパフォーマンスが変動 ◦ MLモデルはコードによらず確率的なふるまい • モデルが複雑であり、多数のステークホルダーがいる ◦ データサイエンティスト、MLエンジニア、ソフトウェアエンジニア ◦ 役割が縦割りになり、システムもそれに合わせたアーキテクチャに なりやすい • データの管理が必要(学習データと本番データ)
  11. ©2024 CyberAgent Inc. Distribution prohibited MLOpsはDevOpsの派生に過ぎない 17 特徴量 エンジニアリング データ準備

    モデリング 評価 モニタリング 継続的学習 ログ収集 評価 ML開発 運用
  12. ©2024 CyberAgent Inc. Distribution prohibited 実践編で扱う内容 19 特徴量 エンジニアリング データ準備

    モデリング 評価 モニタリング 継続的学習 ログ収集 評価 運用
  13. ©2024 CyberAgent Inc. Distribution prohibited 再掲: MLOps基礎編 20 機械学習システムを運用するには ソフトウェアエンジニアリングのスキルが必須

    この講義はソフトウェアっぽい話も多いです 盛りだくさんになっているので、時間内に全部できなくても大丈夫です 頭の中にインデックスを貼ってもらえればOKです
  14. ©2024 CyberAgent Inc. Distribution prohibited Prerequisites 22 • Docker Desktop

    • docker-buildx(Docker Desktopに内包されていると思います) • python 3.11(本講義では3.11.7を使用しています) • poetry • awscli • direnv • terraform(本講義ではv1.4.5を使用しています) • make
  15. ©2024 CyberAgent Inc. Distribution prohibited 余談: 最近のPython事情 23 Rust製ツールが人気 uv:

    • https://astral.sh/blog/uv • package manager rye: • https://github.com/astral-sh/rye • package manager ruff: • https://github.com/astral-sh/ruff • linter & formatter
  16. ©2024 CyberAgent Inc. Distribution prohibited 余談: Python事情の変遷 24 • pytest

    • mypy • black • flake8 • isort • pytest • mypy • ruff Pythonプロジェクトの開始時に入れるべきライブラリ群がアップデート
  17. ©2024 CyberAgent Inc. Distribution prohibited 応用編とほぼ同構成を再作成 26 $ git clone

    https://github.com/hosimesi/aws-mlops-practice $ cd aws-mlops-practice ハンズオンレポジトリをクローン https://github.com/hosimesi/aws-mlops-practice
  18. ©2024 CyberAgent Inc. Distribution prohibited コマンドが通るか確認 27 $ aws sts

    get-caller-identity --profile mlops-practice { "UserId": “XXXXXXXXXXXXXXX:keita_hoshii", "Account": "0123456789", "Arn": "arn:aws:sts::0123456789:assumed-role/xxxxxxxx/keita_hoshii" } 結果が返ってこればOK
  19. ©2024 CyberAgent Inc. Distribution prohibited 環境変数の設定 28 $ cp .env.example

    .env $ $EDITOR .env AWS_REGION=ap-northeast-1 AWS_ACCOUNT_ID=0123456789 AWS_PROFILE=mlops-practice AWS_ALB_DNS= USER_NAME=xxxxx S3_BUCKET=${USER_NAME}-mlops-practice TF_VAR_aws_region=${AWS_REGION} TF_VAR_aws_profile=${AWS_PROFILE} TF_VAR_aws_account_id=${AWS_ACCOUNT_ID} TF_VAR_name=${USER_NAME} 自分の名前(AWSリソースのprefix) 変更しない 自分のAWSのアカウントID $EDITORは自身が使いたいものに任意で変えてください ex. vim, code
  20. ©2024 CyberAgent Inc. Distribution prohibited 環境変数の読み込み 29 $ direnv allow

    . $ echo $AWS_PROFILE direnv: loading ~hoge/fuga/.envrc direnv: export +AWS_ACCOUNT_ID +AWS_ALB_DNS +AWS_PROFILE +AWS_REGION +TF_VAR_aws_account_id +TF_VAR_aws_profile +TF_VAR_aws_region +TF_VAR_name +USER_NAME mlops-practice 設定されていたらOK うまくいかない場合、direnvの設定を再確認(次ページに詳細載っているので参照してください) https://github.com/direnv/direnv/blob/master/man/direnv.1.md
  21. ©2024 CyberAgent Inc. Distribution prohibited Tips: direnvの設定 30 $ $EDITOR

    ~/.bashrc Bashの場合 direnvの設定を記述する $ source ~/.bashrc $ eval "$(direnv hook bash)" $ $EDITOR ~/.zshrc Zshの場合 $ source ~/.zshrc $ eval "$(direnv hook zsh)"
  22. ©2024 CyberAgent Inc. Distribution prohibited State用S3バケットの作成 32 バケットタイプ 汎用 バケット名

    {名前}-mlops-practice-tfstate バケットのバージョニング 有効にする 以下のコマンドでも同様の操作が可能 $ aws s3 mb s3://{名前}-mlops-practice-tfstate --region ap-northeast-1 aws s3api put-bucket-versioning --bucket ${名前}-mlops-practice-tfstate --versioning-configuration Status=Enabled
  23. ©2024 CyberAgent Inc. Distribution prohibited Tips 33 required_version = "~>

    1.4" required_providers { aws = { source = "hashicorp/aws" version = "~> 4.60" } } backend "s3" { bucket = "{名前}-mlops-practice–tfstate" region = "ap-northeast-1" key = "terraform.tfstate" encrypt = true } } 実際のプロダクトではチーム全員が同一リソースを触るため、 StateファイルをS3に置きチームで共有 backendとしてs3を指定 ※ Stateファイル用のバケットが作成済みなことを確認 Terraform内でStateファイルの置き場を管理しようとすると、Stateファイル 自体の保存先が分からないため、置き場だけは手動作成する必要がある
  24. ©2024 CyberAgent Inc. Distribution prohibited Terraformファイルの編集 34 $ $EDITOR infra/main.tf

    variable "name" { description = "The name of the resources to create." } provider "aws" { region = var.aws_region profile = var.aws_profile } terraform { required_version = "~> 1.4" required_providers { aws = { source = "hashicorp/aws" version = "~> 4.60" } } backend "s3" { # FIXME: {your_name}-mlops-practice-tfstate bucket = "hoshii-mlops-practice-tfstate" region = "ap-northeast-1" key = "terraform.tfstate" encrypt = true } } 先ほど作成したbucket名 {名前}-mlops-practice-tfstate
  25. ©2024 CyberAgent Inc. Distribution prohibited AWSのリソース作成 35 $ terraform -chdir=infra

    init Terraformでリソース作成する まずは、S3とECRのみ作成 $ terraform -chdir=infra plan $ terraform -chdir=infra apply
  26. ©2024 CyberAgent Inc. Distribution prohibited Terraform plan 36 現在のリソースとの差分 適用前に意図しないChangeやDestroyが

    ないか確認 + request_payer = (known after apply) + tags_all = (known after apply) + website_domain = (known after apply) + website_endpoint = (known after apply) } # module.stepfunctions.aws_sfn_state_machine.mlops_practice will be created + resource "aws_sfn_state_machine" "mlops_practice" { + arn = (known after apply) + creation_date = (known after apply) + definition = (known after apply) + description = (known after apply) + id = (known after apply) + name = "hoshii-mlops-practice-ml-pipeline" + name_prefix = (known after apply) + publish = false + revision_id = (known after apply) + role_arn = (known after apply) + state_machine_version_arn = (known after apply) + status = (known after apply) + tags_all = (known after apply) + type = "STANDARD" + version_description = (known after apply) } Plan: 87 to add, 0 to change, 0 to destroy.
  27. ©2024 CyberAgent Inc. Distribution prohibited Stateファイルとは 38 Terraform経由で作成したインフラの現在の状態をバージョン管理するもの どのリソースが更新・削除されるべきかを判断するために使用される GitHubと同じでStateをローカルで管理するよりもリモートに保存することで、複数人が同じ

    Terraform設定を使用して作業する場合、全員が同じリソースのビューを持つことが可能 ※ Stateファイルには機密情報も含まれているため、Gitでの管理も非推奨 https://spacelift.io/blog/terraform-s3-backend
  28. ©2024 CyberAgent Inc. Distribution prohibited イメージを作成してECRにプッシュする 39 $ make build-ml

    build-predictor $ make push-ml push-predictor イメージが登録済みなことを確認 学習パイプライン用のイメージ(ml)と推論サーバ用のイメージ(predictor)を作成 https://ap-northeast-1.console.aws.amazon.com/ecr /private-registry/repositories?region=ap-northeast- 1
  29. ©2024 CyberAgent Inc. Distribution prohibited Notice: イメージ作成コマンド 40 MakeでWrapしたコマンドの中身 docker

    build --platform=linux/amd64 --build-arg NAME=$(USER_NAME) --target ml -t $(ECR_REPOSITORY)/$(DOCKER_ML_IMAGE):$(SHORT_SHA) -f $(DOCKERFILE_REPOSITORY)/$(DOCKERFILE_ML) . docker tag $(ECR_REPOSITORY)/$(DOCKER_ML_IMAGE):$(SHORT_SHA) $(ECR_REPOSITORY)/$(DOCKER_ML_IMAGE):$(DOCKER_TAG) build-ml push-ml aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin $(ECR_REPOSITORY) docker push $(ECR_REPOSITORY)/$(DOCKER_ML_IMAGE):$(SHORT_SHA) && docker push $(ECR_REPOSITORY)/$(DOCKER_ML_IMAGE):$(DOCKER_TAG) Dockerfileを元にビルド イメージへのタグ付け ECRログイン イメージのECRへのプッシュ
  30. ©2024 CyberAgent Inc. Distribution prohibited 学習データのアップロード 42 $ unzip data.zip

    ※ カレントディレクトリにdataフォルダができたことを確認 $ make upload 学習データの準備をする ローカルにdata.zipがあるのでそれを回答する https://ap-northeast-1.console.aws.amazon.com/s3/buckets?region=ap-n ortheast-1&bucketType=general&region=ap-northeast-1
  31. ©2024 CyberAgent Inc. Distribution prohibited 学習の実行(ローカル) 43 $ make run-ml

    学習の実行 学習済みモデルが上がっていることを確認 $ docker network create mlops-practice ネットワークの作成
  32. ©2024 CyberAgent Inc. Distribution prohibited 学習の実行(ECS Task) 44 Step FunctionsからMLモデルをキック

    https://ap-northeast-1.console.aws.amazon.com/states/home?region=ap-northeast-1#/statemachines
  33. ©2024 CyberAgent Inc. Distribution prohibited 推論サーバをローカルで動かす 47 ローカルで推論サーバを立ち上げる $ docker

    compose up --build リクエストを投げる https://github.com/hosimesi/aws-mlops-practice/blob/4dbed6a59641aeda70ef03a687187fc489885206/Makefile#L198C1-L208C1 $ make predict {"prediction":0.5002767055606515,"model":"sgd_classifier_ctr_model"} {"prediction":0.49770948950373656,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.5002766695014028,"model":"sgd_classifier_ctr_model"} {"prediction":0.49770948950373656,"model":"sgd_classifier_ctr_optuna_model"} 結果が返ってくればOK ローカルで推論サーバを立ち上げるための事前準備をする
  34. ©2024 CyberAgent Inc. Distribution prohibited ECS上の推論サーバにリクエストを送る 49 $ $EDITOR .env

    AWS_REGION=ap-northeast-1 AWS_ACCOUNT_ID=0123456789 AWS_PROFILE=mlops-practice AWS_ALB_DNS= USER_NAME=xxxxx S3_BUCKET=${USER_NAME}-mlops-practice TF_VAR_aws_region=${AWS_REGION} TF_VAR_aws_profile=${AWS_PROFILE} TF_VAR_aws_account_id=${AWS_ACCOUNT_ID} TF_VAR_name=${USER_NAME} https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#LoadBalancers: Makeコマンドでリクエストが送れるように、ALBのDNSを.envに 追記する
  35. ©2024 CyberAgent Inc. Distribution prohibited 推論サーバの動作確認(ECS) 50 環境変数の再読み込み $ direnv

    allow . リクエストを投げる $ make predict-ecs {"prediction":0.5002767055606515,"model":"sgd_classifier_ctr_model"} {"prediction":0.49770948950373656,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.5002766695014028,"model":"sgd_classifier_ctr_model"} {"prediction":0.49770948950373656,"model":"sgd_classifier_ctr_optuna_model"} 結果が返ってくればOK .PHONY: predict-ecs predict-ecs: while read line; do \ curl -X 'POST' '$(AWS_ALB_DNS)/predict' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d "$$line"; \ echo; \ sleep 1; \ done < ./data/sample.jsonl predict-ecsコマンドの中身
  36. ©2024 CyberAgent Inc. Distribution prohibited CASE2. 推論サーバの自動更新 54 新規の学習済みモデルが自動で推論サーバに載って欲しい 現在の構成では新規にモデルは学習・作成されるが、推論サーバに載っている

    モデルは変わらない • 新しいモデルは学習されるたびにS3に保存 • しかし、推論サーバは自動で新モデルをロードしないため、新モデルを利 用するには手動でサーバを更新する必要がある → 学習パイプラインの最後に推論サーバを自動で更新する
  37. ©2024 CyberAgent Inc. Distribution prohibited 作成するもの 55 • モデルを並列に同時学習 ◦

    SGD_CLASSIFIER_CTR_MODEL ◦ SGD_CLASSIFIER_CTR_OPTUNA_MODEL • 両モデルの学習終了後、推論サーバを新しいモデルを載せたものに更新 ◦ 各モデル名で保存されているモデルのうち、最新のオブジェクトをそれぞれ取得
  38. ©2024 CyberAgent Inc. Distribution prohibited { "StartAt": "ECS RunTask sgd_classifier_ctr_optuna_model",

    "States": { "ECS RunTask sgd_classifier_ctr_optuna_model": { "Type": "Task", "Resource": "arn:aws:states:::ecs:runTask.sync", "Parameters": { "LaunchType": "FARGATE", "Cluster": "{cluster_arn}", "TaskDefinition": "{task_definition_arn}", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "DISABLED", "SecurityGroups": [ "{security_group}" ], "Subnets": [ "{subnet}" ] } }, "Overrides": { "ContainerOverrides": [ { "Name": "ml-pipeline", "Environment": [ { "Name": "MODEL", "Value": "sgd_classifier_ctr_optuna_model" } ] } ] } }, "End": true } } } { "StartAt": "ECS RunTask sgd_classifier_ctr_model", "States": { "ECS RunTask sgd_classifier_ctr_model": { "Type": "Task", "Resource": "arn:aws:states:::ecs:runTask.sync", "Parameters": { "LaunchType": "FARGATE", "Cluster": "{cluster_arn}", "TaskDefinition": "{task_definition_arn}", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "DISABLED", "SecurityGroups": [ "{security_group}" ], "Subnets": [ "{subnet}" ] } }, "Overrides": { "ContainerOverrides": [ { "Name": "ml-pipeline", "Environment": [ { "Name": "MODEL", "Value": "sgd_classifier_ctr_model" } ] } ] } }, "End": true } } } Step Functionsの設定 62 ECS ClusterのARN ECS ML Pipelineのタスク定義のARN ※ revisionは省略 {名前}-mlops-practice-ml-pipeline-sgのID {名前}-mlops-practice-private-subnet-1aのID {モデル名} ECS RunTask {モデル名} sgd_classifier_ctr_modelの場合 sgd_classifier_ctr_optuna_modelの場合 https://github.com/CyberAgentAI/dsc-onboarding-mlops-2024/blob/main/4-mlops-practice/infra/modules/stepfunctions/definition/execute_ml_pipeline_parallel.json
  39. ©2024 CyberAgent Inc. Distribution prohibited APIパラメータ 70 { "LaunchType": "FARGATE",

    "Cluster": "${cluster_arn}", "TaskDefinition": "${update_server_task_definition_arn}”, "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "DISABLED", "SecurityGroups": [ "sg~" ], "Subnets": [ "subnet~" ] } } } ECS ClusterのARN ECS Update Serverのタスク定義のARN {名前}-mlops-practice-ml-pipeline-sgのID {名前}-mlops-practice-private-subnet-1aのID
  40. ©2024 CyberAgent Inc. Distribution prohibited ここまでで詰まった方 72 terraformを準備してるので、同リソースを作成しましょう ※ 時間ある時に復習してみてください

    resource "aws_sfn_state_machine" "mlops_practice_parallel" { name = "${var.name}-mlops-practice-ml-pipeline-parallel" role_arn = var.stepfunctions_role_arn definition = templatefile("./modules/stepfunctions/definition/execute_ml_pipeline_parallel.json", { cluster_arn = "${var.cluster_arn}", task_definition_arn = "${var.task_definition_arn}", update_server_task_definition_arn = "${var.update_server_task_definition_arn}", security_group = "${var.security_group}", subnet = "${var.subnet}" }) } 以下をコメントインし、make apply https://github.com/hosimesi/aws-mlops-practice/blob/main/infra/modules/stepfunctions/main.tf $ make apply
  41. ©2024 CyberAgent Inc. Distribution prohibited Notice: ECSの更新 73 def update_ecs_service(cluster:

    str, service: str) -> None: ecs = boto3.client("ecs") logger.info(f"Start updating ECS service: {service} in cluster: {cluster}") try: response = ecs.update_service(cluster=cluster, service=service, forceNewDeployment=True) logger.info(f"Started ECS service update: {response}") except Exception as e: logger.error(f"Failed to update ECS service: {service} in cluster: {cluster}, error: {str(e)}") boto3を使ってECSサービスを更新する https://github.com/hosimesi/aws-mlops-practice/blob/cf2d9f380bc5515fd485d0a2458f7c7d8769ff 11/ml/utils/aws_controller.py#L116C1-L123C104
  42. ©2024 CyberAgent Inc. Distribution prohibited Notice: 最新のモデルの取得 74 @asynccontextmanager async

    def lifespan(app: FastAPI) -> AsyncGenerator: app.state.predictor_models = get_predictor_models(revision=os.getenv("REVISION")) app.state.instance = get_ecs_instance_id() if os.getenv("SYSTEM_ENV") == "local": app.state.pushgateway_url = "pushgateway:9091" else: app.state.pushgateway_url = f"pushgateway.{INTERNAL_NAMESPACE}:9091" logger.info(f"Instance ID: {app.state.instance}") logger.info(f"Pushgateway URL: {app.state.pushgateway_url}") logger.info("start server") yield logger.info("shutdown server") サーバの開始と終了時に最新のモデルを S3から取得する関数を定義 https://github.com/hosimesi/aws-mlops-practice/blob/cf2d9f380bc5515fd485d0a2458f7c7d8769ff11/predictor/main.p y#L22C1-L36C1
  43. ©2024 CyberAgent Inc. Distribution prohibited MLシステムと通常システムの違い 78 MLシステムでは、コードのバージョン管理とモデルのバージョン管理の両方が重要 • コードのバージョン管理

    ◦ 特定のバージョンのコードでモデルを学習・推論した結果を再現するため → Git、Image Tag • モデルのバージョン管理 ◦ 特定のバージョンのモデルを利用した結果を再現するため ◦ 新しいモデルがパフォーマンスを落とした場合に古いモデルに切り戻すため • データのバージョン管理 ◦ 学習を再現するため ◦ 今回はデータは一意に定まるようになっている、学習前にS3に保存している • 学習時のパラメータ ◦ 学習を再現するため
  44. ©2024 CyberAgent Inc. Distribution prohibited 学習済みモデルのバージョン管理 79 モデルのRevision、名前、S3のパスを管理するためにDynamoDBを使 用 DynamoDB

    高パフォーマンスを実現する、サーバーレス NoSQL フルマネージドデータベース https://aws.amazon.com/jp/dynamodb/
  45. ©2024 CyberAgent Inc. Distribution prohibited 作成を確認 86 ※ 注意点 本来はECRやS3と同様にVPC

    Endpointの作成やDynamoDBへアクセスするためのRoleの 付与をする必要があるが、今回は運営で用意して適用済み ※ VPC Endpointとは VPC内のサービスとVPC外のサービスをプライベート接続で通信するためのコンポーネント
  46. ©2024 CyberAgent Inc. Distribution prohibited from ml.steps import ( extract_step,

    preprocess_step, train_step, create_model_revision_step, ) : : ml_model = train_step(preprocessed=preprocessed, ml_model=model_info.ml_model(), revision=revision, name=model_info.name) create_model_revision_step( revision=revision, name=model_info.name, s3_path=os.path.join(revision, model_info.name), ) Revisionの登録 87 学習パイプラインの最後に、Revisionを登録するstepを追加 追加 $ $EDITOR ml/main.py 追加
  47. ©2024 CyberAgent Inc. Distribution prohibited 学習パイプラインを実行する 88 学習パイプラインのイメージをアップデートする $ make

    build-ml push-ml https://ap-northeast-1.console.aws.amazon.com/states/home?region=ap-northeast-1#/statemachines 学習パイプラインを実行する
  48. ©2024 CyberAgent Inc. Distribution prohibited 推論サーバ側のモデル取得ロジック 90 モデルの取得ロジックは以下 • Revisionを指定するとDynamoDBから決まったRevisionのモデルを取得する

    • 指定しなければ最新のバージョンを取得する $ cat infra/modules/ecs/container_definitions/predictor.json from predictor.utils.setup import get_ecs_instance_id, get_predictor_models : @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator: app.state.predictor_models = get_predictor_models(revision=os.getenv("REVISION")) : コードを確認する
  49. ©2024 CyberAgent Inc. Distribution prohibited モデルのバージョンを固定してみる 92 $ $EDITOR infra/modules/ecs/container_definitions/predictor.json

    "mountPoints": [ { "readOnly": null, "containerPath": "/var/logs", "sourceVolume": "logs" } ], "essential": true, "environment": [ { "name": "REVISION", "value": "" } ], 戻したいDynamoDBのrevisionを指定 ex. { “name”: “REVISION”, “value”: “2024/05/15/10” } $ make apply デプロイする
  50. ©2024 CyberAgent Inc. Distribution prohibited 継続的に学習を回すには? 95 継続的に学習を回すには新たなデータが必要 例えば、広告配信サーバの場合 •

    入札した広告が表示されたかどうか • 表示された広告がクリックされたかどうか • クリックされた広告の商品が購入されたかどうか これらのデータを適切に集約し、新たな学習データとして使用できる状態 にして保存する必要がある
  51. ©2024 CyberAgent Inc. Distribution prohibited 学習データの準備の難しい点 96 実際は、学習データに使用するログがたまるタイミングは異なる • 実際にきたリクエスト

    ◦ 入札したタイミング • 入札した広告が表示されたかどうか ◦ 広告が表示されたタイミング • 表示された広告がクリックされたかどうか ◦ 広告がクリックされたタイミング • クリックされた広告の商品が購入されたかどうか ◦ 商品が購入されたタイミング
  52. ©2024 CyberAgent Inc. Distribution prohibited Fluentd 99 データの収集・変換・転送をするOSS リクエストをログとして収集して学習データに再利用 https://www.fluentd.org/

    Fluentd is an open source data collector for unified logging layer. Fluentd allows you to unify data collection and consumption for a better use and understanding of data.
  53. ©2024 CyberAgent Inc. Distribution prohibited 構成 100 Predictorと同じECS ServiceにサイドカーとしてFluentdコンテナを立ててPredictorコンテナの ログを収集

    サイドカーコンテナはメインのコンテナと並行して動作し、追加サービスを提供するもの ex. ロギング、モニタリング
  54. ©2024 CyberAgent Inc. Distribution prohibited 構成 101 1. FastAPIがファイルにログを書き出す 2.

    サイドカーに立てたFluentdがファイル を読み込んで、S3に転送
  55. ©2024 CyberAgent Inc. Distribution prohibited Predictorのログの変更 102 学習に使えるように、Predictorでログをファイルに吐くように変更 通常のログと識別できるように新たなLoggerを追加 $

    $EDITOR predictor/main.py from ml.utils.logger.logger_config import get_response_logger : logger = get_logger(__name__) : end_time = time.time() logger.info(f"Prediction time: {end_time - start_time}") : end_time = time.time() logger.info(f"Prediction time: {end_time - start_time}") import datetime as dt from ml.utils.logger.logger_config import get_logger, get_response_logger from predictor.schemas.response_log import BidResponseLog : logger = get_logger(__name__) response_logger = get_response_logger(f"{__name__}_response") : end_time = time.time() logger.info(f"Prediction time: {end_time - start_time}") bid_response_log = BidResponseLog( **bid_request.dict(), hostname=env, prediction=pred, logged_at=dt.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") ) response_logger.info(json.dumps(bid_response_log.dict()))
  56. ©2024 CyberAgent Inc. Distribution prohibited <source> @type tail format json

    path /var/logs/bid_response.log pos_file /var/logs/bid_response.log.pos tag log.bid_response </source> <match log.bid_response> @type s3 s3_bucket "#{ENV['USER_NAME']}-mlops-practice" <shared_credentials> profile_name mlops-practice </shared_credentials> path logs/local/ buffer_path /var/logs/fluent time_slice_format %Y%m%d%H time_slice_wait 10m utc buffer_chunk_limit 1m buffer_queue_limit 64 flush_interval 120s retry_wait 5s max_retry_wait 30 num_threads 8 # NOTICE: column mapping format tsv keys logged_at,id,hour,C1,banner_pos,site_id,site_domain,s ite_category,app_id,app_domain,app_category,device_id ,device_ip,device_model,device_type,device_conn_type, C14,C15,C16,C17,C18,C19,C20,C21,hostname,prediction store_as gzip </match> Fluent.confの追加 103 $ $EDITOR fluentd/local/fluent.conf /var/logsをpredictorコンテナとfluentdコンテナで共有 集めたlogの保存先のS3 Bucket zip形式で保存
  57. ©2024 CyberAgent Inc. Distribution prohibited compose.yamlの編集 104 compose.yamlにfluentdコンテナを追加 : fluentd:

    container_name: fluentd build: context: . dockerfile: ./docker/Dockerfile.fluentd volumes: - ./fluentd/local:/fluentd/etc - ./predictor/logs:/var/logs - $HOME/.aws:/root/.aws:ro env_file: - .env networks: - mlops-practice networks: mlops-practice: external: true Predictorコンテナのログを/var/logsでfluentdコンテナと共有 $ $EDITOR compose.yaml
  58. ©2024 CyberAgent Inc. Distribution prohibited envの読み込み&立ち上げ 105 $ docker compose

    up --build CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ************ aws-mlops-practice-fluentd "tini -- /bin/entryp…" * minutes ago Up * seconds 5140/tcp, 24224/tcp fluentd ************ aws-mlops-practice-predictor "gunicorn -b 0.0.0.0…" * hours ago Up * seconds 0.0.0.0:8080->8080/tcp predictor $ docker ps コンテナを確認
  59. ©2024 CyberAgent Inc. Distribution prohibited ローカルの推論サーバにリクエストを送る 106 $ make predict

    別のターミナルを開く $ tail -f predictor/logs/bid_response.log リクエストを送る ログがたくさん吐かれていたらOK ログがたくさん吐かれていたらOK(流し続けてください) {"logged_at": "2024-05-19 14:04:00", "id": "4.802063106841714e+18", "hour": "14102813", "C1": "1005", "banner_pos": "0", "site_id": "85f751fd", "site_domain": "c4e18dd6", "site_category": "50e219e0", "app_id": "54c5d545", "app_domain": "2347f47a", "app_category": "0f2161f8", "device_id": "4619756c", "device_ip": "34c0711c", "device_model": "a59d0d6d", "device_type": "1", "device_conn_type": "0", "C14": "23454", "C15": "320", "C16": "50", "C17": "2688", "C18": "1", "C19": "33", "C20": "-1", "C21": "212", "hostname": "predictor", "prediction": 0.5002767055606515} : : : 上記の形式でログがファイルに保存されます
  60. ©2024 CyberAgent Inc. Distribution prohibited ECRにイメージプッシュ 107 $ make push-predictor

    push-fluentd $ make build-predictor build-fluentd ECSで使えるようにECRにイメージをプッシュする
  61. ©2024 CyberAgent Inc. Distribution prohibited コンテナ定義を確認する 109 $ cat infra/modules/ecs/container_definitions/predictor.json

    [ { "name": "predictor", "image": "${predictor_ecr_uri}:latest", : "mountPoints": [ { "readOnly": null, "containerPath": "/var/logs", "sourceVolume": "logs" } ], "essential": true, : } Fluentdと共有するために ボリュームにマウント コンテナ内部の/var/logsをホストマシンのlogsという名前のボリュームにマウント $ cat infra/modules/ecs/main.tf resource "aws_ecs_task_definition" "predictor" { family = "${var.name}-predictor" network_mode = "awsvpc" cpu = 1024 memory = 2048 requires_compatibilities = ["FARGATE"] container_definitions = templatefile("./modules/ecs/container_definitions/predictor.json", { predictor_ecr_uri = "${var.predictor_ecr_uri}", fluentd_ecr_uri = "${var.fluentd_ecr_uri}", ecs_exporter_ecr_uri = "${var.ecs_exporter_ecr_uri}", name = "${var.name}" }) volume { name = "logs" } task_role_arn = var.ecs_task_role_arn execution_role_arn = var.ecs_task_execution_role_arn }
  62. ©2024 CyberAgent Inc. Distribution prohibited コンテナ定義の編集(Fluentdコンテナ) 110 $ $EDITOR infra/modules/ecs/container_definitions/predictor.json

    : { "name": "fluentd", "image": "${fluentd_ecr_uri}:latest", "mountPoints": [ { "readOnly": null, "containerPath": "/var/logs", "sourceVolume": "logs" } ], "environment": [ { "name": "USER_NAME", "value": "${name}" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-create-group": "true", "awslogs-group": "/ecs/${name}-mlops-practice-predictor", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } } ] Predictorコンテナの下にFluentdコンテナを追加 Fluentdコンテナをサイドカーに設定 Predictorコンテナからのログファイルを共有で きるようにホストマシンのlogsという名前の ボリュームにマウント
  63. ©2024 CyberAgent Inc. Distribution prohibited Docker ComposeとECS Taskの定義の違い 111 ローカルで複数コンテナを立ち上げるdocker

    composeと比較してみる version: "3" : fluentd: container_name: fluentd build: context: . dockerfile: ./docker/Dockerfile.fluentd volumes: - ./fluentd/local:/fluentd/etc - ./predictor/logs:/var/logs - $HOME/.aws:/root/.aws:ro env_file: - .env networks: - mlops-practice { "name": "fluentd", "image": "${fluentd_ecr_uri}:latest", "mountPoints": [ { "readOnly": null, "containerPath": "/var/logs", "sourceVolume": "logs" } ], "environment": [ { "name": "USER_NAME", "value": "{name}" } ], : } ] v v
  64. ©2024 CyberAgent Inc. Distribution prohibited /var/logsはどこからでてきた? 112 $ cat ml/utils/logger/logger_config.py

    def get_response_logger(name: str) -> Logger: logger = getLogger(name) fmt = "%(message)s" handler = FileHandler('/var/logs/bid_response.log') handler.setFormatter(coloredlogs.ColoredFormatter(fmt)) # Add the handler to the logger logger.addHandler(handler) logger.setLevel("INFO") return logger Predictorコンテナで/var/logsにログを出力するように設定している
  65. ©2024 CyberAgent Inc. Distribution prohibited デプロイ 113 $ make apply

    コンテナが2つできていることを確認 • predictor • fluentd
  66. ©2024 CyberAgent Inc. Distribution prohibited ECSにリクエストを送る 114 $ make predict-ecs

    ⚠ ローカルからリクエストを送りすぎるとIPバンされる可能性があるので注意してください {"prediction":0.4977068651182549,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.49770977922636167,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.49771618073871404,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.497712282765125,"model":"sgd_classifier_ctr_optuna_model"} {"prediction":0.5002767108656835,"model":"sgd_classifier_ctr_model"} {"prediction":0.5002767105991618,"model":"sgd_classifier_ctr_model"} {"prediction":0.4977042330180624,"model":"sgd_classifier_ctr_optuna_model"} : :
  67. ©2024 CyberAgent Inc. Distribution prohibited DWHへの自動連携 116 S3に入ったログを分析や学習がしやすいように自動でDWH(後述)にImport されるようにする Q.

    S3にあるデータをそのまま使用するのはダメ? A. 複数ファイルをJOINしたりしたい場合は、S3のままでは少し難しい Athenaなどもあるのでプロダクトにあったものを導入したい 今回はAWSのマネージドDWHであるRedshiftを使用する ※ Athena: SQLを使用してS3内のデータを直接分析することができるクエリサービス
  68. ©2024 CyberAgent Inc. Distribution prohibited Redshiftとは? 117 • AWSが提供するデータウェアハウスサービス ◦

    各社同じようなサービスを提供 ▪ BigQuery・Snowflake • 大規模データ読出に最適化 • 並列コンピューティング • 列指向ストレージ Redshift Serverless • 実際に使用した秒単位で課金 https://aws.amazon.com/jp/redshift/
  69. ©2024 CyberAgent Inc. Distribution prohibited DWHの比較 118 Redshift • AWSが提供しているDWH

    BigQuery • Google Cloudが提供しているDWH • サーバーレスアーキテクチャ Snowflake • Snowflakeが提供しているDWH • データアプリケーションの講義で使用 • コンピューティングとストレージを分離
  70. ©2024 CyberAgent Inc. Distribution prohibited Redshiftの準備 119 Redshift 無料トライアル or

    Serverless作成 https://ap-northeast-1.console.aws.amazon.com/redshiftv2/home?region=ap-northeast-1#serverless-dashboard
  71. ©2024 CyberAgent Inc. Distribution prohibited IAMロールの紐付け 121 IAMロール(すでに運営で作成済みです) {名前}-mlops-practice-redshift-role {名前}-mlops-practice-ecs-task-role

    {名前}-mlops-practice-lambda-role 許可しているアクション • redshiftに対する全てのアクション ◦ "redshift:*" • s3からデータをimportするためのアク ション ◦ "s3:GetObject" ◦ "s3:ListBucket"
  72. ©2024 CyberAgent Inc. Distribution prohibited Redshiftの準備 122 ベース容量 24 VPC

    {名前}-mlops-practiceのID セキュリティグループ {名前}-mlops-practice-redshift-sgのID サブネット {名前}-mlops-practice-public-subnet-1a {名前}-mlops-practice-public-subnet-1c {名前}-mlops-practice-public-subnet-1d 拡張されたVPCのルーティング ✅ VPC経由のアクセスになる
  73. ©2024 CyberAgent Inc. Distribution prohibited 作るテーブル 126 • imp log

    ◦ Predictorで先ほど吐き出したリクエストのログが溜まるテーブル ◦ 入札したものが全て表示された前提 • click log ◦ クリックしたかどうかのログが溜まるテーブル ◦ 事前に準備しているclick.tsv.gzをそのまま入れる
  74. ©2024 CyberAgent Inc. Distribution prohibited テーブル作成(imp_log) 127 DROP TABLE IF

    EXISTS imp_log; CREATE TABLE IF NOT EXISTS imp_log ( logged_at varchar(255), id varchar(255), hour varchar(255), C1 varchar(255), banner_pos varchar(255), site_id varchar(255), site_domain varchar(255), site_category varchar(255), app_id varchar(255), app_domain varchar(255), app_category varchar(255), device_id varchar(255), device_ip varchar(255), device_model varchar(255), device_type varchar(255), device_conn_type varchar(255), C14 varchar(255), C15 varchar(255), C16 varchar(255), C17 varchar(255), C18 varchar(255), C19 varchar(255), C20 varchar(255), C21 varchar(255), hostname varchar(255), prediction float8, primary key (id) ) DISTKEY (id) SORTKEY(logged_at); 左上の「Run」をクリック
  75. ©2024 CyberAgent Inc. Distribution prohibited テーブル作成(click_log) 128 DROP TABLE IF

    EXISTS click_log; CREATE TABLE IF NOT EXISTS click_log ( id varchar(255) not null, click int, primary key (id) ) DISTKEY (id); 左上の「Run」をクリック
  76. ©2024 CyberAgent Inc. Distribution prohibited データ挿入(click_log) 129 COPY click_log FROM

    's3://{名前}-mlops-practice/train_data/click.tsv.gz' GZIP IAM_ROLE 'arn:aws:iam::0123456789:role/{名前}-mlops-practice-redshift-role' FORMAT AS CSV DELIMITER '\t' IGNOREHEADER 1 REGION 'ap-northeast-1'; 本来はclick_logもclickが起こったタイミングでログ収集→保存する必要あり 今回は事前に用意したclick.tsv.gzを使用 S3のpath s3://{名前}-mlops-practice/train_data/click.tsv.gz IAMロール {名前}-mlops-practice-redshift-roleのARN ※ RedshiftではS3からのLoadもquery likeに書くことが可能
  77. ©2024 CyberAgent Inc. Distribution prohibited クエリを書いてみる 130 SELECT id, click

    FROM click_log LIMIT 10; ※ 今回はデータが少ないため使用していますが、LIMITはフルスキャンが走るので実務では他の方法でサンプリングする ※ *も使わない。カラムを指定する
  78. ©2024 CyberAgent Inc. Distribution prohibited 自動でS3からRedshiftにインポートする 131 PredictorからのログがS3に上がり、Redshiftに自動でインポートさせる S3へのputイベントをトリガーに、Lambdaでインポートを動かす ※

    Preview版ではあるが、S3から直接Redshiftにインポートが可能 GAになる日は近いかも? https://aws.amazon.com/jp/blogs/news/simplify-data-ingestion-from-amazon-s3-to-am azon-redshift-using-auto-copy-preview/
  79. ©2024 CyberAgent Inc. Distribution prohibited 権限作成 133 CREATE USER "IAMR:{名前}-mlops-practice-lambda-role"

    PASSWORD DISABLE; CREATE GROUP lambda; ALTER GROUP lambda ADD USER "IAMR:{名前}-mlops-practice-lambda-role"; GRANT USAGE, CREATE ON SCHEMA public TO GROUP lambda; GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA public TO GROUP lambda; LambdaのRoleに権限をつけていく Role IAMR:{名前}-mlops-practice-lambda-role SELECT usename, has_table_privilege(usename, 'imp_log', 'insert') AND has_table_privilege(usename, 'imp_log', 'select') FROM pg_user;
  80. ©2024 CyberAgent Inc. Distribution prohibited 権限作成 134 CREATE USER "IAMR:{名前}-mlops-practice-ecs-task-role"

    PASSWORD DISABLE; CREATE GROUP ecs; ALTER GROUP ecs ADD USER "IAMR:{名前}-mlops-practice-ecs-task-role"; GRANT USAGE, CREATE ON SCHEMA public TO GROUP ecs; GRANT SELECT ON ALL TABLES IN SCHEMA public TO GROUP ecs; ECS TaskのRoleに権限をつけていく Role IAMR:{名前}-mlops-practice-ecs-task-role SELECT usename, has_table_privilege(usename, 'imp_log', 'select') FROM pg_user;
  81. ©2024 CyberAgent Inc. Distribution prohibited NOTICE: 各コマンドの説明 135 CREATE USER

    "IAMR:{名前}-mlops-practice-ecs-task-role" PASSWORD DISABLE; ユーザーの作成 GRANT SELECT ON ALL TABLES IN SCHEMA public TO GROUP ecs; CREATE GROUP ecs; ALTER GROUP ecs ADD USER "IAMR:{名前}-mlops-practice-ecs-task-role"; GRANT USAGE, CREATE ON SCHEMA public TO GROUP ecs; グループの作成 グループにユーザーの追加 グループにUSAGEとCREATE権限を付与(USAGEは使用権限・CREATEはテーブルなどの作成権限) グループに全てのテーブルに対するSELECT権限を付与
  82. ©2024 CyberAgent Inc. Distribution prohibited Lambdaとは 136 $ make build-importer

    ECRにイメージをPushする $ make push-importer サーバレスのファンクション(FaaS) インフラを意識せずアプリケーションに注力 Lambdaを使ってS3とRedshiftでデータ連携する https://aws.amazon.com/jp/lambda/
  83. ©2024 CyberAgent Inc. Distribution prohibited NOTICE: importerの中身 137 def handler(event,

    context): redshift_workgroup = os.getenv("REDSHIFT_WORKGROUP") redshift_db = os.getenv("REDSHIFT_DATABASE") lambda_iam_role_arn = os.getenv("LAMBDA_IAM_ROLE_ARN") bucket = event["Records"][0]["s3"]["bucket"]["name"] file_path = event["Records"][0]["s3"]["object"]["key"] full_sql = sql.format(bucket=bucket, lambda_iam_role_arn=lambda_iam_role_arn, file_path=file_path) client = boto3.client("redshift-data") response = client.execute_statement( WorkgroupName=redshift_workgroup, Database=redshift_db, Sql=full_sql, ) print(response) ログが保存されるS3のパスをRedshiftに流すだけ
  84. ©2024 CyberAgent Inc. Distribution prohibited Data Importerの作成 138 Lambda →「関数の作成」をクリック

    https://ap-northeast-1.console.aws.amazon.com/lambda/home?region=ap-northeast-1#/functions
  85. ©2024 CyberAgent Inc. Distribution prohibited Data Importerの作成 140 メモリ 128MB

    エフェメラルストレージ 512MB タイムアウト 1分 実行ロール: {名前}-mlops-practice-lambda-role
  86. ©2024 CyberAgent Inc. Distribution prohibited ECSにリクエストを送る 143 $ make request-ecs

    ⚠ ローカルからリクエストを送りすぎるとIPバンされる可能性があるので注意してください ⚠ 送りすぎるとLambdaが起動し続けるので気をつけてください SELECT id, logged_at, hour FROM imp_log WHERE logged_at > LOCALTIMESTAMP - interval '60 minutes'; imp_logにレコードが入っていたらOK(入るまで数分かかります)
  87. ©2024 CyberAgent Inc. Distribution prohibited DWHのデータで学習 144 S3にあるtrain.tsvではなく、DWHに入っているデータを使って学習してみる $ $EDITOR

    ml/main.py from ml.steps import create_model_revision_step, extract_step, preprocess_step, train_step : : extracted = extract_step(name=model_info.name, revision=revision, train_args=model_info.train_args) from ml.steps import create_model_revision_step, extract_from_redshift_step, preprocess_step, train_step : : extracted = extract_from_redshift_step(name=model_info.name, revision=revision, train_args=model_info.train_args) イメージのプッシュ後、Step Functionsで実行 $ make build-ml push-ml extract_from_redshift_stepに差し替える https://ap-northeast-1.console.aws.amazon.com/states/home?region=ap-northeast-1#/statemachines
  88. ©2024 CyberAgent Inc. Distribution prohibited from ml.steps import create_model_revision_step, extract_from_redshift_step,

    preprocess_step, train_step, evaluate_step, sanity_check_step : eval_metrics, data_metrics = evaluate_step(preprocessed=preprocessed, ml_model=ml_model) : s3_path = sanity_check_step( revision=revision, name=model_info.name, preprocessed=preprocessed, evaluate_metrics=eval_metrics, ) : create_model_revision_step(revision=revision, s3_path=s3_path, name=model_info.name) サニティチェックの導入 148 $ $EDITOR ml/main.py 追加 追加 新旧モデルで精度の良い方のモデルのS3のパスが返ってくる 追加
  89. ©2024 CyberAgent Inc. Distribution prohibited def evaluate_step( preprocessed: dict[DatasetType, FeatureTarget],

    ml_model: BaseMLModel ) -> tuple[EvaluateMetrics, DataMetrics]: : logloss = log_loss(test_data.target, predictions) accuracy = accuracy_score(test_data.target, pred_bin) auc = roc_auc_score(test_data.target, predictions) : eval_metrics = EvaluateMetrics( logloss=logloss, accuracy=accuracy, auc=auc, precision=precision, recall=recall, calibration=calibration ) logger.info(f"Evaluation Metrics: {eval_metrics}") data_metrics = DataMetrics( train_data_ammount=preprocessed[DatasetType.TRAIN].feature.shape[0], test_data_ammount=test_data.feature.shape[0], valid_data_ammount=preprocessed[DatasetType.VALID].feature.shape[0], ) : return eval_metrics, data_metrics NOTICE: Evaluate Step 149 $ cat ml/steps/evaluate_step.py テストデータに対するモデルの精度評価 データに関するメトリクスも取得
  90. ©2024 CyberAgent Inc. Distribution prohibited def sanity_check_step(revision: str, name: str,

    test_data: str, evaluate_metrics: EvaluateMetrics) -> str: ; download_from_s3( s3_bucket=S3_BUCKET_NAME, s3_key=item["s3_keys"][name], file_path=os.path.join(LOCAL_BASE_ARTIFACT_DIR, f"{name}.pkl") ) : model = MODELS.retrieve(name=name) ; test_data = model.preprocessor().transform(test_data) predictions = model.ml_model().batch_predict(test_data) logloss = log_loss(test_data.target, predictions) # Compare the new model with the old model by logloss. if logloss < evaluate_metrics.logloss: logger.warning("New model is worse than the old model.") logger.warning(f"Old Model Metrics: {logloss}, New Model Metrics: {evaluate_metrics}") return item["s3_keys"][name] else: logger.info("New model is better than the old model.") logger.info(f"Old Model Metrics: {logloss}, New Model Metrics: {evaluate_metrics}") return s3_path NOTICE: Sanity Check Step 150 $ cat ml/steps/sanity_check_step.py 現在のモデル取得 現在のモデルを使ってテストデータを評価 新モデルと現在のモデルでloglossを比較し、 性能の良い方のmodel_pathを返す
  91. ©2024 CyberAgent Inc. Distribution prohibited 実際に起きた事例 154 こちらは実際に自分が起こしてしまった事例です これを機にカナリアリリースの機構を導入することになりました 1.

    機械学習の前処理部分のコードを少し変更 2. 推論サーバに全台適用(リリースタイミングのミス) 3. 学習済みモデルで使用していた前処理からずれが起き、予測値異常に 4. 損害: 💰💰💰
  92. ©2024 CyberAgent Inc. Distribution prohibited 推論サーバのカナリアイメージ準備 157 $ make build-predictor-canary

    $ make push-predictor-canary ※ ECRレポジトリはTerraformで作成済み イメージの中身自体はPredictorと同等
  93. ©2024 CyberAgent Inc. Distribution prohibited カナリア用タスク定義作成 158 追加 resource "aws_ecs_task_definition"

    "predictor_canary" { family = "${var.name}-predictor-canary" network_mode = "awsvpc" cpu = 1024 memory = 2048 requires_compatibilities = ["FARGATE"] container_definitions = templatefile("./modules/ecs/container_definitions/predictor_canary.json", { predictor_canary_ecr_uri = "${var.predictor_canary_ecr_uri}", fluentd_ecr_uri = "${var.fluentd_ecr_uri}", ecs_exporter_ecr_uri = "${var.ecs_exporter_ecr_uri}", name = "${var.name}" }) volume { name = "logs" } task_role_arn = var.ecs_task_role_arn execution_role_arn = var.ecs_task_execution_role_arn } $ $EDITOR infra/modules/ecs/main.tf
  94. ©2024 CyberAgent Inc. Distribution prohibited カナリア用ECSサービス作成(追加) 159 resource "aws_ecs_service" "predictor_canary"

    { name = "${var.name}-predictor-canary-service" cluster = aws_ecs_cluster.mlops_practice.name task_definition = aws_ecs_task_definition.predictor_canary.arn desired_count = 1 deployment_minimum_healthy_percent = 0 deployment_maximum_percent = 200 launch_type = "FARGATE" network_configuration { security_groups = [ "${var.predictor_security_group}" ] subnets = var.private_subnets } load_balancer { target_group_arn = var.predictor_canary_target_group_arn container_name = "predictor-canary" container_port = 8080 } } name {name}-predictor-canary-service task_definition カナリア用のtask定義のarn target_group_arn カナリア用のtarget groupのarn Predictorと同一のもの • cluster • security group • subnet
  95. ©2024 CyberAgent Inc. Distribution prohibited カナリア用オートスケーリング設定(追加) 160 resource "aws_appautoscaling_target" "predictor_canary"

    { max_capacity = 3 min_capacity = 1 resource_id = "service/${aws_ecs_cluster.mlops_practice.name}/${aws_ecs_service.predictor_canary.name}" scalable_dimension = "ecs:service:DesiredCount" service_namespace = "ecs" } resource_id: カナリア用のECS Serviceを指定 オートスケーリングの範囲は1台から3台
  96. ©2024 CyberAgent Inc. Distribution prohibited カナリア用オートスケーリングポリシー(追加) 161 resource "aws_appautoscaling_policy" "predictor_canary"

    { name = "${var.name}-predictor-canary-auto-scaling-policy" policy_type = "TargetTrackingScaling" resource_id = aws_appautoscaling_target.predictor_canary.resource_id scalable_dimension = aws_appautoscaling_target.predictor_canary.scalable_dimension service_namespace = aws_appautoscaling_target.predictor_canary.service_namespace target_tracking_scaling_policy_configuration { predefined_metric_specification { predefined_metric_type = "ECSServiceAverageCPUUtilization" } scale_in_cooldown = 60 scale_out_cooldown = 60 target_value = 70.0 } } resource_id 先ほど作成したカナリア用の resource_id
  97. ©2024 CyberAgent Inc. Distribution prohibited リスナールールの設定 162 resource "aws_lb_listener_rule" "mlops_practice_predictor"

    { listener_arn = aws_lb_listener.mlops_practice_predictor.arn action { type = "forward" target_group_arn = aws_lb_target_group.mlops_practice_predictor.arn } condition { path_pattern { values = ["/", "/predict"] } } } 通常のPredictor リクエストの90% カナリアのPredictor リクエストの10% resource "aws_lb_listener_rule" "mlops_practice_predictor" { listener_arn = aws_lb_listener.mlops_practice_predictor.arn action { type = "forward" forward { target_group { arn = aws_lb_target_group.mlops_practice_predictor.arn weight = 90 } target_group { arn = aws_lb_target_group.mlops_practice_predictor_canary.arn weight = 10 } } } condition { path_pattern { values = ["/", "/predict"] } } } 修正する $ $EDITOR infra/modules/alb/main.tf
  98. ©2024 CyberAgent Inc. Distribution prohibited デプロイ 163 $ make apply

    AWSのターゲットグループが複数になっているか確認 ECSサービスも更新 https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#LoadBalancers: カナリアをデプロイする
  99. ©2024 CyberAgent Inc. Distribution prohibited リクエストを送ってみる(再掲) 164 $ make predict-ecs

    AWS_REGION=ap-northeast-1 AWS_ACCOUNT_ID=0123456789 AWS_PROFILE=mlops-practice AWS_ALB_DNS= USER_NAME=xxxxx S3_BUCKET=${USER_NAME}-mlops-practice TF_VAR_aws_region=${AWS_REGION} TF_VAR_aws_profile=${AWS_PROFILE} TF_VAR_aws_account_id=${AWS_ACCOUNT_ID} TF_VAR_name=${USER_NAME} 埋めてない場合は埋める ⚠ ローカルからリクエストを送りすぎるとIPバンされる可能性があるので注意してください
  100. ©2024 CyberAgent Inc. Distribution prohibited リクエストの割り振り確認 165 9:1になるように設定したので、意図通りになっているか確認 Redshiftのエディターでクエリを投げる SELECT

    date_trunc('minute', CAST(logged_at AS timestamp) + interval '9 hours') as minute, COUNT(CASE WHEN hostname='predictor' THEN 1 ELSE NULL END) as predictor_count, COUNT(CASE WHEN hostname='predictor-canary' THEN 1 ELSE NULL END) as predictor_canary_count FROM imp_log WHERE logged_at > LOCALTIMESTAMP - interval '60 minutes' GROUP BY minute ORDER BY minute ASC;
  101. ©2024 CyberAgent Inc. Distribution prohibited まとめ 167 ヘルスチェック的な意味合いでのカナリアリリースを作成 1. 監視の重要性:

    新バージョンのパフォーマンスを監視し、問題がないことを確認。何を もって異常と判断するかの指標と、それらを監視する機構を準備する必要性 2. 管理コスト: インフラ管理コストは増える 小規模なプロダクトの場合、カナリア自体不要になることもある 開発リソースを含めたプロダクトの規模やビジネス上クリティカルに なるか判断し、導入を検討
  102. ©2024 CyberAgent Inc. Distribution prohibited Tips: カナリアからの移行手順 168 評価指標を定めてそれを元に適用比率を段階的に引き上げる 指標によってタイムスパンは異なるが以下一例

    • 1%適用 ◦ ヘルスチェック ◦ 数時間から数日 • 10%適用 ◦ メトリクスが悪化してないか ◦ 数日から1週間程度 • 50%適用 ◦ 評価指標(KPI)が悪化してないか ◦ 数週間程度 • 100%適用
  103. ©2024 CyberAgent Inc. Distribution prohibited なぜ監視するのか 170 • システムの正常性(予防とリカバリー) ◦

    MLの予測値やシステムのアウトプットそのものがビジネスにクリティカルなので システムの異常やエラーを早期に検知し、問題が大きくなる前に対応する • パフォーマンスチューニング ◦ 監視データを分析することで、システムのパフォーマンスを最適化する ◦ UXの向上や、システムコストの削減 ビジネスへの負の影響を最小化し、正の影響を最大化するため
  104. ©2024 CyberAgent Inc. Distribution prohibited ML特有の監視項目 171 • データ品質 ◦

    データの品質にモデルのパフォーマンスは大きく影響を受ける ◦ 欠損値・異常値などを監視 • モデルパフォーマンス ◦ モデルの精度(Logloss、Accuracy、AUCなど) ◦ 予測のレイテンシやスループット • ドリフト検出 ◦ データの分布が学習時と推論時で異なることでモデルのパフォーマンス に影響を及ぼす ◦ 特徴量の分布や予測の分布を監視 • Software Metrics
  105. ©2024 CyberAgent Inc. Distribution prohibited なにから監視するのか 173 MLOpsはDevOpsの特定領域を切り取っただけ → 通常のソフトウェアメトリクスから手をつける

    → その後MLの監視 大事なこと • 監視すべき対象をしっかり絞る • ビジネスインパクトの大きいものから。その後にリソースの監視 • チームの状況を考える
  106. ©2024 CyberAgent Inc. Distribution prohibited 使用技術 174 Grafana Grafana Labsが公開しているログ・データ可視化

    ツール AWSマネージドサービスもある Prometheus システム監視およびアラートツールで、メトリクス を時系列データとして収集して保存 AWSマネージドサービスもある
  107. ©2024 CyberAgent Inc. Distribution prohibited Grafanaの設定(compose.yaml) 177 grafana: container_name: grafana

    build: context: . dockerfile: ./docker/Dockerfile.grafana healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 30s timeout: 10s retries: 5 ports: - 3000:3000 volumes: - .local/grafana:/var/lib/grafana - ./grafana/local/datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml - ./grafana/local/dashboard.yaml:/etc/grafana/provisioning/dashboards/dashboard.yaml - ./grafana/dashboards:/var/lib/grafana/dashboards environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin networks: - mlops-practice 追加する $ $EDITOR compose.yaml
  108. ©2024 CyberAgent Inc. Distribution prohibited Prometheusの設定(compose.yaml) 178 prometheus: container_name: prometheus

    build: context: . dockerfile: ./docker/Dockerfile.prometheus volumes: - ./prometheus/local/prometheus.yaml:/etc/prometheus/prometheus.yaml - .local/prometheus:/prometheus command: - "--config.file=/etc/prometheus/prometheus.yaml" ports: - 9090:9090 networks: - mlops-practice 追加する $ $EDITOR compose.yaml
  109. ©2024 CyberAgent Inc. Distribution prohibited Pushgatewayの設定(compose.yaml) 179 pushgateway: container_name: pushgateway

    build: context: . dockerfile: ./docker/Dockerfile.pushgateway ports: - 9091:9091 networks: - mlops-practice 追加する Pushgatewayとは Prometheusのコンポーネントの一つで、短期的なジョブからのメトリクスを収集するためのツール PrometheusがPullに対して、PushgatewayにPushしPrometheusからはPushgatewayをpullする 推論サーバの予測値を取る際に使用 $ $EDITOR compose.yaml
  110. ©2024 CyberAgent Inc. Distribution prohibited compose.yaml(完成版) 180 version: "3" services:

    predictor: container_name: predictor build: context: . dockerfile: ./docker/Dockerfile target: local args: - NAME=hoshii restart: always tty: true ports: - 8080:8080 volumes: - ./ml:/app/ml - ./predictor:/app/predictor - ./predictor/logs:/var/logs - $HOME/.aws/credentials:/root/.aws/credentials:ro entrypoint: ["gunicorn", "-b", "0.0.0.0:8080", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", "--access-logfile", "-", "--error-logfile", "-", "--log-level", "info", "--timeout", "60", "predictor.main:app", ] env_file: - .env environment: - ENV=predictor - SYSTEM_ENV=local networks: - mlops-practice fluentd: container_name: fluentd build: context: . dockerfile: ./docker/Dockerfile.fluentd volumes: - ./fluentd/local:/fluentd/etc - ./predictor/logs:/var/logs - $HOME/.aws:/root/.aws:ro env_file: - .env networks: - mlops-practice prometheus: container_name: prometheus build: context: . dockerfile: ./docker/Dockerfile.prometheus volumes: - ./prometheus/local/prometheus.yaml:/etc/prometheus/prometheus.yaml - .local/prometheus:/prometheus command: - "--config.file=/etc/prometheus/prometheus.yaml" ports: - 9090:9090 networks: - mlops-practice grafana: container_name: grafana build: context: . dockerfile: ./docker/Dockerfile.grafana healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"] interval: 30s timeout: 10s retries: 5 ports: - 3000:3000 volumes: - .local/grafana:/var/lib/grafana - ./grafana/local/datasource.yaml:/etc/grafana/provisioning/datasources/datasource.y aml - ./grafana/local/dashboard.yaml:/etc/grafana/provisioning/dashboards/dashboard.ya ml - ./grafana/dashboards:/var/lib/grafana/dashboards environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin networks: - mlops-practice pushgateway: container_name: pushgateway build: context: . dockerfile: ./docker/Dockerfile.pushgateway ports: - 9091:9091 networks: - mlops-practice networks: mlops-practice: external: true https://github.com/hosimesi/aws-mlops-practice/blob/main/ compose.yaml
  111. ©2024 CyberAgent Inc. Distribution prohibited from prometheus_client import CollectorRegistry, Counter,

    Gauge, Histogram, push_to_gateway : : response_logger = get_response_logger(f"{__name__}_response") # Prometheus metrics registry = CollectorRegistry() response_time = Histogram( "response_time_seconds", "Response time in seconds", ["env", "instance", "model_name"], registry=registry ) request_count = Counter( "request_count", "Total Request Count", ["env", "instance", "model_name", "status_code"], registry=registry ) prediction_value = Gauge("prediction_value", "Predicted value", ["env", "instance", "model_name"], registry=registry) 推論サーバからメトリクスを送る 181 $ $EDITOR predictor/main.py 赤枠の部分を追加する スループット計測 リクエスト数 予測値
  112. ©2024 CyberAgent Inc. Distribution prohibited @app.exception_handler(HTTPException) async def http_exception_handler(request, exc):

    request_count.labels(env=env, instance=app.state.instance, model_name="", status_code="4xx").inc() return JSONResponse( status_code=exc.status_code, content={"message": str(exc.detail)}, ) @app.exception_handler(Exception) async def exception_handler(request, exc): request_count.labels(env=env, instance=app.state.instance, model_name="", status_code="5xx").inc() return JSONResponse( status_code=500, content={"message": str(exc)}, ) 推論サーバからメトリクスを送る 182 $ $EDITOR predictor/main.py 赤枠の部分を追加する 400系のリクエスト数 500系のリクエスト数
  113. ©2024 CyberAgent Inc. Distribution prohibited response_logger.info(json.dumps(bid_response_log.dict())) # Update metrics response_time.labels(env=env,

    instance=app.state.instance, model_name=model_name).observe(time.time() - start_time) prediction_value.labels(env=env, instance=app.state.instance, model_name=model_name).set(pred) request_count.labels(env=env, instance=app.state.instance, model_name=model_name, status_code="2xx").inc() except Exception as e: logger.error(f"Error occurred: {str(e)}") # Push metrics to Prometheus Pushgateway push_to_gateway(app.state.pushgateway_url, job="predict", registry=registry) return {"prediction": pred, "model": model_name} 推論サーバからメトリクスを送る 183 $ $EDITOR predictor/main.py 赤枠の部分を追加する メトリクスの送信
  114. ©2024 CyberAgent Inc. Distribution prohibited from ml.steps import ( create_model_revision_step,

    evaluate_step, extract_from_redshift_step, preprocess_step, sanity_check_step, send_metrics_step, train_step, ) eval_metrics, data_metrics = evaluate_step(preprocessed=preprocessed, ml_model=ml_model) send_metrics_step( current_time_jst=args.current_time_jst, eval_metrics=eval_metrics, data_metrics=data_metrics, model_name=model_info.name, extracted=extracted, ) s3_path = sanity_check_step( revision=revision, name=model_info.name, preprocessed=preprocessed, evaluate_metrics=eval_metrics, ) 学習パイプラインからメトリクスを送る 184 $ $EDITOR ml/main.py 赤枠の部分を追加する
  115. ©2024 CyberAgent Inc. Distribution prohibited Dockerコンテナの立ち上げ 185 $ docker compose

    up --build $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES xxxxxxxxxxx aws-mlops-practice-fluentd "tini -- /bin/entryp…" xx minutes ago Up xx minutes 5140/tcp, 24224/tcp fluentd xxxxxxxxxxx aws-mlops-practice-predictor "gunicorn -b 0.0.0.0…" xx hours ago Up xx minutes 0.0.0.0:8080->8080/tcp predictor xxxxxxxxxxx aws-mlops-practice-pushgateway "/bin/pushgateway" xx days ago Up xx minutes 0.0.0.0:9091->9091/tcp pushgateway xxxxxxxxxxx aws-mlops-practice-grafana "/run.sh" xx days ago Up xx minutes (healthy) 0.0.0.0:3000->3000/tcp grafana xxxxxxxxxxx aws-mlops-practice-prometheus "/bin/prometheus --c…" xx days ago Up xx minutes 0.0.0.0:9090->9090/tcp prometheus コンテナが5つ立っていたらOK
  116. ©2024 CyberAgent Inc. Distribution prohibited データの送信 186 $ make build-ml

    push-ml 推論サーバのイメージビルド MLパイプラインのイメージビルド&プッシュ $ make build-predictor build-predictor-canary $ make run-ml データを貯めるため、学習を何回か回す 推論サーバにリクエストを送る $ make predict
  117. ©2024 CyberAgent Inc. Distribution prohibited Tips: データドリフトの検知 200 Amazon SageMaker

    Model Monitorなどで行うことが可能 • データの記述統計量など • データ品質 • モデル品質 • データキャプチャ 実際導入する際はオーバーエンジニアリングになってないか・監視することで何を達成したいかに 即して考える もしかしたらGrafanaだけで事足りるかもしれない • 学習データに含まれるclickの数が変わったタイミングでアラートを上げる • trainデータの数が変わったタイミングでアラートを上げる
  118. ©2024 CyberAgent Inc. Distribution prohibited サービスディスカバリとは 202 ネットワーク上のサービスを自動的に検出し、 その位置や設定を特定するプロセス ex

    オートスケールしたPrivate IPを持つ インスタンスをDNSのような仕組みを用いて 自動で登録できたりする AWS Cloud Map
  119. ©2024 CyberAgent Inc. Distribution prohibited ServiceのArnを取得 210 $ aws servicediscovery

    get-service --id {サービスID} --region ap-northeast-1 全て得られたArnをコピーしておく • prometheus • pushgateway • predictor • predictor-canary
  120. ©2024 CyberAgent Inc. Distribution prohibited Terraformの修正(pushgateway) 211 resource "aws_ecs_service" "pushgateway"

    { name = "${var.name}-pushgateway-service" cluster = aws_ecs_cluster.mlops_practice_dashboard.name task_definition = aws_ecs_task_definition.pushgateway.arn desired_count = 1 deployment_minimum_healthy_percent = 0 deployment_maximum_percent = 200 launch_type = "FARGATE" network_configuration { security_groups = [ "${var.pushgateway_security_group}" ] subnets = var.private_subnets } service_registries { registry_arn = "your_registry_arn" container_name = "pushgateway" } } 追加 得られたArnに書き換え $ $EDITOR infra/modules/ecs/main.tf
  121. ©2024 CyberAgent Inc. Distribution prohibited Terraformの修正(prometheus) 212 resource "aws_ecs_service" "prometheus"

    { name = "${var.name}-prometheus-service" cluster = aws_ecs_cluster.mlops_practice_dashboard.name task_definition = aws_ecs_task_definition.prometheus.arn desired_count = 1 deployment_minimum_healthy_percent = 0 deployment_maximum_percent = 200 launch_type = "FARGATE" network_configuration { security_groups = [ "${var.prometheus_security_group}" ] subnets = var.private_subnets } service_registries { registry_arn = "your_registry_arn" container_name = "prometheus" } } 追加 得られたArnに書き換え $ $EDITOR infra/modules/ecs/main.tf
  122. ©2024 CyberAgent Inc. Distribution prohibited Terraformの修正(predictor) 213 resource "aws_ecs_service" "predictor"

    { name = "${var.name}-predictor-service" cluster = aws_ecs_cluster.mlops_practice.name task_definition = aws_ecs_task_definition.predictor.arn desired_count = 1 deployment_minimum_healthy_percent = 0 deployment_maximum_percent = 200 launch_type = "FARGATE" network_configuration { security_groups = [var.predictor_security_group] subnets = var.private_subnets } load_balancer { target_group_arn = var.predictor_target_group_arn container_name = "predictor" container_port = 8080 } service_registries { registry_arn = "your_registry_arn" container_name = "predictor" } } 追加 得られたArnに書き換え $ $EDITOR infra/modules/ecs/main.tf
  123. ©2024 CyberAgent Inc. Distribution prohibited Terraformの修正(predictor-canary) 214 resource "aws_ecs_service" "predictor_canary"

    { name = "${var.name}-predictor-canary-service" cluster = aws_ecs_cluster.mlops_practice.name task_definition = aws_ecs_task_definition.predictor_canary.arn desired_count = 1 deployment_minimum_healthy_percent = 0 deployment_maximum_percent = 200 launch_type = "FARGATE" network_configuration { security_groups = [var.predictor_security_group] subnets = var.private_subnets } load_balancer { target_group_arn = var.predictor_canary_target_group_arn container_name = "predictor-canary" container_port = 8080 } service_registries { registry_arn = "your_registry_arn" container_name = "predictor-canary" } } 追加 得られたArnに書き換え $ $EDITOR infra/modules/ecs/main.tf
  124. ©2024 CyberAgent Inc. Distribution prohibited Prometheus.yamlの修正 215 global: scrape_interval: 15s

    evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' honor_labels: true static_configs: - targets: ['localhost:9090'] - job_name: 'pushgateway' honor_labels: true static_configs: - targets: ['pushgateway.{名前}-mlops-practice.internal:9091'] - job_name: 'predictor_ecs_exporter' honor_labels: true static_configs: - targets: ['predictor.{名前}-mlops-practice.internal:9543'] - job_name: 'predictor_canary_ecs_exporter' honor_labels: true static_configs: - targets: ['predictor-canary.{名前}-mlops-practice.internal:9543'] 先ほど作ったservice名に変更(pushgateway) $ $EDITOR prometheus/ecs/prometheus.yaml 先ほど作ったservice名に変更(predictor) 先ほど作ったservice名に変更(predictor-canary) {サービス名}.{名前}-mlops-practice.internal
  125. ©2024 CyberAgent Inc. Distribution prohibited datasource.yamlの修正 216 apiVersion: 1 datasources:

    - name: Prometheus type: prometheus access: proxy # FIXME: Change the URL to the internal DNS name of the Prometheus server url: http://prometheus.{名前}-mlops-practice.internal:9090 isDefault: true 先ほど作ったservice名に変更 $ $EDITOR grafana/ecs/datasource.yaml prometheus.{名前}-mlops-practice.internal:9090
  126. ©2024 CyberAgent Inc. Distribution prohibited イメージのプッシュ 217 $ make build-grafana

    build-prometheus build-pushgateway イメージのビルド&プッシュ $ make push-grafana push-prometheus push-pushgateway push-predictor push-predictor-canary
  127. ©2024 CyberAgent Inc. Distribution prohibited SoftWareメトリクスの取得 218 ecs exporterをサイドカーコンテナとして立てる ecs

    exporterがECSのメトリクスをPrometheusに送信する ex. cpu使用率、メモリ使用率
  128. ©2024 CyberAgent Inc. Distribution prohibited ECS Exporterコンテナの追加 220 $ $EDITOR

    infra/modules/ecs/container_definitions/predictor.json { "name": "ecs_exporter", "image": "${ecs_exporter_ecr_uri}:latest", "portMappings": [ { "name": "ecs-exporter-9779-tcp", "containerPort": 9779, "hostPort": 9779, "protocol": "tcp", "appProtocol": "http" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-create-group": "true", "awslogs-group": "/ecs/${name}-mlops-practice-ecs-exporter", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } } $ $EDITOR infra/modules/ecs/container_definitions/predictor-canary.json { "name": "ecs_exporter", "image": "${ecs_exporter_ecr_uri}:latest", "portMappings": [ { "name": "ecs-exporter-9779-tcp", "containerPort": 9779, "hostPort": 9779, "protocol": "tcp", "appProtocol": "http" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-create-group": "true", "awslogs-group": "/ecs/${name}-mlops-practice-ecs-exporter", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } }
  129. ©2024 CyberAgent Inc. Distribution prohibited デプロイ 221 $ make apply

    Dashboard用のALBのドメインをクリック https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#LoadBalancers Grafanaの画面が見れればOK デプロイする
  130. ©2024 CyberAgent Inc. Distribution prohibited 注意点 227 • 時間の都合上、ML側のメトリクスの可視化からしたが通常のソフトウェアの メトリクスから取る

    • 幅広く可視化したがチーム・事業によって見るべきメトリクスは変わるので、 取捨選択する ◦ 誰にもみられないダッシュボードにしない • 監視対象のビジネス的な閾値を設定することで、アラートを上げることも可能 ◦ このときも何でもアラートを上げるのではなく取捨選択する 他にもいろんな機能があるので色々触ってみてください Tableauなどもそうですが、DSは可視化能力も大事です
  131. ©2024 CyberAgent Inc. Distribution prohibited 機械学習システムの難しさ 229 Team skills: In

    an ML project, the team usually includes data scientists or ML researchers, who focus on exploratory data analysis, model development, and experimentation. These members might not be experienced software engineers who can build production-class services. https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning データサイエンティストのみで機械学習サービスを構築・運用するのは大変です ソフトウェアエンジニア・フロントエンド・データサイエンティスト・リサーチャーに かかわらず、機械学習システムを一緒に作る上でハマりどころなどを共有し、 互いにリスペクトして協力しながら開発・事業を作っていきましょう
  132. ©2024 CyberAgent Inc. Distribution prohibited 終わりに 230 かなりいろいろ紹介しましたが、今日の講義はプロダクトによってはオーバースペックです ※ 一人でできる必要もありません

    運用していく上で色々できることはありますが、 チーム・事業にとってクリティカルなものだけに絞りましょう 大事なこと • 何を達成したいかを考える • 誰にも見られないリッチなダッシュボードより、簡素でもビジネスにとって重要なもの をまとめたダッシュボードの方が良い • DevOpsからスモールに始める • サードパーティのツールをうまく組み合わせる
  133. ©2024 CyberAgent Inc. Distribution prohibited 手動で削除するリソース 232 • Cloud Map

    • Route 53 • ECR • S3(tfstate以外の中身) • Dynamo DB • Lambda • Redshift $ make destroy Destroy