Amazon Web Services 한국 블로그

Amazon SageMaker Model Monitor – 기계 학습 모델을 위한 완전 관리형 자동 모니터링 기능 출시 (서울 리전 포함)

Amazon SageMaker Model Monitor는 정식 서비스 환경에서 기계 학습(ML) 모델을 모니터링하고, 데이터 품질 문제가 발생했을 때 이를 알려주는 새로운 서비스입니다.

데이터 작업을 시작하면서 때 처음 깨달은 것은 데이터 품질에 아무리 주의를 기울여도 부족하다는 것입니다. 데이터베이스 중 하나에서 예기치 않은 NULL 값이나 복잡한 문자 인코딩 때문에 발생한 문제를 해결하기 위해 수많은 시간을 보낸 경험을 여러분 모두 한 번은 겪었을 거라 생각합니다.

기계 학습 모델은 말 그대로 대량의 데이터로 만들어지므로, ML 전문가들이 데이터 세트를 관리하는 데 왜 그토록 많은 시간을 투자하는지 쉽게 이해할 수 있습니다. 이들은 특히 학습 세트(모델 학습에 사용)와 검증 세트(정확도 측정에 사용)의 데이터 샘플이 동일한 통계 속성을 가지고 있는지 확인합니다.

어디서 괴물이 나타날지 모릅니다!

실험용 데이터 세트는 완벽하게 제어할 수 있지만 모델이 처리할 실제 데이터에 대해서는 확신하기 어렵습니다. 물론 실제 데이터는 정리되지 않은 상태일 것입니다. 하지만 더 걱정되는 문제는 “데이터 드리프트”, 즉 수신하는 데이터의 통계적 본질의 점진적인 변화입니다. 최소값, 최대값, 평균값, 중간값, 차이값 등은 모두 모델 학습 시 예측과 결정의 토대가 되는 핵심 속성입니다. 직관적으로 여러분도 이러한 값이 크게 변할 경우 예측 정확도에 영향을 미칠 것을 확실히 느낄 것입니다. 입력 기능이 바뀌거나 심지어 누락되어 대출 애플리케이션이 더 높은 금액을 예측한다고 상상해보십시오!

이러한 상황을 감지하는 것은 상당히 어렵습니다. 우선 모델에 수신되는 데이터를 캡처해야 하고, 이 데이터를 학습 세트와 비교하기 위해 온갖 통계적인 분석을 수행해야 합니다. 또한 드리프트를 감지하는 규칙을 정의하고 드리프트가 실제로 발생했을 때 경보도 전송해야 합니다. 여기서 끝나는 게 아니라 모델을 업데이트할 때마다 이 과정을 처음부터 다시 반복해야 합니다. 물론 ML 전문가들은 이렇게 복잡한 도구를 빌드하는 방법을 알고 있습니다. 하지만 이는 엄청난 시간과 리소스를 댓가로 얻어낼 수 있는 결과물입니다. 차별화되지 않는 일에 힘을 쏟아 붓는 상황이 반복되는 것입니다.

모든 고객이 가치를 창출하는 데 집중할 수 있도록 Amazon SageMaker Model Monitor가 탄생했습니다. 좀 더 자세히 설명해드리겠습니다.

Amazon SageMaker Model Monitor 소개
일반적인 모니터링 세션은 다음과 같은 순서를 따릅니다. 우선 모니터링할 SageMaker 엔드포인트에서 시작합니다. 엔드포인트는 기존 엔드포인트이거나 모니터링용으로 만든 새 엔드포인트일 수 있습니다. 모델이 기본 제공 알고리즘, 기본 제공 프레임워크 또는 자체 컨테이너를 사용하여 학습되었는지에 관계없이 모든 엔드포인트에서 SageMaker Model Monitor를 사용할 수 있습니다.

SageMaker SDK를 사용하여 엔드포인트로 전송된 데이터의 구성 가능한 일부를 캡처하고(원하는 경우 예측도 캡처할 수 있음) Amazon Simple Storage Service(S3) 버킷 중 하나에 저장할 수 있습니다. 캡처된 데이터에는 메타데이터(콘텐츠 유형, 타임스탬프 등)가 추가되며 다른 S3 객체와 마찬가지로 보호하고 액세스할 수 있습니다.

그런 다음 엔드포인트에 배포된 모델을 학습시키는 데 사용된 데이터 세트에서 기준선을 생성합니다(기존 기준선도 사용 가능). 이렇게 하면 Amazon SageMaker Processing 작업이 실행되고 SageMaker Model Monitor 가 다음을 수행합니다.

  • 입력 데이터에 대해 스키마를 추론합니다(예: 각 기능에 대한 유형 및 완전성 정보). 검토 후 필요하면 업데이트해야 합니다.
  • 사전 빌드된 컨테이너의 경우에만 Deequ를 사용하여 기능 통계를 계산합니다. Deequ는 Amazon에서 개발하여 사용 중인 Apache Spark 기반의 오픈 소스 도구입니다(블로그 게시물연구 논문). 이러한 통계에는 데이터 스트림에서 정확한 분위수를 계산하는 고급 기술인 KLL sketches가 포함됩니다. 이 기술은 최근에 Deequ에 제공한 기술입니다.

