AWS 기술 블로그

롯데ON 사례로 본 개인화 추천 시스템 구축하기, 2부 : Amazon SageMaker를 활용한 MLOps 구성 및 추천 모델 실시간 서비스

롯데ON은 단순 상품판매 뿐만 아닌 상품에 대한 경험을 함께 제공할 수 있는 플랫폼을 목표로 서비스하고 있습니다. 패션, 뷰티, 럭셔리, 키즈 등 다양한 전문관을 운영하며 고객들이 선호하는 라이프 스타일 전반에 걸쳐 쇼핑에 관한 좋은 경험을 제공해 드릴 수 있도록 노력하고 있습니다.

롯데ON의 고객 쇼핑 경험을 높이기 위해, 추천플랫폼개발팀에서는 고객이 찾고 있는 상품이나 흥미를 느낄 만한 상품을 적재적소에 제공할 수 있도록 추천 서비스를 지속적으로 개선해 나가고 있습니다.

1부에서는 롯데ON에서 Dynamic A/B Testing 아키텍처 구축한 사례를 알아보았습니다. 이번 게시글에서는 AWS 서비스를 활용하여 MLOps 환경을 구성하고, 실시간 서비스를 제공한 사례를 소개합니다.

문제 정의

기존에는 주로 상품 간의 관계를 파악하여 고객이 선택한 상품과 관련도가 높은 상품을 제공해 주는 방식으로 서비스를 제공하고 있었습니다. 하지만 고객들 개개인의 취향을 분석하고 니즈를 충족하기 위해선 서비스를 고도화 할 필요가 있었습니다. 이에 따라, 데이터의 선형적인 관계만 파악하는 것뿐 아니라 보다 복잡한 관계를 파악할 수 있는 딥러닝 기반의 추천 알고리즘 도입을 결정하였습니다. 따라서 만들어진 모델을 관리하는 동시에 실시간으로 서비스할 수 있도록 MLOps 플랫폼을 구축하게 되었습니다.

또한, 기존 추천 플랫폼에서 사용하고 있는 코드 레포지토리인 GitLab과 연동할 수 있는 CI/CD 를 구축하여 신규로 개발하는 추천 모델들을 쉽게 추가하고, 모델의 주기적인 재학습 및 재배포를 통하여 지속적으로 추천 서비스의 품질을 높일 수 있는 구조를 만드는 것이 또 다른 요구사항이었습니다.

이번 기술 블로그에서는 고객들에게 양질의 추천을 제공하기 위해 구축한 MLOps 플랫폼과 딥러닝 기반의 추천 알고리즘(Neural Collaborative Filtering ; NCF)을 실시간으로 추론하여 서비스에 도입하기 까지의 전반적인 과정에 대해 소개합니다.

솔루션 아키텍처

아래는 NCF 알고리즘 기반 추천 모델 서빙을 MLOps로 구성한 솔루션 아키텍처 입니다. 대표적으로 사용하는 AWS 서비스는 Amazon SageMaker, Amazon EMR, AWS CodeBuild, Amazon S3, Amazon EventBridge, AWS LambdaAmazon API Gateway 입니다. SageMaker를 중심으로 여러 AWS 서비스를 결합하여 구성하였으며, 다음의 항목들을 중점으로 생각하며 아키텍처를 설계하였습니다.

  • 데이터 전처리
  • 모델의 학습 및 배포 자동화
  • 모델 서빙을 통한 실시간 추론
  • CI/CD 구조

위의 아키텍처는 3개의 디커플링 (Decoupling) 컴포넌트로 구성된 MLOps 데이터 흐름을 보여 주고 있고, 각각의 컴포넌트에 대해서 설명 드리겠습니다.

1. 코드 준비 및 데이터 전처리 (파란색)

  • 단계 1: 데이터 과학자가 모델과 학습 파이프라인이 포함된 배포 코드를 롯데ON에서 사용중인 GitLab 에 퍼블리시를 하면, Jenkins 가 이 코드를 S3에 업로드 합니다.
  • 단계 2: 지정한 스케줄에 맞춰 Airflow를 통해 EMR 전처리 배치를 실행 시킵니다. 전처리 데이터는 S3와 함께 피처스토어로 사용되는 MongoDB로 적재 됩니다.

