{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# [모듈 2.1] 모델 훈련 스텝 및 모델 등록 스텝 개발 \n", "## 부제목: SageMaker 모델 빌드 파이프라인을 이용한 모델 빌드 오케스트레이션\n", "\n", "이 노트북은 \"모델 훈련\" 및 \"모델 등록\" 의 2 가지 스텝을 정의하고, 모델 빌딩 파이프라인을 생성하여 실행하는 노트북 입니다.\n", "아래의 목차와 같이 노트북 실행이 될 예정이고\n", "전체를 모두 실행시에 완료 시간은 약 5분-10분 소요 됩니다.\n", "\n", "- 1. 모델 훈련 및 모델 등록 개요 \n", "- 2. 기본 라이브러리 로딩\n", "- 3. 훈련에 사용할 전처리된 파일을 확인\n", "- 4. 모델 빌딩 파이프라인 의 스텝(Step) 생성\n", "- 5. 파리마터, 단계, 조건을 조합하여 최종 파이프라인 정의 및 실행\n", "- 6. 모델 레지스트리에서 모델 등록 확인\n", "- 7. 훈련 아티펙트 경로 추출\n", "\n", "---\n", "### 노트북 커널\n", "- 이 워크샵은 노트북 커널이 `conda_python3` 를 사용합니다. 다른 커널일 경우 변경 해주세요.\n", "---\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. 모델 훈련 및 모델 등록 개요\n", "- 모델 훈련 및 등록 단계의 개발자 가이드 \n", " - [모델 훈련 스텝](https://docs.aws.amazon.com/ko_kr/sagemaker/latest/dg/build-and-manage-steps.html#step-type-training)\n", " - [모델 등록 단계](https://docs.aws.amazon.com/ko_kr/sagemaker/latest/dg/build-and-manage-steps.html#step-type-register-model)\n", " - [모델 레지스트리로 모델 등록 및 배포](https://docs.aws.amazon.com/ko_kr/sagemaker/latest/dg/model-registry.html)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. 기본 라이브러리 로딩\n", "\n", "세이지 메이커 관련 라이브러리를 로딩 합니다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import boto3\n", "import sagemaker\n", "import pandas as pd\n", "import os\n", "\n", "sagemaker_session = sagemaker.session.Session()\n", "role = sagemaker.get_execution_role()\n", "sm_client = boto3.client(\"sagemaker\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.1 노트북 변수 로딩\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "저장된 변수를 확인 합니다." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stored variables and their in-db values:\n", "bucket -> 'sagemaker-us-east-1-051065130547'\n", "claims_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n", "customers_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n", "input_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n", "input_preproc_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n", "project_prefix -> 'sagemaker-webinar-pipeline-advanced'\n", "test_preproc_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n", "train_preproc_data_uri -> 's3://sagemaker-us-east-1-051065130547/sagemaker-w\n" ] } ], "source": [ "%store" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "기존 노트북에서 저장한 변수를 로딩 합니다." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "%store -r" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. 훈련에 사용할 전처리된 파일을 확인\n", "이후에 훈련에서 사용할 S3의 저장된 전처리 데이터를 확인 합니다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2022-03-21 12:16:19 682602 sagemaker-webinar-pipeline-advanced/preporc/train.csv\n" ] } ], "source": [ "! aws s3 ls {train_preproc_data_uri} --recursive" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
fraudvehicle_claimtotal_claim_amountcustomer_agemonths_as_customernum_claims_past_yearnum_insurers_past_5_yearspolicy_deductablepolicy_annual_premiumcustomer_zip...collision_type_missingincident_severity_Majorincident_severity_Minorincident_severity_Totaledauthorities_contacted_Ambulanceauthorities_contacted_Fireauthorities_contacted_Noneauthorities_contacted_Policepolice_report_available_Nopolice_report_available_Yes
008913.66876380513.668763549401750300099207...0010001010
1019746.72439526146.7243954116501750295095632...0001000101
2011652.96991822052.9699185715501750300093203...0010000101
3011260.930936115960.930936398001750300085208...0010001010
4027987.70465231387.704652396001750300091792...0100000110
\n", "

5 rows × 59 columns

\n", "
" ], "text/plain": [ " fraud vehicle_claim total_claim_amount customer_age months_as_customer \\\n", "0 0 8913.668763 80513.668763 54 94 \n", "1 0 19746.724395 26146.724395 41 165 \n", "2 0 11652.969918 22052.969918 57 155 \n", "3 0 11260.930936 115960.930936 39 80 \n", "4 0 27987.704652 31387.704652 39 60 \n", "\n", " num_claims_past_year num_insurers_past_5_years policy_deductable \\\n", "0 0 1 750 \n", "1 0 1 750 \n", "2 0 1 750 \n", "3 0 1 750 \n", "4 0 1 750 \n", "\n", " policy_annual_premium customer_zip ... collision_type_missing \\\n", "0 3000 99207 ... 0 \n", "1 2950 95632 ... 0 \n", "2 3000 93203 ... 0 \n", "3 3000 85208 ... 0 \n", "4 3000 91792 ... 0 \n", "\n", " incident_severity_Major incident_severity_Minor \\\n", "0 0 1 \n", "1 0 0 \n", "2 0 1 \n", "3 0 1 \n", "4 1 0 \n", "\n", " incident_severity_Totaled authorities_contacted_Ambulance \\\n", "0 0 0 \n", "1 1 0 \n", "2 0 0 \n", "3 0 0 \n", "4 0 0 \n", "\n", " authorities_contacted_Fire authorities_contacted_None \\\n", "0 0 1 \n", "1 0 0 \n", "2 0 0 \n", "3 0 1 \n", "4 0 0 \n", "\n", " authorities_contacted_Police police_report_available_No \\\n", "0 0 1 \n", "1 1 0 \n", "2 1 0 \n", "3 0 1 \n", "4 1 1 \n", "\n", " police_report_available_Yes \n", "0 0 \n", "1 1 \n", "2 1 \n", "3 0 \n", "4 0 \n", "\n", "[5 rows x 59 columns]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_prep_df = pd.read_csv(train_preproc_data_uri)\n", "train_prep_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4. 모델 빌딩 파이프라인 의 스텝(Step) 생성\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.1 모델 빌딩 파이프라인 변수 생성\n", "\n", "파이프라인에서 사용할 파이프라인 파라미터를 정의합니다. 파이프라인을 스케줄하고 실행할 때 파라미터를 이용하여 실행조건을 커스마이징할 수 있습니다. 파라미터를 이용하면 파이프라인 실행시마다 매번 파이프라인 정의를 수정하지 않아도 됩니다.\n", "\n", "지원되는 파라미터 타입은 다음과 같습니다:\n", "\n", "* `ParameterString` - 파이썬 타입에서 `str` \n", "* `ParameterInteger` - 파이썬 타입에서 `int` \n", "* `ParameterFloat` - 파이썬 타입에서 `float` \n", "\n", "이들 파라미터를 정의할 때 디폴트 값을 지정할 수 있으며 파이프라인 실행시 재지정할 수도 있습니다. 지정하는 디폴트 값은 파라미터 타입과 일치하여야 합니다.\n", "\n", "본 노트북에서 사용하는 파라미터는 다음과 같습니다.\n", "\n", "* `processing_instance_type` - 프로세싱 작업에서 사용할 `ml.*` 인스턴스 타입 \n", "* `processing_instance_count` - 프로세싱 작업에서 사용할 인스턴스 개수 \n", "* `training_instance_type` - 학습작업에서 사용할 `ml.*` 인스턴스 타입\n", "* `model_approval_status` - 학습된 모델을 CI/CD를 목적으로 등록할 때의 승인 상태 (디폴트는 \"PendingManualApproval\")\n", "* `input_data` - 입력데이터에 대한 S3 버킷 URI\n", "\n", "\n", "\n", "파이프라인의 각 스텝에서 사용할 변수를 파라미터 변수로서 정의 합니다.\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "from sagemaker.workflow.parameters import (\n", " ParameterInteger,\n", " ParameterString,\n", ")\n", "\n", "train_instance_type = ParameterString(\n", " name=\"TrainingInstanceType\",\n", " default_value=\"ml.m5.xlarge\"\n", ")\n", "\n", "\n", "train_instance_count = ParameterInteger(\n", " name=\"TrainInstanceCount\",\n", " default_value=1\n", ")\n", "\n", "model_approval_status = ParameterString(\n", " name=\"ModelApprovalStatus\", default_value=\"PendingManualApproval\"\n", ")\n", "\n", "\n", "input_data = ParameterString(\n", " name=\"InputData\",\n", " default_value=train_preproc_data_uri,\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.2 하이퍼파라미터 세팅" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "기본 XGBoost 하이퍼파라미터 외에 `scale_pos_weight` 는 레이블이 뷸균형이 되어 있을 경우에, 레이블 값의 가중치를 부여하는 파라미터 입니다. 레이블 0, 1 의 비율에 따라 지정합니다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fraud_sum: 131 , non_fraud_sum: 3869, class_weight: 29\n" ] } ], "source": [ "from src.p_utils import get_pos_scale_weight\n", "class_weight = get_pos_scale_weight(train_prep_df, label='fraud')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "hyperparameters = {\n", " \"scale_pos_weight\" : class_weight, \n", " \"max_depth\": \"3\",\n", " \"alpha\" : \"0\", \n", " \"eta\": \"0.3\",\n", " \"min_child_weight\": \"1\",\n", " \"objective\": \"binary:logistic\",\n", " \"num_round\": \"100\",\n", "}\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.3 Estimator 생성\n", "\n", "Estimator 생성시에 인자가 필요 합니다. 주요한 인자만 보겠습니다.\n", "- 사용자 훈련 코드 \"\"xgboost_script.py\"\n", "- 훈련이 끝난 후에 결과인 모델 아티펙트의 경로 \"estimator_output_path\" 지정 합니다. 지정 안할 시에는 디폴트 경로로 저장 됩니다.\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "estimator_output_path: \n", " s3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs\n" ] } ], "source": [ "from sagemaker.xgboost.estimator import XGBoost\n", "\n", "estimator_output_path = f's3://{bucket}/{project_prefix}/training_jobs'\n", "print(\"estimator_output_path: \\n\", estimator_output_path)\n", "\n", "xgb_train = XGBoost(\n", " entry_point = \"xgboost_script.py\",\n", " source_dir = \"src\",\n", " output_path = estimator_output_path,\n", " #code_location = estimator_output_path,\n", " hyperparameters = hyperparameters,\n", " role = role,\n", " instance_count = train_instance_count,\n", " instance_type = train_instance_type,\n", " framework_version = \"1.0-1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.4 모델 훈련 스탭 생성\n", "스텝 생성시에 위에서 생성한 Estimator 입력 및 입력 데이타로서 전처리 데이터가 존재하는 S3 경로를 제공합니다." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from sagemaker.inputs import TrainingInput\n", "from sagemaker.workflow.steps import TrainingStep\n", "\n", "\n", "step_train = TrainingStep(\n", " name=\"Fraud-Advance-Train\",\n", " estimator=xgb_train,\n", " inputs={\n", " \"train\": TrainingInput(\n", " s3_data= input_data,\n", " content_type=\"text/csv\"\n", " ),\n", " },\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.5 모델 등록 스텝\n", "RegisterModel인스턴스를 생성하기 위해 학습단계에서 선언한 Estimator 인스턴스를 사용합니다. 모델 패키지는 재사용가능한 모델 아티팩트의 추상화이며 추론을 위해 필요한 모든 정보를 포함하고 있습니다. 예를 들어, 모델의 Weight가 있는 위치나 추론이미지 등의 설정이 이에 포함됩니다.\n", "\n", "모델 패키지 그룹은 모델 패키지의 집합입니다. 특정 머신러닝 문제를 해결하기 위해 모델 패키지 그룹을 생성하고, 새로운 버전의 모델패키지를 추가할 수 있습니다. 일반적으로 SageMaker pipeline작업이 실행될 때 마다 새로운 버전의 모델패키지를 생성하고 모델패키지그룹에 추가하게 됩니다.\n", "\n", "RegisterModel은 Python SDK에서 Estimator 인스턴스의 register 메소드와 유사합니다.\n", "\n", "구체적으로, TrainingStep으로 정의한 step_train에서 S3ModelArtifacts를 속성을 이용하여 모델을 전달합니다. TrainingStep의 properties에서 활용할 수 있는 속성들은 DescribeTrainingJob 의 응답 오브젝트에 대응됩니다.\n", "\n", "본 노트북에서 사용된 모델패키지 그룹이름은 SageMaker Project와 함께 모델 레지스트리와 CI/CD 작업에서 직접 활용될 수 있습니다.\n", "\n", "- 모델 그룹 리스팅 API: [ListModelPackageGroups](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_ListModelPackageGroups.html) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 모델 그룹 생성\n", "\n", "- 참고\n", " - 모델 그룹 릭스팅 API: [ListModelPackageGroups](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_ListModelPackageGroups.html)\n", " - 모델 지표 등록: [Model Quality Metrics](https://docs.aws.amazon.com/ko_kr/sagemaker/latest/dg/model-monitor-model-quality-metrics.html)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No model group exists\n", "Create model group\n", "ModelPackageGroup Arn : arn:aws:sagemaker:us-east-1:051065130547:model-package-group/sagemaker-webinar-pipeline-advanced\n" ] } ], "source": [ "model_package_group_name = f\"{project_prefix}\"\n", "model_package_group_input_dict = {\n", " \"ModelPackageGroupName\" : model_package_group_name,\n", " \"ModelPackageGroupDescription\" : \"Sample model package group\"\n", "}\n", "response = sm_client.list_model_package_groups(NameContains=model_package_group_name)\n", "if len(response['ModelPackageGroupSummaryList']) == 0:\n", " print(\"No model group exists\")\n", " print(\"Create model group\") \n", " \n", " create_model_pacakge_group_response = sm_client.create_model_package_group(**model_package_group_input_dict)\n", " print('ModelPackageGroup Arn : {}'.format(create_model_pacakge_group_response['ModelPackageGroupArn'])) \n", "else:\n", " print(f\"{model_package_group_name} exitss\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "모델이 모델 레지스트리에 저장될때 \"모델 승인 상태\" 를 \"PendingManualApproval\" 로 지정 합니다." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "model_approval_status = ParameterString(\n", " name=\"ModelApprovalStatus\", default_value=\"PendingManualApproval\"\n", ")\n", "\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "from sagemaker.workflow.step_collections import RegisterModel\n", "\n", "step_register = RegisterModel(\n", " name= f\"Fraud-Advance-RegisterModel\",\n", " estimator=xgb_train,\n", " image_uri= step_train.properties.AlgorithmSpecification.TrainingImage,\n", " model_data= step_train.properties.ModelArtifacts.S3ModelArtifacts, \n", " content_types=[\"text/csv\"],\n", " response_types=[\"text/csv\"],\n", " inference_instances=[\"ml.t2.medium\", \"ml.m5.xlarge\"],\n", " transform_instances=[\"ml.m5.xlarge\"],\n", " model_package_group_name=model_package_group_name,\n", " approval_status=model_approval_status,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5. 파리마터, 단계, 조건을 조합하여 최종 파이프라인 정의 및 실행\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.1 파이프라인 정의\n", "파이프라인 정의시에 아래 3개의 인자를 제공합니다.\n", "- 파이프라인 이름\n", "- 파이프라인 파라미터\n", "- 파이프라인 실험 설정\n", "- 스텝 정의 (여기서는 훈련, 모델 등록 두가지 스텝 임)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from sagemaker.workflow.pipeline import Pipeline\n", "\n", "from sagemaker.workflow.execution_variables import ExecutionVariables\n", "from sagemaker.workflow.pipeline_experiment_config import PipelineExperimentConfig\n", "\n", "\n", "pipeline_name = project_prefix + \"-Train-Register-Step\"\n", "pipeline = Pipeline(\n", " name=pipeline_name,\n", " parameters=[\n", " train_instance_type, \n", " train_instance_count, \n", " input_data,\n", " model_approval_status,\n", " ],\n", " pipeline_experiment_config=PipelineExperimentConfig(\n", " ExecutionVariables.PIPELINE_NAME,\n", " ExecutionVariables.PIPELINE_EXECUTION_ID\n", " ), \n", " steps=[step_train, step_register],\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.2 파이프라인 정의 확인\n", "위에서 정의한 파이프라인 정의는 Json 형식으로 정의 되어 있습니다." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "No finished training job found associated with this estimator. Please make sure this estimator is only used for building workflow config\n" ] }, { "data": { "text/plain": [ "{'Version': '2020-12-01',\n", " 'Metadata': {},\n", " 'Parameters': [{'Name': 'TrainingInstanceType',\n", " 'Type': 'String',\n", " 'DefaultValue': 'ml.m5.xlarge'},\n", " {'Name': 'TrainInstanceCount', 'Type': 'Integer', 'DefaultValue': 1},\n", " {'Name': 'InputData',\n", " 'Type': 'String',\n", " 'DefaultValue': 's3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/preporc/train.csv'},\n", " {'Name': 'ModelApprovalStatus',\n", " 'Type': 'String',\n", " 'DefaultValue': 'PendingManualApproval'}],\n", " 'PipelineExperimentConfig': {'ExperimentName': {'Get': 'Execution.PipelineName'},\n", " 'TrialName': {'Get': 'Execution.PipelineExecutionId'}},\n", " 'Steps': [{'Name': 'Fraud-Advance-Train',\n", " 'Type': 'Training',\n", " 'Arguments': {'AlgorithmSpecification': {'TrainingInputMode': 'File',\n", " 'TrainingImage': '683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-xgboost:1.0-1-cpu-py3'},\n", " 'OutputDataConfig': {'S3OutputPath': 's3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs'},\n", " 'StoppingCondition': {'MaxRuntimeInSeconds': 86400},\n", " 'ResourceConfig': {'InstanceCount': {'Get': 'Parameters.TrainInstanceCount'},\n", " 'InstanceType': {'Get': 'Parameters.TrainingInstanceType'},\n", " 'VolumeSizeInGB': 30},\n", " 'RoleArn': 'arn:aws:iam::051065130547:role/sagemaker-notebook-SageMakerIamRole-13SLYUPDCYIY9',\n", " 'InputDataConfig': [{'DataSource': {'S3DataSource': {'S3DataType': 'S3Prefix',\n", " 'S3Uri': {'Get': 'Parameters.InputData'},\n", " 'S3DataDistributionType': 'FullyReplicated'}},\n", " 'ContentType': 'text/csv',\n", " 'ChannelName': 'train'}],\n", " 'HyperParameters': {'scale_pos_weight': '29',\n", " 'max_depth': '\"3\"',\n", " 'alpha': '\"0\"',\n", " 'eta': '\"0.3\"',\n", " 'min_child_weight': '\"1\"',\n", " 'objective': '\"binary:logistic\"',\n", " 'num_round': '\"100\"',\n", " 'sagemaker_submit_directory': '\"s3://sagemaker-us-east-1-051065130547/sagemaker-xgboost-2022-03-21-12-18-21-232/source/sourcedir.tar.gz\"',\n", " 'sagemaker_program': '\"xgboost_script.py\"',\n", " 'sagemaker_container_log_level': '20',\n", " 'sagemaker_job_name': '\"sagemaker-xgboost-2022-03-21-12-18-21-232\"',\n", " 'sagemaker_region': '\"us-east-1\"'},\n", " 'DebugHookConfig': {'S3OutputPath': 's3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs',\n", " 'CollectionConfigurations': []},\n", " 'ProfilerRuleConfigurations': [{'RuleConfigurationName': 'ProfilerReport-1647865101',\n", " 'RuleEvaluatorImage': '503895931360.dkr.ecr.us-east-1.amazonaws.com/sagemaker-debugger-rules:latest',\n", " 'RuleParameters': {'rule_to_invoke': 'ProfilerReport'}}],\n", " 'ProfilerConfig': {'S3OutputPath': 's3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs'}}},\n", " {'Name': 'Fraud-Advance-RegisterModel',\n", " 'Type': 'RegisterModel',\n", " 'Arguments': {'ModelPackageGroupName': 'sagemaker-webinar-pipeline-advanced',\n", " 'InferenceSpecification': {'Containers': [{'Image': {'Get': 'Steps.Fraud-Advance-Train.AlgorithmSpecification.TrainingImage'},\n", " 'ModelDataUrl': {'Get': 'Steps.Fraud-Advance-Train.ModelArtifacts.S3ModelArtifacts'}}],\n", " 'SupportedContentTypes': ['text/csv'],\n", " 'SupportedResponseMIMETypes': ['text/csv'],\n", " 'SupportedRealtimeInferenceInstanceTypes': ['ml.t2.medium',\n", " 'ml.m5.xlarge'],\n", " 'SupportedTransformInstanceTypes': ['ml.m5.xlarge']},\n", " 'ModelApprovalStatus': {'Get': 'Parameters.ModelApprovalStatus'}}}]}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import json\n", "\n", "definition = json.loads(pipeline.definition())\n", "definition" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.3 파이프라인 정의를 제출하고 실행하기 \n", "\n", "파이프라인 정의를 파이프라인 서비스에 제출합니다. 함께 전달되는 역할(role)을 이용하여 AWS에서 파이프라인을 생성하고 작업의 각 단계를 실행할 것입니다. " ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "No finished training job found associated with this estimator. Please make sure this estimator is only used for building workflow config\n" ] } ], "source": [ "pipeline.upsert(role_arn=role)\n", "execution = pipeline.start()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "워크플로우의 실행상황을 살펴봅니다. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'PipelineArn': 'arn:aws:sagemaker:us-east-1:051065130547:pipeline/sagemaker-webinar-pipeline-advanced-train-register-step',\n", " 'PipelineExecutionArn': 'arn:aws:sagemaker:us-east-1:051065130547:pipeline/sagemaker-webinar-pipeline-advanced-train-register-step/execution/twg45ptdqzid',\n", " 'PipelineExecutionDisplayName': 'execution-1647865102041',\n", " 'PipelineExecutionStatus': 'Executing',\n", " 'CreationTime': datetime.datetime(2022, 3, 21, 12, 18, 21, 973000, tzinfo=tzlocal()),\n", " 'LastModifiedTime': datetime.datetime(2022, 3, 21, 12, 18, 21, 973000, tzinfo=tzlocal()),\n", " 'CreatedBy': {},\n", " 'LastModifiedBy': {},\n", " 'ResponseMetadata': {'RequestId': '77ca2c6b-9227-4d47-ba86-6271ccb4273d',\n", " 'HTTPStatusCode': 200,\n", " 'HTTPHeaders': {'x-amzn-requestid': '77ca2c6b-9227-4d47-ba86-6271ccb4273d',\n", " 'content-type': 'application/x-amz-json-1.1',\n", " 'content-length': '475',\n", " 'date': 'Mon, 21 Mar 2022 12:18:22 GMT'},\n", " 'RetryAttempts': 0}}" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "execution.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.4 파이프라인 실행 기다리기" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "execution.wait()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "실행이 완료될 때까지 기다립니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "실행된 단계들을 리스트업합니다. 파이프라인의 단계실행 서비스에 의해 시작되거나 완료된 단계를 보여줍니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.5 파이프라인 실행 단계 기록 보기" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'StepName': 'Fraud-Advance-RegisterModel',\n", " 'StartTime': datetime.datetime(2022, 3, 21, 12, 22, 18, 126000, tzinfo=tzlocal()),\n", " 'EndTime': datetime.datetime(2022, 3, 21, 12, 22, 18, 911000, tzinfo=tzlocal()),\n", " 'StepStatus': 'Succeeded',\n", " 'AttemptCount': 0,\n", " 'Metadata': {'RegisterModel': {'Arn': 'arn:aws:sagemaker:us-east-1:051065130547:model-package/sagemaker-webinar-pipeline-advanced/1'}}},\n", " {'StepName': 'Fraud-Advance-Train',\n", " 'StartTime': datetime.datetime(2022, 3, 21, 12, 18, 22, 915000, tzinfo=tzlocal()),\n", " 'EndTime': datetime.datetime(2022, 3, 21, 12, 22, 17, 727000, tzinfo=tzlocal()),\n", " 'StepStatus': 'Succeeded',\n", " 'AttemptCount': 0,\n", " 'Metadata': {'TrainingJob': {'Arn': 'arn:aws:sagemaker:us-east-1:051065130547:training-job/pipelines-twg45ptdqzid-fraud-advance-train-lzwnxozdeb'}}}]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "execution.list_steps()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5.6 세이지 메이커 스튜디오에서 확인하기\n", "아래의 세가지의 스크린 샷은 다음과 같습니다.\n", "- 파이프라인의 실형 한 내역 입니다. 같은 파이프라인을 4번 실행한 것을 확인 됩니다.\n", "- 파이프라인에 입력 파라미터로 제공된 것을 확인합니다.\n", "- 두 개의 스텝으로 이루어진 파이프라인 그래프을 확인할 수 있습니다.\n", "\n", "![pipeline-train-register.png](img/pipeline-train-register.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 6. 모델 레지스트리에서 모델 등록 확인\n", "위에서 등록한 모델 그룹 이름을 통해서 어떤 모델이 등록되었는지를 확인 합니다.\n", "- 등록된 모델 버전에 대한 보기 --> [모델 버전의 세부 정보 보기](https://docs.aws.amazon.com/ko_kr/sagemaker/latest/dg/model-registry-details.html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6.1 세이지 메이커 스튜디오에서 모델 레지스트리 확인\n", "세이지 메이커 스튜디오에 로그인해서 확인이 가능합니다.\n", "- 아래는 \"sagemaker-webinar-pipeline-advanced' 라는 모델 그룹에 4개의 모델 버전이 등록 되어 있는 것을 보여 주고 있습니다.\n", "- Version 4 의 모델 상세 내역을 확인 합니다.\n", "\n", "![model-registry.png](img/model-registry.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6.2 SageMaker Python SDK 로 모델 레지스트리 내용 학인 " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ModelPackageSummaryList': [{'ModelPackageGroupName': 'sagemaker-webinar-pipeline-advanced',\n", " 'ModelPackageVersion': 1,\n", " 'ModelPackageArn': 'arn:aws:sagemaker:us-east-1:051065130547:model-package/sagemaker-webinar-pipeline-advanced/1',\n", " 'CreationTime': datetime.datetime(2022, 3, 21, 12, 22, 18, 810000, tzinfo=tzlocal()),\n", " 'ModelPackageStatus': 'Completed',\n", " 'ModelApprovalStatus': 'PendingManualApproval'}],\n", " 'ResponseMetadata': {'RequestId': 'b5a85c71-80c3-40c5-b117-fbc16d719f25',\n", " 'HTTPStatusCode': 200,\n", " 'HTTPHeaders': {'x-amzn-requestid': 'b5a85c71-80c3-40c5-b117-fbc16d719f25',\n", " 'content-type': 'application/x-amz-json-1.1',\n", " 'content-length': '340',\n", " 'date': 'Mon, 21 Mar 2022 12:22:22 GMT'},\n", " 'RetryAttempts': 0}}" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 위에서 생성한 model_package_group_name 을 인자로 제공 합니다.\n", "response = sm_client.list_model_packages(ModelPackageGroupName= model_package_group_name)\n", "response" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 등록된 모델 버전의 상세 정보 확인" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ModelPackageGroupName': 'sagemaker-webinar-pipeline-advanced',\n", " 'ModelPackageVersion': 1,\n", " 'ModelPackageArn': 'arn:aws:sagemaker:us-east-1:051065130547:model-package/sagemaker-webinar-pipeline-advanced/1',\n", " 'CreationTime': datetime.datetime(2022, 3, 21, 12, 22, 18, 810000, tzinfo=tzlocal()),\n", " 'InferenceSpecification': {'Containers': [{'Image': '683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-xgboost:1.0-1-cpu-py3',\n", " 'ImageDigest': 'sha256:04889b02181f14632e19ef6c2a7d74bfe699ff4c7f44669a78834bc90b77fe5a',\n", " 'ModelDataUrl': 's3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs/pipelines-twg45ptdqzid-Fraud-Advance-Train-lzWNxOzDEB/output/model.tar.gz'}],\n", " 'SupportedTransformInstanceTypes': ['ml.m5.xlarge'],\n", " 'SupportedRealtimeInferenceInstanceTypes': ['ml.t2.medium', 'ml.m5.xlarge'],\n", " 'SupportedContentTypes': ['text/csv'],\n", " 'SupportedResponseMIMETypes': ['text/csv']},\n", " 'ModelPackageStatus': 'Completed',\n", " 'ModelPackageStatusDetails': {'ValidationStatuses': [],\n", " 'ImageScanStatuses': []},\n", " 'CertifyForMarketplace': False,\n", " 'ModelApprovalStatus': 'PendingManualApproval',\n", " 'MetadataProperties': {'GeneratedBy': 'arn:aws:sagemaker:us-east-1:051065130547:pipeline/sagemaker-webinar-pipeline-advanced-train-register-step/execution/twg45ptdqzid'},\n", " 'ResponseMetadata': {'RequestId': '6fa73db5-459f-4b8e-9709-6f9e0b75e113',\n", " 'HTTPStatusCode': 200,\n", " 'HTTPHeaders': {'x-amzn-requestid': '6fa73db5-459f-4b8e-9709-6f9e0b75e113',\n", " 'content-type': 'application/x-amz-json-1.1',\n", " 'content-length': '1187',\n", " 'date': 'Mon, 21 Mar 2022 12:22:22 GMT'},\n", " 'RetryAttempts': 0}}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ModelPackageArn = response['ModelPackageSummaryList'][0]['ModelPackageArn']\n", "sm_client.describe_model_package(ModelPackageName=ModelPackageArn)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 7 훈련 아티펙트 경로 추출\n", "\n", "위의 훈련 스텝이 완료되면 실행해주세요" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " train_model_artifact: s3://sagemaker-us-east-1-051065130547/sagemaker-webinar-pipeline-advanced/training_jobs/pipelines-twg45ptdqzid-Fraud-Advance-Train-lzWNxOzDEB/output/model.tar.gz\n" ] } ], "source": [ "from src.p_utils import get_train_artifact\n", " \n", "train_model_artifact = get_train_artifact(execution, sm_client,job_type='TrainingJob', kind=0)\n", "print(\" train_model_artifact: \", train_model_artifact)\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "image_uri = xgb_train.image_uri" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "훈련 모델 아티펙트와, 훈련시 사용한 다커 이미지의 경로를 저장 합니다." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stored 'train_model_artifact' (str)\n", "Stored 'image_uri' (str)\n" ] } ], "source": [ "%store train_model_artifact\n", "%store image_uri" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "instance_type": "ml.m5.large", "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.13" }, "toc-autonumbering": false, "toc-showcode": false, "toc-showmarkdowntxt": false, "toc-showtags": false }, "nbformat": 4, "nbformat_minor": 4 }