이러한 아티팩트를 사용하여 다음 단계에서는 SageMaker Model Monitor가 수집된 데이터와 예측 품질을 검사할 수 있게 모니터링 일정을 시작해야 합니다. 기본 제공 컨테이너 또는 사용자 지정 컨테이너를 사용하는지에 관계없이 몇 가지 기본 제공 규칙이 적용되고 Amazon S3로 보고서가 정기적으로 푸시됩니다. 보고서에는 가장 최근 기간 동안 수신된 데이터에 대한 통계 및 스키마 정보뿐 아니라 감지된 모든 위반 사항이 포함됩니다.

마지막으로 SageMaker Model Monitor는 기능별 메트릭을 대시보드와 경보를 설정하는 데 사용할 수 있는 Amazon CloudWatch로 보냅니다. CloudWatch에 있는 요약 메트릭은 SageMaker Studio에서도 볼 수 있으며, 두말 할 필요 없이 모든 통계, 모니터링 결과 및 수집된 데이터는 노트북에서 보고 추가적으로 분석할 수 있습니다.

AWS CloudFormation을 사용하여 SageMaker Model Monitor를 사용하는 방법에 대한 자세한 내용 및 예를 보려면 개발자 안내서를 참조하십시오.

이제 기본 제공 XGBoost 알고리즘을 사용하여 학습된 churn prediction 모델을 사용하는 데모를 살펴보겠습니다.

데이터 캡처 활성화
첫 번째 단계는 데이터 캡처를 활성화하기 위해 엔드포인트 구성을 생성하는 것입니다. 이 데모에서는 수신 데이터뿐 아니라 모델 출력(예: 예측)도 100% 캡처하도록 설정하겠습니다. 그리고 CSV 및 JSON 데이터 콘텐츠 유형도 전달합니다.

data_capture_configuration = {
    "EnableCapture": True,
    "InitialSamplingPercentage": 100,
    "DestinationS3Uri": s3_capture_upload_path,
    "CaptureOptions": [
        { "CaptureMode": "Output" },
        { "CaptureMode": "Input" }
    ],
    "CaptureContentTypeHeader": {
       "CsvContentTypes": ["text/csv"],
       "JsonContentTypes": ["application/json"]
}

다음으로 일반적인 CreateEndpoint API를 사용하여 엔드포인트를 생성합니다.

create_endpoint_config_response = sm_client.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType':'ml.m5.xlarge',
        'InitialInstanceCount':1,
        'InitialVariantWeight':1,
        'ModelName':model_name,
        'VariantName':'AllTrafficVariant'
    }],
    DataCaptureConfig = data_capture_configuration)

기존 엔드포인트인 경우 엔드포인트 구성을 원활하게 업데이트하기 위해 UpdateEndpoint API를 사용해야 합니다.

엔드포인트를 반복적으로 호출하고 나면 S3에 캡처된 데이터를 볼 수 있습니다. 명확하게 볼 수 있게 출력을 편집했습니다.

$ aws s3 ls --recursive s3://sagemaker-us-west-2-123456789012/sagemaker/DEMO-ModelMonitor/datacapture/DEMO-xgb-churn-pred-model-monitor-2019-11-22-07-59-33/
AllTrafficVariant/2019/11/22/08/24-40-519-9a9273ca-09c2-45d3-96ab-fc7be2402d43.jsonl
AllTrafficVariant/2019/11/22/08/25-42-243-3e1c653b-8809-4a6b-9d51-69ada40bc809.jsonl

다음은 이러한 파일 중 하나에서 가져온 줄입니다.

    "endpointInput":{
        "observedContentType":"text/csv",
        "mode":"INPUT",
        "data":"132,25,113.2,96,269.9,107,229.1,87,7.1,7,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,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,0,0,0,0,0,0,0,1,0,1,0,0,1",
        "encoding":"CSV"
     },
     "endpointOutput":{
        "observedContentType":"text/csv; charset=utf-8",
        "mode":"OUTPUT",
        "data":"0.01076381653547287",
        "encoding":"CSV"}
     },
    "eventMetadata":{
        "eventId":"6ece5c74-7497-43f1-a263-4833557ffd63",
        "inferenceTime":"2019-11-22T08:24:40Z"},
        "eventVersion":"0"}

예상한 것과 비슷하게 결과가 나왔습니다. 이제 이 모델의 기준선을 생성하겠습니다.