2. 학습 파이프라인 실행 및 모델 배포 (초록색)

  • 단계 1: S3에 학습데이터가 업로드 되면 EventBridge에 지정된 룰에 따라서 CodeBuild를 실행합니다.
  • 단계 2: CodeBuild에서 사전에 정의해 놓은 SageMaker Pipeline을 실행시키고, 프로비저닝을 포함한 전처리, 모델 학습, 모델 등록 등의 Step들을 순차적으로 실행시킵니다.
  • 단계 3: Lambda Step을 통하여 학습 후 배포된 모델을 SageMaker Endpoint에 업데이트 시킵니다.

3. 실시간 추천 추론 서비스 (갈색)

  • 단계 1: Client Application (파트 1 블로그에서 언급된 추천 API) 에서 API Gateway 에 추론 요청을 합니다.
  • 단계 2: API Gateway 는 요청을 Lambda 에 보내고, Lambda 에서는 SageMaker Endpoint의 모델에 추천 리스트를 요청하는 추론 요청을 합니다.
  • 단계 3: Lambda 는 추천 리스트를 제공받아 API Gateway 에 제공합니다.
  • 단계 4: API Gateway 는 Client Application 인 추천 API 에 추천 리스트를 제공 합니다.

추천 모델: Neural Collaborative Filtering (NCF)

NCF는 2017년에 International World Wide Web Conference에 소개된 논문을 기반으로 하는 알고리즘입니다. 기존 추천 시스템에서 많이 쓰이는 Linear한 Matrix Factorization의 한계점을 Neural Net 기반의 Collaborative Filtering으로 커버한 알고리즘입니다. 논문의 저자들은 Neural Net을 통해 Non-Linearity를 추가함으로써 유저와 아이템의 관계를 좀 더 복합적으로 모델링할 수 있게 하였습니다. NCF의 데이터로는 유저가 아이템에 반응한 상호작용 데이터를 사용하며, 모델의 전체적인 구조는 아래 그림과 같습니다.

