A collection of notes and resources
既存のアーキテクチャと要件に基づいてインフラストラクチャを作成し、スクリプト化する
from aws_cdk import Stack
from aws_cdk import aws_sagemaker as sagemaker
class MLStack(Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
# SageMaker エンドポイント定義
endpoint = sagemaker.CfnEndpoint(
self, "MLEndpoint",
endpoint_config_name="my-endpoint-config"
)
import boto3
client = boto3.client('application-autoscaling')
# スケーラブルターゲットの登録
response = client.register_scalable_target(
ServiceNamespace='sagemaker',
ResourceId=f'endpoint/{endpoint_name}/variant/{variant_name}',
ScalableDimension='sagemaker:variant:DesiredInstanceCount',
MinCapacity=1,
MaxCapacity=10
)
# ターゲット追跡スケーリングポリシー
client.put_scaling_policy(
PolicyName='target-tracking-policy',
ServiceNamespace='sagemaker',
ResourceId=f'endpoint/{endpoint_name}/variant/{variant_name}',
ScalableDimension='sagemaker:variant:DesiredInstanceCount',
PolicyType='TargetTrackingScaling',
TargetTrackingScalingPolicyConfiguration={
'TargetValue': 750.0, # 目標値
'PredefinedMetricSpecification': {
'PredefinedMetricType': 'SageMakerVariantInvocationsPerInstance'
},
'ScaleInCooldown': 300,
'ScaleOutCooldown': 60
}
)
from sagemaker.estimator import Estimator
# トレーニングでスポットインスタンス使用
estimator = Estimator(
image_uri=container,
role=role,
instance_count=2,
instance_type='ml.p3.2xlarge',
use_spot_instances=True,
max_run=3600,
max_wait=7200 # スポット中断時の待機時間
)
import json
import boto3
sagemaker_runtime = boto3.client('sagemaker-runtime')
def lambda_handler(event, context):
# 前処理
payload = preprocess(event['body'])
# SageMaker 推論
response = sagemaker_runtime.invoke_endpoint(
EndpointName='my-endpoint',
ContentType='application/json',
Body=json.dumps(payload)
)
# 後処理
result = postprocess(response['Body'].read())
return {
'statusCode': 200,
'body': json.dumps(result)
}
# Stack 1: ネットワーク
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Outputs:
VPCId:
Value: !Ref VPC
Export:
Name: MLVPCId
# Stack 2: SageMaker
Resources:
SageMakerEndpoint:
Type: AWS::SageMaker::Endpoint
Properties:
EndpointConfigName: !Ref EndpointConfig
Tags:
- Key: VPC
Value: !ImportValue MLVPCId
from aws_cdk import Stack, CfnOutput
from aws_cdk import aws_ec2 as ec2
from aws_cdk import aws_sagemaker as sagemaker
class NetworkStack(Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
self.vpc = ec2.Vpc(self, "MLVPC")
# 他のスタックで使用できるように出力
CfnOutput(self, "VPCId", value=self.vpc.vpc_id)
class MLStack(Stack):
def __init__(self, scope, id, vpc, **kwargs):
super().__init__(scope, id, **kwargs)
# ネットワークスタックのVPCを使用
endpoint = sagemaker.CfnEndpoint(
self, "Endpoint",
endpoint_config_name="config"
)
FROM python:3.9-slim
# 依存関係のインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードのコピー
COPY app/ /opt/ml/code/
WORKDIR /opt/ml/code
# SageMaker の推論スクリプト
ENV SAGEMAKER_PROGRAM inference.py
# エントリーポイント
ENTRYPOINT ["python", "inference.py"]
# ECR リポジトリの作成
aws ecr create-repository --repository-name ml-inference
# Docker イメージのビルド
docker build -t ml-inference .
# ECR にログイン
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.com
# タグ付け
docker tag ml-inference:latest \
123456789012.dkr.ecr.us-east-1.amazonaws.com/ml-inference:latest
# プッシュ
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/ml-inference:latest
from sagemaker.model import Model
model = Model(
image_uri='123456789012.dkr.ecr.us-east-1.amazonaws.com/ml-inference:latest',
model_data=f's3://{bucket}/model.tar.gz',
role=role
)
predictor = model.deploy(
initial_instance_count=1,
instance_type='ml.m5.xlarge'
)
from sagemaker.tensorflow import TensorFlowModel
model = TensorFlowModel(
model_data=f's3://{bucket}/model.tar.gz',
role=role,
framework_version='2.12'
)
# VPC 設定でデプロイ
predictor = model.deploy(
initial_instance_count=1,
instance_type='ml.m5.xlarge',
endpoint_name='private-endpoint',
vpc_config={
'SecurityGroupIds': ['sg-xxxxx'],
'Subnets': ['subnet-yyyyy', 'subnet-zzzzz']
}
)
import boto3
ec2 = boto3.client('ec2')
# SageMaker Runtime VPC Endpoint
response = ec2.create_vpc_endpoint(
VpcId='vpc-xxxxx',
ServiceName='com.amazonaws.us-east-1.sagemaker.runtime',
VpcEndpointType='Interface',
SubnetIds=['subnet-yyyyy'],
SecurityGroupIds=['sg-zzzzz']
)
from sagemaker.pytorch import PyTorchModel
# モデルの作成
pytorch_model = PyTorchModel(
model_data=f's3://{bucket}/model.tar.gz',
role=role,
framework_version='2.0',
py_version='py310',
entry_point='inference.py'
)
# デプロイ
predictor = pytorch_model.deploy(
initial_instance_count=2,
instance_type='ml.g4dn.xlarge',
serializer=sagemaker.serializers.JSONSerializer(),
deserializer=sagemaker.deserializers.JSONDeserializer()
)
# 推論
result = predictor.predict(data)
| メトリクス | 用途 | 設定例 |
|---|---|---|
| InvocationsPerInstance | 一般的な負荷 | 目標値: 1000 |
| ModelLatency | レイテンシー重視 | 目標値: 100ms |
| CPUUtilization | CPU集約的モデル | 目標値: 70% |
| GPUUtilization | GPU集約的モデル | 目標値: 80% |
# カスタムメトリクスベースのスケーリング
client.put_scaling_policy(
PolicyName='latency-based-scaling',
ServiceNamespace='sagemaker',
ResourceId=f'endpoint/{endpoint_name}/variant/{variant_name}',
ScalableDimension='sagemaker:variant:DesiredInstanceCount',
PolicyType='TargetTrackingScaling',
TargetTrackingScalingPolicyConfiguration={
'TargetValue': 100.0, # 100ms
'CustomizedMetricSpecification': {
'MetricName': 'ModelLatency',
'Namespace': 'AWS/SageMaker',
'Dimensions': [
{'Name': 'EndpointName', 'Value': endpoint_name},
{'Name': 'VariantName', 'Value': variant_name}
],
'Statistic': 'Average'
},
'ScaleInCooldown': 600,
'ScaleOutCooldown': 300
}
)
| 観点 | CloudFormation | CDK |
|---|---|---|
| 言語 | YAML/JSON | Python, TypeScript等 |
| 学習曲線 | 緩やか | やや急 |
| 再利用性 | 低い | 高い(クラス、関数) |
| テスト | 困難 | 容易 |
| IDEサポート | 限定的 | 優れている |
| 抽象化 | 低レベル | 高レベル |