모니터링 기준선 생성
이 단계는 매우 간단합니다. 기준선 데이터 세트의 위치와 결과를 저장할 위치를 전달하면 됩니다.

from processingjob_wrapper import ProcessingJob

processing_job = ProcessingJob(sm_client, role).
   create(job_name, baseline_data_uri, baseline_results_uri)

이 작업을 완료하면 S3에서 새 객체 2개를 볼 수 있는데 하나는 통계 객체이고 다른 하나는 제약 조건 객체입니다.

aws s3 ls s3://sagemaker-us-west-2-123456789012/sagemaker/DEMO-ModelMonitor/baselining/results/
constraints.json
statistics.json

constraints.json 파일은 교육 데이터 세트에 대해 추론된 스키마의 정보를 제공합니다(정확한지 확인 필요). 각 기능의 유형 및 기능이 항상 표시되는지 여부에 대한 정보도 볼 수 있습니다(여기서 1.0은 100%를 의미함). 다음은 처음 몇 개의 줄입니다.

{
  "version" : 0.0,
  "features" : [ {
    "name" : "Churn",
    "inferred_type" : "Integral",
    "completeness" : 1.0
  }, {
    "name" : "Account Length",
    "inferred_type" : "Integral",
    "completeness" : 1.0
  }, {
    "name" : "VMail Message",
    "inferred_type" : "Integral",
    "completeness" : 1.0
  }, {
    "name" : "Day Mins",
    "inferred_type" : "Fractional",
    "completeness" : 1.0
  }, {
    "name" : "Day Calls",
    "inferred_type" : "Integral",
    "completeness" : 1.0

이 파일의 맨 끝에는 CloudWatch 모니터링에 대한 구성 정보(켜기/끄기, 드리프트 임계값 설정 등)가 나옵니다.

"monitoring_config" : {
    "evaluate_constraints" : "Enabled",
    "emit_metrics" : "Enabled",
    "distribution_constraints" : {
      "enable_comparisons" : true,
      "min_domain_mass" : 1.0,
      "comparison_threshold" : 1.0
    }
  }

statistics.json 파일에는 각 기능의 서로 다른 통계(중간값, 평균값, 분위수 등)는 물론 엔드포인트에 수신된 고유한 값이 표시됩니다. 다음은 한 가지 예제입니다.

"name" : "Day Mins",
    "inferred_type" : "Fractional",
    "numerical_statistics" : {
      "common" : {
        "num_present" : 2333,
        "num_missing" : 0
      },
      "mean" : 180.22648949849963,
      "sum" : 420468.3999999996,
      "std_dev" : 53.987178959901556,
      "min" : 0.0,
      "max" : 350.8,
      "distribution" : {
        "kll" : {
          "buckets" : [ {
            "lower_bound" : 0.0,
            "upper_bound" : 35.08,
            "count" : 14.0
          }, {
            "lower_bound" : 35.08,
            "upper_bound" : 70.16,
            "count" : 48.0
          }, {
            "lower_bound" : 70.16,
            "upper_bound" : 105.24000000000001,
            "count" : 130.0
          }, {
            "lower_bound" : 105.24000000000001,
            "upper_bound" : 140.32,
            "count" : 318.0
          }, {
            "lower_bound" : 140.32,
            "upper_bound" : 175.4,
            "count" : 565.0
          }, {
            "lower_bound" : 175.4,
            "upper_bound" : 210.48000000000002,
            "count" : 587.0
          }, {
            "lower_bound" : 210.48000000000002,
            "upper_bound" : 245.56,
            "count" : 423.0
          }, {
            "lower_bound" : 245.56,
            "upper_bound" : 280.64,
            "count" : 180.0
          }, {
            "lower_bound" : 280.64,
            "upper_bound" : 315.72,
            "count" : 58.0
          }, {
            "lower_bound" : 315.72,
            "upper_bound" : 350.8,
            "count" : 10.0
          } ],
          "sketch" : {
            "parameters" : {
              "c" : 0.64,
              "k" : 2048.0
            },
            "data" : [ [ 178.1, 160.3, 197.1, 105.2, 283.1, 113.6, 232.1, 212.7, 73.3, 176.9, 161.9, 128.6, 190.5, 223.2, 157.9, 173.1, 273.5, 275.8, 119.2, 174.6, 133.3, 145.0, 150.6, 220.2, 109.7, 155.4, 172.0, 235.6, 218.5, 92.7, 90.7, 162.3, 146.5, 210.1, 214.4, 194.4, 237.3, 255.9, 197.9, 200.2, 120, ...

이제 엔드포인트 모니터링을 시작해 보겠습니다.

엔드포인트 모니터링
이번에도 API를 한 번만 호출하면 됩니다. 엔드포인트에 대한 모니터링 일정을 생성하고 기준선 데이터 세트에 대한 제약 조건 파일과 통계 파일을 전달하면 됩니다. 데이터와 예측을 조정하려는 경우에는 필요에 따라 사전 처리 및 사후 처리 함수도 전달할 수 있습니다.

ms = MonitoringSchedule(sm_client, role)
schedule = ms.create(
   mon_schedule_name, 
   endpoint_name, 
   s3_report_path, 
   # record_preprocessor_source_uri=s3_code_preprocessor_uri, 
   # post_analytics_source_uri=s3_code_postprocessor_uri,
   baseline_statistics_uri=baseline_results_uri + '/statistics.json',
   baseline_constraints_uri=baseline_results_uri+ '/constraints.json'
)

그런 후 엔드포인트에 가짜 데이터(예: 임의 값으로 만든 샘플)를 전송하고 SageMaker 모델 모니터가 보고서를 생성할 때까지 기다립니다. 엄청 긴장되는 순간입니다!

보고서 검사
얼마 지나지 않아 S3에 보고서가 표시됩니다.

mon_executions = sm_client.list_monitoring_executions(MonitoringScheduleName=mon_schedule_name, MaxResults=3)
for execution_summary in mon_executions['MonitoringExecutionSummaries']:
    print("ProcessingJob: {}".format(execution_summary['ProcessingJobArn'].split('/')[1]))
    print('MonitoringExecutionStatus: {} \n'.format(execution_summary['MonitoringExecutionStatus']))

ProcessingJob: model-monitoring-201911221050-df2c7fc4
MonitoringExecutionStatus: Completed 

ProcessingJob: model-monitoring-201911221040-3a738dd7
MonitoringExecutionStatus: Completed 

ProcessingJob: model-monitoring-201911221030-83f15fb9
MonitoringExecutionStatus: Completed 

모니터링 작업 중 하나에 대한 보고서를 찾아보겠습니다.

desc_analytics_job_result=sm_client.describe_processing_job(ProcessingJobName=job_name)
report_uri=desc_analytics_job_result['ProcessingOutputConfig']['Outputs'][0]['S3Output']['S3Uri']
print('Report Uri: {}'.format(report_uri))

Report Uri: s3://sagemaker-us-west-2-123456789012/sagemaker/DEMO-ModelMonitor/reports/2019112208-2019112209

보고서에 어떤 내용이 있을까요?

aws s3 ls s3://sagemaker-us-west-2-123456789012/sagemaker/DEMO-ModelMonitor/reports/2019112208-2019112209/

constraint_violations.json
constraints.json
statistics.json

예상대로 constraints.jsonstatistics.json에는 모니터링 작업을 통해 처리된 데이터 샘플에 대한 스키마 정보와 통계 정보가 포함되어 있습니다. 세 번째 파일인 constraints_violations.json을 직접 열어보겠습니다.

violations" : [ {
    "feature_name" : "State_AL",
    "constraint_check_type" : "data_type_check",
    "description" : "Value: 0.8 does not meet the constraint requirement! "
  }, {
    "feature_name" : "Eve Mins",
    "constraint_check_type" : "baseline_drift_check",
    "description" : "Numerical distance: 0.2711598746081505 exceeds numerical threshold: 0"
  }, {
    "feature_name" : "CustServ Calls",
    "constraint_check_type" : "baseline_drift_check",
    "description" : "Numerical distance: 0.6470588235294117 exceeds numerical threshold: 0"
  }

이런! 정수 기능에 부동 소수점 값을 잘못 할당한 것 같군요. 이렇게 되면 문제가 생길 수밖에 없습니다.

일부 기능에서도 드리프트가 나타나고 있는데, 이 또한 좋은 결과가 아닙니다. 데이터 수집 프로세스에서 문제가 있었거나 데이터 배분이 실제로 변경되었을 수 있으므로 모델을 다시 학습해야 합니다. 이 모든 정보를 CloudWatch 메트릭으로 사용할 수 있기 때문에 임계값을 정의하거나, 알람을 설정하거나, 새로운 교육 작업을 자동으로 트리거할 수도 있습니다.

지금 이용 가능
보시다시피 Amazon SageMaker Model Monitor는 설정하기 쉽고 ML 모델의 품질 문제점을 빠르게 파악할 수 있게 도와줍니다.

이제 여러분도 Amazon SageMaker를 사용할 수 있는 모든 상용 리전에서 지금 바로 Amazon SageMaker Model Monitor를 사용해볼 수 있습니다. 이 기능은 Amazon의 ML 프로젝트 워크벤치인 Amazon SageMaker Studio에도 통합되어 있습니다. 마지막으로, 모든 정보는 쥬피터 노트북에서 보고 추가적으로 분석할 수 있습니다.

사용해 보시고 피드백이 있으면 Amazon SageMaker에 대한 AWS 포럼 또는 평소에 연락하는 AWS Support 담당자를 통해 알려주시기 바랍니다.

– Julien