(출처 : https://arxiv.org/abs/1708.05031)

NCF는 소개된 지 오래되었지만, 지금도 다양한 영역에서 간단하게 좋은 성능을 내는 모델로 알려져 있습니다. 그래서 우리는 MLOps 플랫폼의 프로토타입이 되는 모델로 해당 모델을 선정하였습니다. 모델에 대한 자세한 내용은 논문을 참조하시기 바랍니다.

MLOps 구현 상세 1: 데이터 전처리

NCF의 경우 유저-아이템 간 상호작용 데이터를 사용하는데, 어플리케이션 단에서 수집된 로우 데이터를 가공하고 학습에 적합한 형태로 변형하기 위해선 꽤 큰 리소스가 필요했습니다. 우리는 Apache Hadoop 및 Spark와 같은 환경을 완전관리형으로 제공해주는 EMR을 사용함으로써 보다 빠르게 데이터를 처리할 수 있었습니다.

데이터 전처리 배치는 AWS CLI 명령어를 통해 EMR을 실행시키는 쉘 스크립트를 작성하여, Airflow에 등록하여 특정 주기마다 실행될 수 있도록 하였습니다. 전처리 배치가 완료되면 학습에 필요한 훈련/테스트 데이터가 수행시간을 기반으로 파티셔닝 되어 S3에 저장하도록 하였습니다. 다음은 EMR을 실행 시키는 AWS CLI 명령어의 예시입니다.

aws emr create-cluster --release-label emr-6.0.0 \
    --name "CLUSTER_NAME" \
    --applications Name=Hadoop Name=Hive Name=Spark \
    --tags 'Name=EMR-DATA-PREP' 'Owner=MODEL' 'Service=LOTTEON' \
    --ec2-attributes '{"KeyName":"keyname","InstanceProfile":"DefaultRole","ServiceAccessSecurityGroup":"sg-xxxxxxxxxxxxxx","SubnetId":"subnet- xxxxxxxxxxxxxx ","EmrManagedSlaveSecurityGroup":"sg- xxxxxxxxxxxxxx ","EmrManagedMasterSecurityGroup":"sg-xxxxxxxxxxxxxx "}' \
--instance-groups '[{"InstanceCount":1,"InstanceGroupType":"MASTER","InstanceType":"r5.xlarge","Name":"Master Instance Group"},{"InstanceCount":2,"InstanceGroupType":"CORE","InstanceType":"r5.xlarge","Name":"Core Instance Group"},{"InstanceCount":2,"BidPrice":"OnDemandPrice","InstanceGroupType":"TASK","InstanceType":"r5.xlarge","Name":"Task Instance Group"}]' \
    --service-role EMR_DefaultRole \
    --region ap-northeast-2 \
    --steps Type=CUSTOM_JAR,Name=DATA_PREP,ActionOnFailure=CONTINUE,Jar=s3://ap-northeast-2.elasticmapreduce/libs/script-runner/script-runner.jar,Args=["s3://bucket/prefix/data_prep_batch.sh"]  \
    --auto-terminate

MLOps 구현 상세 2: 모델의 학습 및 배포 자동화

이벤트 기반 파이프라인 자동화

전처리 배치가 완료되어 S3에 훈련/테스트 데이터가 저장되면, 이 이벤트를 트리거로 하여 CodeBuild를 실행시키고, SageMaker의 학습 파이프라인이 수행 되도록 하였습니다. 이 과정에서 전처리 배치의 결과 파일의 버전을 기록하고, 버전에 맞춘 동적인 제어와 실행 이력을 관리할 수 있도록 하였습니다. EMR로 수행되는 데이터 전처리 단계와 SageMaker 학습 파이프라인을 이벤트 기반으로 연결하기 위해 EventBridge, Lambda, CodeBuild를 사용하였습니다.

EventBridge는 사용자가 설정한 이벤트 패턴과 대상에 따라, 이벤트를 수신하고 대상으로 라우팅하는 규칙을 적용하는 서버리스 서비스입니다. 우리가 구성한 EventBridge의 첫번째 역할은 전처리 배치가 S3에 학습용 데이터셋을  저장시키면, 해당 S3 object 생성 이벤트를 트리거로 Lambda를 실행시키는 것 입니다. Lambda에서는 CodeBuild가 실행될 때 필요한 buildspec.yml 파일을 동적으로 수정합니다. 이 때 수정되는 내용은 학습해야 하는 데이터의 경로, 버전, 파티션 정보 등 학습 파이프라인을 수행할 때 필요한 정보들입니다. EventBridge의 두번째 역할은 buildspec.yml 파일이 수정되는 것을 트리거로 하여 CodeBuild 수행으로 연결되도록 이벤트를 송신하는 역할입니다.

CodeBuild는 SageMaker Pipeline이 정의되어 있는 소스코드를 빌드하게 됩니다. 이 과정에서 buildspec.yml을 참조하게 되며, buildspec에 정의된 경로로부터 빌드에 필요한 소스코드 복제 및 라이브러리 설치 등의 과정을 수행하게 됩니다. CodeBuild의 프로젝트 빌드 탭을 통하여 빌드의 성공 및 실패 이력과 SageMaker Pipeline의 수행 로그를 실시간으로 확인할 수 있습니다.

 

SageMaker 학습 파이프라인

SageMaker Pipeline은 ML서비스에 필요한 전처리, 학습, 배포 등의 Step을 SDK를 이용하여 쉽게 정의 할 수 있도록 도와줍니다. 각 Step은 SageMaker Studio 내에서 시각화 되어 모델을 관리하는데 있어 큰 도움을 주고, 학습된 모델의 이력이나 모델을 서빙 할 수 있는 Endpoint도 관리할 수 있습니다. 또한 Step의 결과값에 조건문을 달아서 Step을 설정할 수도 있기 때문에 재학습 결과가 우수한 모델만 채택 하거나, 학습 실패에 대한 대비를 하기에도 좋습니다. 우리가 구축한 SageMaker Pipeline의 단계별 예시는 다음과 같습니다.

  • Model Training Step
  • Register Model Step
  • Create Model Step
  • Deploy Model Step

각 Step은 SageMaker Studio의 파이프라인에서 시각화 되며, 아래처럼 실시간으로 각 Step의 결과값이나 진행 상황을 확인할 수도 있습니다.

이제부터는 모델 학습부터, 배포까지 이어지는 Step들을 간단한 예시들을 통해 보여드리도록 하겠습니다.

모델 학습 Step

훈련에 사용할 Pytorch Estimator를 정의하고, Train Step을 정의해줍니다. 여기에서는 사전에 학습 코드 (에: train.py)가 준비되어야 하며 코드의 위치를 source_dir의 인자로 전달해줍니다. Train Step은 entry_point의 인자로 전달한 학습 코드를 실행시키게 됩니다. 기본적으로 학습은 지정한 인스턴스에서 컨테이너를 띄워서 진행하게 되므로, 자신이 개발한 학습 환경에 맞는 학습 도커 이미지의 경로를 전달해줘야 합니다. 단 여기서 Estimator의 프레임워크가 지정된 상태에서는 사용할 프레임워크의 버전과 Python 버전을 전달해주면, 기본적으로 버전에 맞는 컨테이너 이미지를 Amazon ECR로부터 자동으로 불러와 줍니다.

Pytorch Estimator 정의가 끝났으면, 학습에 관련된 Step을 정의해줍니다. 앞서 정의한 Pytorch Estimator를 인자로 넘겨주고, Input Data의 위치를 넘겨주면 됩니다. Input Data의 위치를 넘겨주면 컨테이너의 특정 경로 (/opt/ml/input/data/<channel_name>, 예 : /opt/ml/input/data/train)로 train과 test 데이터를 다운받아 사용할 수 있습니다.

추가적으로 Pytorch Estimator 를 정의할 시에 Metric Definitions를 활용해 모델이 학습되는 동안에 생성되는 학습 지표를 Amazon CloudWatch로 모니터링 할 수 있습니다. 또한 estimator_output_path 지정을 통해서 학습 후의 모델 아티펙트의 결과가 저장되는 경로를 지정할 수 있으며, model_hyperparameters를 지정하여, 모델 학습에 필요한 파라미터를 사용할 수 있습니다.

metric_definitions=[
        {'Name': 'HR', 'Regex': 'HR=(.*?);'},
        {'Name': 'NDCG', 'Regex': 'NDCG=(.*?);'},
        {'Name': 'Loss', 'Regex': 'Loss=(.*?);'}
    ]
estimator_output_path = f's3://{bucket}/{prefix}'
model_hyperparameter = {'epochs': 10, 
                    'lr': 0.001,
                    'batch_size': 256,
                    'top_k' : 10,
                    'dropout' : 0.3,
                    'factor_num' : 32,
                    'num_layers' : 3
                }  
s3_code_uri = 's3://code_location/source.tar.gz'

host_estimator = PyTorch(
    entry_point="train.py",           
    source_dir = s3_code_uri, 
    output_path = estimator_output_path,                
    role=aws_role,
framework_version='1.8.1',
    py_version='py3',
    instance_count=1,
    instance_type='ml.p3.2xlarge',
    session = pipeline_session,
    hyperparameters=model_hyperparameter,
    metric_definitions = metric_definitions
)

from sagemaker.inputs import TrainingInput
from sagemaker.workflow.steps import TrainingStep
data_loc = f's3://{bucket}/{prefix}'
step_train = TrainingStep(
    name= "NCF-Training",
    estimator=host_estimator,
    inputs={
        "train": TrainingInput(s3_data=data_loc),
        "test": TrainingInput(s3_data=data_loc),        
    }
)

모델 패키지 그룹 생성

다음으로는 훈련된 모델을 관리해줄 모델 패키지 그룹을 생성하는 과정입니다. 모델 패키지에 학습된 모델을 등록하면, 학습된 모델을 다음과 같이 버전별로 관리 할 수 있습니다. 해당 정보를 통해 이전 버전의 모델들을 언제든지 참조할 수 있습니다. 위 과정은 처음 모델을 학습시킬 때 한번만 해주면 동일한 그룹명을 선언한 모델에 한해서 지속적으로 추가 및 업데이트 할 수 있습니다.

import boto3
model_package_group_name = 'NCF'
sm_client = boto3.client("sagemaker")
model_package_group_input_dict = {
    "ModelPackageGroupName" : model_package_group_name,
    "ModelPackageGroupDescription" : "Model Package Group"
}
response = sm_client.list_model_package_groups(NameContains=model_package_group_name)
if len(response['ModelPackageGroupSummaryList']) == 0:
create_model_pacakge_group_response = sm_client.create_model_package_group(**model_package_group_input_dict)

학습된 모델을 모델 패키지 그룹에 등록

다음으로는 학습된 모델을 위에서 만든 모델 패키지 그룹에 등록시키는 과정입니다. 아래 코드에서 Model 클래스를 선언하는 과정에서 앞선 “모델 학습 Step”의 결과값을 가져오는 것을 볼 수 있는데, 이 과정에서 Step간의 종속성이 형성되게 됩니다. 종속성이 선언 된 Step은 반드시 앞 선 Step이 성공해야만 실행되게 됩니다. 다만 depends_on 옵션을 사용하면 데이터의 선후 관계가 없더라도 Step간 종속성을 선언할 수 있습니다.

모델 패키지 그룹에 학습된 모델이 등록되었다면, 이제 이 정보를 가지고 추후 모델 버전의 관리 및 추적을 할 수 있고, Real Time SageMaker Endpoint 를 생성하거나, Batch Transform Job 등의 다양한 작업을 진행할 수 있습니다.

from sagemaker.workflow.model_step import ModelStep
from sagemaker.model import Model

inference_image_uri = '763104351884.dkr.ecr.ap-northeast-2.amazonaws.com/pytorch-inference:1.8.1-gpu-py3'
model = Model(
    image_uri=inference_image_uri,
    model_data = step_train.properties.ModelArtifacts.S3ModelArtifacts,
    role=role,
    sagemaker_session=pipeline_session,
)

register_model_step_args = model.register(
    content_types=["text/csv"],
    response_types=["text/csv"],
    model_package_group_name=model_package_group_name,
    approval_status='Approved',        
)

step_model_registration = ModelStep(
    name="RegisterModel",
    step_args=register_model_step_args
)

Real Time SageMaker Endpoint 생성을 위한 전 단계인 SageMaker Model 생성

Real Time SageMaker Endpoint 생성을 위해서는 먼저 SageMaker Model 을 생성해야 합니다. Endpoint 생성 시 Endpoint Configuration이 필요한데, SageMaker Model은 Endpoint Configuration 생성 시 Endpoint에서 호스팅 되는 모델로 등록됩니다.

SageMaker Model 을 생성시에는 다음의 단계를 주의하여 진행해야 합니다.

  • “모델 학습 Step” 의 결과인 properties.ModelArtifacts.S3ModelArtifacts를 model_data의 인자로 제공합니다. 즉 학습된 모델의 가중치 파일의 경로를 제공 합니다.
  • 추론 도커 이미지: PyTorchModel 클래스 및 framework_version, py_version 을 명시했기에 이 정보를 통하여 Amazon ECR 을 통해서 추론 도커 이미지의 경로를 가져옵니다. 이는 모델 학습에 사용했던 모델을 메모리에 적재하여 추론 작업을 하는 추론 도커 이미지 입니다. 모델 학습 시 사용한 PyTorch 프레임워크, Python 버전 등을 같게 입력해 주어야 합니다. 이는 학습과 추론의 PyTorch, Python 버전을 같게 유지하는 것을 의미 합니다.
  • 실제 Endpoint에서 추론할 때 사용하는 py 파일을 entry_point 인자로 제공합니다.

이 단계는 depends_on 옵션을 통해 위에서 정의한 모델 패키지 등록 스텝에 종속성을 설정하도록 하겠습니다.

from sagemaker.pytorch.model import PyTorchModel
from sagemaker.workflow.model_step import ModelStep

model_name = 'NCF-MODEL'
s3_code_uri = 's3://code_location/source.tar.gz'

model_inference = PyTorchModel(
        name = model_name,
        model_data = step_train.properties.ModelArtifacts.S3ModelArtifacts, 
image_uri= image_uri,
        role=role,
        entry_point= 'inference.py',
        source_dir = s3_code_uri,
        framework_version='1.8.1',
        py_version='py3',
        model_server_workers=1,
        sagemaker_session=pipeline_session
                            )
step_model_create = ModelStep(
    name="ModelCreation",
    step_args=model_inference.create(instance_type = 'ml.p3.2xlarge'),
    depends_on=step_model_registration
)

SageMaker Endpoint 생성

이제 생성된 모델을 바탕으로 Endpoint Configuration을 정의해주고, 배포하면 Endpoint가 생성되게 됩니다. SageMaker Python SDK에 배포와 관련된 Step은 아직 지원하지 않기 때문에 해당 Step은 Lambda를 사용하여 Step에 등록해 주었습니다. Lambda에 instance_type 등 필요한 인자들을 넘겨주고 해당 정보를 사용해 Endpoint Configuration을 우선 만들게 됩니다. endpoint_name을 바탕으로 Endpoint를 호출하기 때문에 해당 변수는 유니크한 이름으로 잘 정의해주시면 됩니다. 아래의 Lambda에서는 endpoint_name을 기준으로 해당 Endpoint가 존재하면 모델을 업데이트 시켜주고, 존재하지 않으면 새롭게 배포하게 됩니다.

# lambda_deploy_model.py
import json
import boto3
def lambda_handler(event, context):
    sm_client = boto3.client("sagemaker")
    model_name = event["model_name"]
    endpoint_config_name = event["endpoint_config_name"]
    endpoint_name = event["endpoint_name"]
    instance_type = event["instance_type"]
 
    create_endpoint_config_response = sm_client.create_endpoint_config(
        EndpointConfigName=endpoint_config_name,
        ProductionVariants=[
            {
                "InstanceType": instance_type,
                "InitialVariantWeight": 1,
                "InitialInstanceCount": 1,
                "ModelName": model_name,
                "VariantName": "AllTraffic",
            }
        ],
    )
    print(f"create_endpoint_config_response: {create_endpoint_config_response}")
    existing_endpoints = sm_client.list_endpoints(NameContains=endpoint_name)['Endpoints']
    if len(existing_endpoints["Endpoints"]) > 0:
        sm_client.update_endpoint(
            EndpointName=endpoint_name, EndpointConfigName=endpoint_config_name
        )
    else:
        sm_client.create_endpoint(
            EndpointName=endpoint_name, EndpointConfigName=endpoint_config_name
        )
    return {"statusCode": 200, "body": json.dumps("Endpoint Created Successfully")}

위에서 정의한 Lambda를 SageMaker Pipeline의 Step으로 가져다 쓰기 위해선 Lambda와 관련된 SDK를 이용하면 됩니다. Lambda 소스의 위치를 Lambda의 인자로 넘겨주면 자동으로 Lambda를 등록하여 사용할 수 있습니다. 이와 연계하여 LambdaStep을 정의하고 필요한 인자들을 전달해주면 됩니다.

from sagemaker.lambda_helper import Lambda
from sagemaker.workflow.lambda_step import (LambdaStep, LambdaOutput, LambdaOutputTypeEnum)
endpoint_name = 'NCF-ENDPOINT'
endpoint_config_name = 'NCF-CONF'
deploy_script_path = 's3://code_location/lambda_deploy_model.py'
deploy_model_func = Lambda(
    function_name='lambda-deploy-step',
    execution_role_arn=role,
    script=deploy_script_path,
    handler="lambda_deploy_model.lambda_handler"
)
output_param_1 = LambdaOutput(output_name="statusCode", output_type=LambdaOutputTypeEnum.String)
output_param_2 = LambdaOutput(output_name="body", output_type=LambdaOutputTypeEnum.String)

step_deploy_lambda = LambdaStep(
    name="LambdaDeployStep",
    lambda_func=deploy_model_func,
    inputs={
        "model_name": step_model_create.properties.ModelName,
        "endpoint_config_name": endpoint_config_name,
        "endpoint_name": endpoint_name,
        "instance_type": 'ml.p3.2xlarge',       
    },
    outputs=[output_param_1, output_param_2]
)

SageMaker 파이프라인 생성

이제 마지막으로 정의된 Step들을 사용하여 파이프라인P을 만들어주는 단계입니다. 파이프라인의 이름을 정의해주고, 해당 파이프라인에서 사용할 Step들을 인자로 넘겨주면 됩니다. 이후에는 start 함수를 통해 정의된 파이프라인을 실행시킬 수 있습니다.

from sagemaker.workflow.pipeline import Pipeline
pipeline_name = 'NCF-pipeline'
pipeline = Pipeline(
    name=pipeline_name,
    steps=[step_train, step_model_registration, step_model_create, step_deploy_lambda],
    sagemaker_session=pipeline_session,
)

pipeline.start()

위 과정을 거쳐, 학습된 모델로 Endpoint가 만들어지면 딥러닝 기반 모델을 바탕으로 서비스할 준비가 완료됩니다.

MLOps 구현 상세 3: 모델 서빙을 통한 실시간 추론

이제 만들어진 Endpoint에서 실시간으로 추론하는 방법을 살펴보겠습니다. Endpoint에 접근하는 방법 또한 SageMaker SDK를 사용하면 됩니다. 다음은 invoke_endpoint 함수를 통해 배포 된 Endpoint에서 입력 값에 대한 실시간 추론 값을 받아오는 예시입니다. Body의 인자로 전달한 피처는 Endpoint를 구성할 때 사용한 모델의 inference.py의 입력 값으로 전달되어 추론의 결과값을 실시간으로 리턴 하게 됩니다.

import boto3
sagemaker_runtime = boto3.client("sagemaker-runtime")
endpoint_name='NCF-ENDPOINT'
 
response = sagemaker_runtime.invoke_endpoint(
                    EndpointName=endpoint_name, 
                    Body=bytes("'features': '{\"user\": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], \"item\": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}'}")
)
print(response['Body'].read())

사전에 추론 함수를 구성할 때, 전달받은 아이템들 중에서 유저가 가장 좋아할 확률이 높은 아이템을 순서대로 리턴 하도록 하였습니다. 위 예제는 0번 인덱스의 유저에게 1~25번의 아이템 중 좋아할 만한 확률이 높은 순으로 아이템을 리턴 하는 예시입니다.

우리는 해당 함수에 비지니스 로직을 더하여 Lambda에 구성하였고, API Gateway와 연결시켜 실시간으로 추론하여 추천 아이템을 리턴 하는 API의 기능을 구현하였습니다. 이후 온라인 서비스를 위하여 성능테스트를 진행했으며, 1000 TPS의 환경에서도 안정적으로 서비스 할 수 있는 성능을 확인하였습니다. API 구성 방식이나 파라미터 캐시를 통한 자원 효율화 등의 자세한 내용은 파트1 블로그 #1(링크)을 참고하시길 바랍니다.

MLOps 구현 상세 4: CI/CD 구조

DevOps의 기본인 CI/CD 구조는 MLOps 환경을 구성함에 있어서도 중요한 부분입니다. AWS의 Code Series를 사용하면 이를 쉽게 구축할 수 있습니다. 여기서 AWS Code Series는 AWS CodeCommit, AWS CodeBuild, AWS CodeDeploy, AWS CodePipeline을 통칭하는 서비스입니다. 이 서비스들을 이용하면, 코드 형상관리부터 배포, 빌드, 배치관리 까지 CI/CD에 필요한 기능을 전부 구현할 수 있습니다. 다만 해당 서비스들이 같은 Code Series끼리만 연동되는 것이 아니라, Github이나 Jenkins 등 타 서비스들과도 연동되기 때문에 기존에 보유한 CI/CD 구조가 있다면 부족한 부분만 따로 연계하여 사용하기에도 좋습니다. 따라서 우리는 기존에 가지고 있던 CI/CD 파이프라인에 위에서 설명한 CodeBuild 서비스만 연계하여 CI/CD구조를 확장하였습니다.

SageMaker 노트북을 GitLab과 연동하여 코드 관리를 하였고, 작업이 마무리 되면 Jenkins를 통해 S3에 복제하였습니다. 이후에는 위에서 설명한 것과 같이 해당 S3의 경로를 NCF CodeBuild project의 기본 레포지토리 경로로 설정하여 CodeBuild를 통해 해당 프로젝트를 빌드할 수 있도록 구성하였습니다.

 

결론

지금까지 우리는 AWS 서비스를 활용하여 MLOps 환경을 구성하고, 딥러닝 모델을 기반으로 실시간 추론 서비스를 제공하는 End-to-End 과정을 살펴보았습니다. MLOps 환경을 구성함으로써 고객들에게 다채로운 알고리즘을 기반으로 한 질 좋은 서비스를 제공할 수 있는 밑바탕으로 만들었습니다. 또한, 프로토타입 개발과 배포까지 빠르게 진행할 수 있는 환경이 만들어졌습니다. 프로토타이핑 알고리즘으로 개발한 NCF도 실제로 서비스 해 보니 좋은 결과를 얻을 수 있었습니다. 앞으로는 우리가 구축한 MLOps 플랫폼의 이점을 이용하여 롯데ON 데이터와 맞는 모델들을 찾아 빠르게 개발하고, 실험하여 고객들에게 점진적으로 좋은 퀄리티의 추천 경험을 제공해드릴 예정입니다.

다양한 AWS 서비스와 연계하여 SageMaker를 사용해보니 서비스를 개발하고, 운영하는데 있어서 여러 이점이 있었습니다. 먼저 모델을 개발하는 입장에서 자주 사용하는 패키지나 딥러닝 관련 프레임워크에 대한 환경 세팅이 구성되어 있어서 라이브러리마다 버전을 맞추는 등의 환경설정을 해야 하는 부담 없었고, AWS CLI 명령어 및 관련 SDK를 활용한 AWS 서비스 간의 연계성 및 확장성도 크다고 느껴졌습니다. 그리고 서비스를 운영하는 입장에서 각각의 서비스의 이력 관리와 더불어 CloudWatch와 같은 모니터링 기능이 잘 연계되어 있어, 운영하는 서비스를 트래킹하고 모니터링하기도 좋았습니다.

실습을 위한 Neural Collaborative Filtering (NCF)과 MLOps 구성은 aws-samples/aws-ai-ml-workshop-kr github 에서도 확인 해보실 수 있습니다.

끝으로 AWS 서비스를 활용하여 MLOps 환경을 구성하고, 실시간 서비스를 제공함에 있어 본 포스팅이 도움이 되었으면 합니다.

SeungBum Shim

SeungBum Shim

심승범 데이터 엔지니어는 롯데이커머스 추천플랫폼개발팀 소속으로, 롯데ON 데이터 분석을 통해 추천 관련 프로덕트 활용/개선 방안을 발굴해내고, MLOps 파이프라인 및 ML/DL 추천 모델 개발 등을 담당하고 있습니다.

HyeKyung Yang

HyeKyung Yang

양혜경 리서치 엔지니어는 롯데이커머스 추천플랫폼개발팀 소속으로 다양한 데이터를 분석/활용하여 ML/DL 추천 모델 개발과 Dynamic A/B Test 환경 개발 등을 담당하고 있습니다.

Jieun Lim

Jieun Lim

임지은 데이터 엔지니어는 롯데이커머스 추천플랫폼개발팀 소속으로 롯데ON의 개인화 추천 시스템 운영, 개인화 추천 모델과 Dynamic A/B Test 환경 개발 등을 담당하고 있습니다.

Jesam Kim

Jesam Kim

김제삼 솔루션즈 아키텍트는 리테일 고객의 클라우드 기술 도입과 문제 해결을 돕고 있으며, 특히 추천 서비스 영역에서의 비즈니스 요구사항과 과제를 해결할 수 있는 지속 가능한 아키텍처를 설계할 수 있도록 기술적인 도움을 드리는 역할을 수행하고 있습니다.

Gonsoo Moon

Gonsoo Moon

AWS AIML 스페셜리스트 솔루션즈 아키텍트로 일하고 있습니다. AI/ML 의 다양한 유스케이스 및 프러뎍션 경험을 바탕으로 고객의 AI/ML 문제를 해결하기 위해 고객과 함께 고민하고 협업하는 일을 주로 하고 있습니다. AI/ML 기술을 데이터 과학자, 개발자, 분석가 분에게 전파하여, 글로벌 및 한국 사회가 발전될 수 있게 기여를 하고자 합니다.