SageMaker Pipelinesで始めるMLOps

# はじめに
本記事は、AI/ML on AWS Advent Calendar 2022の15日目の記事です。

私は現在都内のベンチャー企業にてデータエンジニア(データサイエンティスト)としてインターンをしています。
業務内容としては、データの前処理からエンドポイントの作成まで幅広く行っております。
普段業務する中で、MLOpsの重要性をひしひしと感じたので、記事にしたいと思いました。
そこで今回は、MLOpsを実現するAWSのSageMaker PipelinseというCI/CDサービスについて説明していきたいと思います！

データエンジニア・データサイエンティストを目指している学生の方やMLOpsに興味のある方にとって有用な記事となれば幸いです。

# 目次
[1.MLOpsの重要性](#1-MLOpsの重要性)
[2.SageMakerPipelines](#2-SageMakerPipelines)
[3.手順の説明](#3-手順の説明)
[4.最後に](#4-最後に)

# 1. MLOpsの重要性
以下は、私が機械学習プロジェクトを進めていく上で感じた課題になります。
- 前処理・トレーニング・デプロイ作業が独立してしまい、運用サイクルがうまく回せない
- モデルのパラメータ管理が煩雑で再現性が担保できない
- プロジェクト毎に一から作業をスタートするので作業効率が悪い

全てに共通しているのは、「とにかく効率が悪い」ということ。
MLOpsとはこれらを解決するための思想、すなわち**機械学習モデルを開発・運用する際に、めんどくさいところは自動化しよう**という思想になります。

このMLOpsを実現するためのサービスの一つが、AWSが提供しているSageMaker Pipelinesです。

# 2. SageMaker Pipelines
### SageMaker Pipelinsとは
[SageMaker Pipelines](https://aws.amazon.com/jp/sagemaker/pipelines/)とは、データの取得から開発したモデルの推論エンドポイントの作成といった、機械学習に必要なワークフローを全て自動化してくれるサービスになります。
下図のようなMLパイプラインを簡単に構築でき、AWS側でテンプレートも用意されているのでさまざまなユースケースに対応できます。
![h2自動生成 - SageMaker Pipelines.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/e670ea50-69cb-7893-606b-8f093ec35997.png)
Pipelinesは[ SageMaker Studio ](https://aws.amazon.com/jp/sagemaker/studio/)上で利用でき、[ Amazon SageMaker Python SDK ](https://sagemaker.readthedocs.io/en/stable/workflows/pipelines/sagemaker.workflow.pipelines.html#)を使用して定義することにより、下図のようにワークフローを可視化することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/87e49146-8f90-bba5-752e-bc4a04f43021.png)

### 自動化の流れ
以下はデータの前処理からモデルのデプロイまで自動化するテンプレートのフローになります。
（※他にもさまざまなテンプレートがありますが、ここでは説明を割愛します。）
1. SageMaker Studio上でコードを変更し、CodeCommitへpush
2. EventBridgeがpushを検知し、ModelBuilePipelineを実行
3. モデルの学習が終了後、デプロイパイプラインの実行を手動承認する。
4. ステージング環境へのデプロイが完了後、本番環境へのデプロイを手動承認する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/382731f3-8056-79f5-70f1-ca6e6dc75c8e.png" width="80%">

次章では、この自動化の手順を説明していきます。

# 3. 手順の説明
今回はSageMakerStudioのセットアップは完了している前提で話を進めていきます。
完了していない方は[こちら](https://qiita.com/s_Pure/items/4312c0b27296d6dce433)の記事を参考にしてセットアップを完了させて下さい。

今回は、AWS側で用意されているテンプレートを使用して、デプロイまでの手順を説明していきます。

### プロジェクトの作成
1. SageMaker resorcesアイコンよりProjectsタブを選択し、Create projectボタンを押しましょう。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/2f4f0764-8302-2833-ffd3-0e6c4cd61064.png)
2. project templateから「MLOps template for model building, training, and deployment」を選択し、Select project templateボタンを押しましょう。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/a8f87f8e-9ac2-067a-57d9-440f3eead4e7.png)
3. Projectの名前を入力し、Create projectボタンを押すとプロジェクトが作成される。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/6ce56173-bd72-9c78-58bf-c51efde0798e.png)


### リポジトリのクローン
新しく作成されたprojectを選択し、Repositriesを選択しましょう。
モデルビルド用・モデルデプロイ用の2つのリポジトリが存在しているので、どちらもクローンします。
**※留意事項**
本来ならLocal pathにclone repositrieというボタンが映し出されます。
クローンが完了すると下図のような表示になり、ローカルパスが表示されます。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/e5736a90-2d6a-0f2b-6ac3-d0bee1cccc9d.png)
modelbuild側のディレクトリ構成は以下のようになっています。
pipeline-name部分はデフォルトでabalonが設定されているので、任意のプロジェクト名に変更しておきましょう。
　今回は説明を割愛しますが、evaluate.py・pipelin.py・preprocess.pyを書き換えることで自由に処理内容を変更できます。例えば、デフォルトではXGBoostを使用していますが、RandamForrestを使用したり、ハイパーパラメータの設定を変えることも可能です。これについてはまた後日記事にしようと思います。
他のファイルは特に変更は必要ありません。
```
~modelbuild
┣codebuild-buildspec.yml
┣CONTRIBUTING.md
┣pipelines
┃   ┣<pipeline-name>
┃   ┃     ┣__init__.py
┃   ┃     ┣evaluate.py
┃   ┃     ┣pipeline.py
┃   ┃     ┗preprocess.py
┃   ┣__init__.py
┃   ┣get_pipeline_definition.py
┃   ┣run_pipeline.py
┃   ┣_utils.py
┃   ┗__version__.py
┣README.md
┣sagemaker-pipelines-project.ipynb
┣setup.cfg
┣setup.py
┣tests
┃   ┗test_pipelines.py
┗tox.ini

```
modeldeploy側のファイルは変更しなくても動作するので、説明は割愛します。

### ymlファイルの修正
pipeline-nameの部分はデフォルトでabalonが設定されているので、先ほど設定したプロジェクト名に変更しておきましょう。
```yml:codebuild-buildspec.yml
~  
  build:
    commands:
      - export PYTHONUNBUFFERED=TRUE
      - export SAGEMAKER_PROJECT_NAME_ID="${SAGEMAKER_PROJECT_NAME}-${SAGEMAKER_PROJECT_ID}"
      - |
        # 変更後
        run-pipeline --module-name pipelines.<pipeline-name>.pipeline \     
        # 変更前
        # run-pipeline --module-name pipelines.abalon.pipeline \
~
```

### CodeCommitへPush
先ほどymlファイルを変更したので、その変更をコミットし、CodeCommitへPushしましょう。
Push後に自動でCodeBuildが実行され、モデルレジストリに学習後のモデルが登録されます。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/5e31fa36-3967-a656-675c-884ee63dd945.png)

### モデルを承認
1. CodePipelineが正常に実行されたら、Model registryにモデルグループが作成されます。右側に登録されたモデルのバージョンが表示されるので、承認したいモデルのバージョンをクリックします。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/3c2fa689-8055-cd84-4d70-5d24a6b97c29.png)

2. 右上のUpdate statusより、ステータスをApprovedに変更しましょう。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/97018e8c-a2fc-ec25-4782-c81291a8ed31.png)

### モデルのデプロイ
1. ステータスを変更すると、自動でModelDeploy側のCodePipelinsが実行されます。正常に実行されるとモデルがステージング環境にデプロイされるので、下図の様にEndpointsタブからモデルの出力を確認します。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/ca3bac99-47aa-dc03-d6eb-a1430844f57e.png)

2. 本番環境へデプロイしてもよさそうなら、CodePipelineにて承認を行いましょう。SageMaker Endpointを確認してエンドポイントが作成されていたら成功です。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/4315aa4a-2c9a-29f5-3f1e-af55d3d10d31.png)
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1441421/0734855c-bd1e-0e2f-1cd0-19e161bab9c4.png)

これでデフォルト設定のままではありますが、無事モデルをデプロイすることができました！
特に難しい設定をせずに簡単にMLパイプラインを構築できるので非常に便利ですね！

# 4. 最後に
いかがだったでしょうか？皆さんもこれでMLOpsの重要性やSageMaker Pipelinesの始め方が理解できたかと思います。
あとは皆さんの方でパイプラインの中身(pipeline.py)を変更して、ユースケースに合わせたMLパイプラインを構築していきましょう！
具体的なコードの説明は後日記事にしようと思いますので、しばらくお待ちください！