사전 빌드 컨테이너 확장 - Amazon SageMaker

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

사전 빌드 컨테이너 확장

사전 빌드된 SageMaker 컨테이너가 모든 요구 사항을 충족하지 못하는 경우 기존 이미지를 확장하여 요구 사항을 충족할 수 있습니다. 환경 또는 프레임워크에 대한 직접적인 지원이 있더라도 다른 기능을 추가하거나 컨테이너 환경을 다르게 구성해야 할 수 있습니다. 사전 빌드 이미지를 확장하면 이미지를 처음부터 새로 생성할 필요 없이 포함된 딥 러닝 라이브러리 및 설정을 사용할 수 있습니다. 컨테이너를 확장하여 라이브러리를 추가하고, 설정을 수정하고, 추가 종속성 항목을 설치할 수 있습니다.

다음 자습서는 사전 빌드된 SageMaker 이미지를 확장하여 Amazon ECR에 게시하는 방법을 보여줍니다.

사전 빌드 컨테이너를 확장하기 위한 요건

사전 빌드된 SageMaker 이미지를 확장하려면 Dockerfile 내에 다음 환경 변수를 설정해야 합니다. SageMaker컨테이너를 사용한 환경 변수에 대한 자세한 내용은 Training Toolkit 리포지토리를 참조하십시오. SageMaker GitHub

  • SAGEMAKER_SUBMIT_DIRECTORY: 훈련용 Python 스크립트가 있는 컨테이너 내부의 디렉터리입니다.

  • SAGEMAKER_PROGRAM: 호출하여 훈련의 진입점으로 사용해야 하는 Python 스크립트입니다.

다음 항목을 포함시켜 추가 라이브러리를 Dockerfile에 설치할 수도 있습니다.

RUN pip install <library>

다음 튜토리얼에서는 이들 환경 변수를 사용하는 방법을 보여줍니다.

Python 스크립트를 실행하도록 SageMaker 컨테이너 확장하기

이 자습서에서는 CIFAR-10 데이터세트를 사용하는 Python 파일로 SageMaker PyTorch 컨테이너를 확장하는 방법을 알아봅니다. SageMaker PyTorch 컨테이너를 확장하면 사용할 수 있도록 만들어진 기존 교육 솔루션을 활용할 수 있습니다. SageMaker 이 튜토리얼에서는 훈련 이미지를 확장하지만, 동일한 단계를 수행하여 추론 이미지를 확장할 수도 있습니다. 사용 가능한 이미지의 전체 목록은 사용 가능한 딥 러닝 컨테이너 이미지를 참조하세요.

SageMaker 컨테이너를 사용하여 자체 교육 모델을 실행하려면 SageMaker Notebook 인스턴스를 통해 Docker 컨테이너를 빌드하세요.

1단계: SageMaker 노트북 인스턴스 생성

  1. SageMaker 콘솔을 엽니다.

  2. 왼쪽 탐색 창에서 노트북을 선택하고 노트북 인스턴스를 선택한 다음 노트북 인스턴스 생성을 선택하세요.

  3. 노트북 인스턴스 생성 페이지에서 다음 정보를 입력합니다.

    1. 노트북 인스턴스 이름RunScriptNotebookInstance를 입력합니다.

    2. 노트북 인스턴스 유형에서 ml.t2.medium을 선택합니다.

    3. 권한 및 암호화 섹션에서 다음 방법대로 하세요.

      1. IAM 역할에서 새 역할 생성을 선택합니다.

      2. IAM 역할 생성 페이지에서 특정 S3 버킷을 선택하고 sagemaker-run-script라는 이름의 Amazon S3 버킷을 지정한 다음 역할 생성을 선택하세요.

        SageMaker 와 같은 AmazonSageMaker-ExecutionRole-20190429T110788 이름의 AmazonSageMaker-ExecutionRole-YYYYMMDDTHHmmSS IAM 역할을 생성합니다. 실행 역할 명명 규칙에서는 역할이 생성된 날짜 및 시간을 T로 구분하여 사용합니다.

    4. 루트 액세스에서 활성화를 선택하세요.

    5. 노트북 인스턴스 생성을 선택합니다.

  4. 노트북 인스턴스 페이지에서 상태대기 중으로 표시됩니다. Amazon CloudWatch Internet Monitor가 기계 학습 컴퓨팅 인스턴스 (이 경우에는 노트북 인스턴스 시작) 를 시작하고 여기에 ML 스토리지 볼륨을 연결하는 데 몇 분 정도 걸릴 수 있습니다. 노트북 인스턴스에는 사전 구성된 Jupyter 노트북 서버와 Anaconda 라이브러리 세트가 있습니다. 자세한 내용은 을 참조하십시오. CreateNotebookInstance.

  5. 권한 및 암호화 섹션에서 IAM 역할 ARN 번호를 복사한 다음, 해당 번호를 메모장 파일에 붙여 넣어 임시로 저장하세요. 나중에 이 IAM 역할 ARN 번호를 사용하여 노트북 인스턴스에서 로컬 훈련 예측기를 구성해야 합니다. IAM 역할 ARN 번호'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'과 같습니다.

  6. 노트북 인스턴스의 상태가 로 변경되면 InServiceOpen을 선택합니다 JupyterLab.

2단계: Dockerfile 및 Python 훈련 스크립트 생성 및 업로드

  1. JupyterLab 폴더를 연 후에는 홈 디렉토리에 새 폴더를 만드십시오 JupyterLab. 왼쪽 상단에서 새 폴더 아이콘을 선택한 다음 폴더 이름 docker_test_folder을 입력하세요.

  2. docker_test_folder 디렉터리에서 Dockerfile 텍스트 파일을 생성하세요.

    1. 왼쪽 상단에서 새 런처 아이콘(+)을 선택하세요.

    2. 오른쪽 창의 기타 섹션에서 텍스트 파일을 선택하세요.

    3. 다음 Dockerfile 샘플 코드를 텍스트 파일에 붙여 넣으세요.

      # SageMaker PyTorch image FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04 ENV PATH="/opt/ml/code:${PATH}" # this environment variable is used by the SageMaker PyTorch container to determine our user code directory. ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code # /opt/ml and all subdirectories are utilized by SageMaker, use the /code subdirectory to store your user code. COPY cifar10.py /opt/ml/code/cifar10.py # Defines cifar10.py as script entrypoint ENV SAGEMAKER_PROGRAM cifar10.py

      이 Dockerfile 스크립트는 다음 작업을 수행합니다.

      • FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04— SageMaker PyTorch 기본 이미지를 다운로드합니다. 이 이미지를 컨테이너 빌드에 가져오려는 SageMaker 기본 이미지로 바꿀 수 있습니다.

      • ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code/opt/ml/code을(를) 훈련 스크립트 디렉터리로 설정합니다.

      • COPY cifar10.py /opt/ml/code/cifar10.py— 에서 예상한 컨테이너 내부 위치에 스크립트를 SageMaker 복사합니다. 스크립트는 이 폴더에 있어야 합니다.

      • ENV SAGEMAKER_PROGRAM cifar10.pycifar10.py 훈련 스크립트를 진입점 스크립트로 설정합니다.

    4. 왼쪽 디렉터리 탐색 창에서 텍스트 파일 이름을 untitled.txt(으)로 자동 지정할 수 있습니다. 파일 이름을 변경하려면 해당 파일을 마우스 오른쪽 버튼으로 클릭하고 이름 변경을 선택한 다음, 파일 이름을 .txt 확장자가 없는 Dockerfile(으)로 변경하고 Ctrl+s 또는 Command+s을(를) 눌러 파일을 저장하세요.

  3. docker_test_folder에서 훈련 스크립트 cifar10.py을(를) 생성하거나 업로드하세요. 이 연습에서는 다음 예제 스크립트를 사용할 수 있습니다.

    import ast import argparse import logging import os import torch import torch.distributed as dist import torch.nn as nn import torch.nn.parallel import torch.optim import torch.utils.data import torch.utils.data.distributed import torchvision import torchvision.models import torchvision.transforms as transforms import torch.nn.functional as F logger=logging.getLogger(__name__) logger.setLevel(logging.DEBUG) classes=('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') # https://github.com/pytorch/tutorials/blob/master/beginner_source/blitz/cifar10_tutorial.py#L118 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1=nn.Conv2d(3, 6, 5) self.pool=nn.MaxPool2d(2, 2) self.conv2=nn.Conv2d(6, 16, 5) self.fc1=nn.Linear(16 * 5 * 5, 120) self.fc2=nn.Linear(120, 84) self.fc3=nn.Linear(84, 10) def forward(self, x): x=self.pool(F.relu(self.conv1(x))) x=self.pool(F.relu(self.conv2(x))) x=x.view(-1, 16 * 5 * 5) x=F.relu(self.fc1(x)) x=F.relu(self.fc2(x)) x=self.fc3(x) return x def _train(args): is_distributed=len(args.hosts) > 1 and args.dist_backend is not None logger.debug("Distributed training - {}".format(is_distributed)) if is_distributed: # Initialize the distributed environment. world_size=len(args.hosts) os.environ['WORLD_SIZE']=str(world_size) host_rank=args.hosts.index(args.current_host) dist.init_process_group(backend=args.dist_backend, rank=host_rank, world_size=world_size) logger.info( 'Initialized the distributed environment: \'{}\' backend on {} nodes. '.format( args.dist_backend, dist.get_world_size()) + 'Current host rank is {}. Using cuda: {}. Number of gpus: {}'.format( dist.get_rank(), torch.cuda.is_available(), args.num_gpus)) device='cuda' if torch.cuda.is_available() else 'cpu' logger.info("Device Type: {}".format(device)) logger.info("Loading Cifar10 dataset") transform=transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset=torchvision.datasets.CIFAR10(root=args.data_dir, train=True, download=False, transform=transform) train_loader=torch.utils.data.DataLoader(trainset, batch_size=args.batch_size, shuffle=True, num_workers=args.workers) testset=torchvision.datasets.CIFAR10(root=args.data_dir, train=False, download=False, transform=transform) test_loader=torch.utils.data.DataLoader(testset, batch_size=args.batch_size, shuffle=False, num_workers=args.workers) logger.info("Model loaded") model=Net() if torch.cuda.device_count() > 1: logger.info("Gpu count: {}".format(torch.cuda.device_count())) model=nn.DataParallel(model) model=model.to(device) criterion=nn.CrossEntropyLoss().to(device) optimizer=torch.optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum) for epoch in range(0, args.epochs): running_loss=0.0 for i, data in enumerate(train_loader): # get the inputs inputs, labels=data inputs, labels=inputs.to(device), labels.to(device) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs=model(inputs) loss=criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 2000 == 1999: # print every 2000 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss=0.0 print('Finished Training') return _save_model(model, args.model_dir) def _save_model(model, model_dir): logger.info("Saving the model.") path=os.path.join(model_dir, 'model.pth') # recommended way from http://pytorch.org/docs/master/notes/serialization.html torch.save(model.cpu().state_dict(), path) def model_fn(model_dir): logger.info('model_fn') device="cuda" if torch.cuda.is_available() else "cpu" model=Net() if torch.cuda.device_count() > 1: logger.info("Gpu count: {}".format(torch.cuda.device_count())) model=nn.DataParallel(model) with open(os.path.join(model_dir, 'model.pth'), 'rb') as f: model.load_state_dict(torch.load(f)) return model.to(device) if __name__ == '__main__': parser=argparse.ArgumentParser() parser.add_argument('--workers', type=int, default=2, metavar='W', help='number of data loading workers (default: 2)') parser.add_argument('--epochs', type=int, default=2, metavar='E', help='number of total epochs to run (default: 2)') parser.add_argument('--batch-size', type=int, default=4, metavar='BS', help='batch size (default: 4)') parser.add_argument('--lr', type=float, default=0.001, metavar='LR', help='initial learning rate (default: 0.001)') parser.add_argument('--momentum', type=float, default=0.9, metavar='M', help='momentum (default: 0.9)') parser.add_argument('--dist-backend', type=str, default='gloo', help='distributed backend (default: gloo)') # The parameters below retrieve their default values from SageMaker environment variables, which are # instantiated by the SageMaker containers framework. # https://github.com/aws/sagemaker-containers#how-a-script-is-executed-inside-the-container parser.add_argument('--hosts', type=str, default=ast.literal_eval(os.environ['SM_HOSTS'])) parser.add_argument('--current-host', type=str, default=os.environ['SM_CURRENT_HOST']) parser.add_argument('--model-dir', type=str, default=os.environ['SM_MODEL_DIR']) parser.add_argument('--data-dir', type=str, default=os.environ['SM_CHANNEL_TRAINING']) parser.add_argument('--num-gpus', type=int, default=os.environ['SM_NUM_GPUS']) _train(parser.parse_args())

3단계: 컨테이너 빌드

  1. JupyterLab 홈 디렉터리에서 Jupyter 노트북을 엽니다. 새 노트북을 열려면 새로 시작 아이콘을 선택한 다음 노트북 섹션에서 conda_pytorch_p39를 선택하세요.

  2. docker_test_folder 디렉터리로 변경하려면 첫 번째 노트북 셀에서 다음 명령을 실행하세요.

    % cd ~/SageMaker/docker_test_folder

    그러면 현재 디렉터리가 다음과 같이 반환됩니다.

    ! pwd

    output: /home/ec2-user/SageMaker/docker_test_folder

  3. Docker에 로그인하여 기본 컨테이너에 액세스하는 방법:

    ! aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com
  4. Docker 컨테이너를 빌드하려면 다음 Docker 빌드 명령(한 칸 띄어 쓴 후 맨 끝에 마침표를 찍음)을 실행하세요.

    ! docker build -t pytorch-extended-container-test .

    Docker 빌드 명령은 생성한 Docker 디렉터리(이 경우에는 docker_test_folder)에서 실행해야 합니다.

    참고

    Docker가 Dockerfile을 찾을 수 없다는 내용의 다음 오류 메시지가 나타날 경우, Dockerfile의 이름이 정확하고 해당 디렉터리에 저장되었는지 확인하세요.

    unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /home/ec2-user/SageMaker/docker/Dockerfile: no such file or directory

    docker이(가) 현재 디렉터리 내에서 어떤 확장자도 없이 특별히 호출된 Dockerfile 파일을 찾는다는 점을 기억해 두세요. 다른 이름을 지정한 경우에는 -f 플래그로 파일 이름을 수동으로 전달할 수 있습니다. 예를 들어 Dockerfile 이름을 Dockerfile-text.txt(으)로 지정한 경우, 다음 명령을 실행하세요.

    ! docker build -t tf-custom-container-test -f Dockerfile-text.txt .

4단계: 컨테이너 테스트

  1. 노트북 인스턴스에서 컨테이너를 로컬로 테스트하려면 Jupyter 노트북을 여세요. 새 런처를 선택하고 conda_pytorch_p39 프레임워크에서 노트북을 선택하세요. 나머지 코드 조각은 Jupyter 노트북 인스턴스에서 실행해야 합니다.

  2. CIFAR-10 데이터 세트를 다운로드하세요.

    import torch import torchvision import torchvision.transforms as transforms def _get_transform(): return transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) def get_train_data_loader(data_dir='/tmp/pytorch/cifar-10-data'): transform=_get_transform() trainset=torchvision.datasets.CIFAR10(root=data_dir, train=True, download=True, transform=transform) return torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) def get_test_data_loader(data_dir='/tmp/pytorch/cifar-10-data'): transform=_get_transform() testset=torchvision.datasets.CIFAR10(root=data_dir, train=False, download=True, transform=transform) return torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2) trainloader=get_train_data_loader('/tmp/pytorch-example/cifar-10-data') testloader=get_test_data_loader('/tmp/pytorch-example/cifar-10-data')
  3. role을(를) Jupyter 노트북 생성에 사용할 역할로 설정하세요. 이는 에스티메이터를 구성하는 데 SageMaker 사용됩니다.

    from sagemaker import get_execution_role role=get_execution_role()
  4. 다음 예제 스크립트를 노트북 코드 셀에 붙여넣어 확장 컨테이너를 사용하여 SageMaker Estimator를 구성하십시오.

    from sagemaker.estimator import Estimator hyperparameters={'epochs': 1} estimator=Estimator( image_uri='pytorch-extended-container-test', role=role, instance_count=1, instance_type='local', hyperparameters=hyperparameters ) estimator.fit('file:///tmp/pytorch-example/cifar-10-data')
  5. 코드 셀을 실행합니다. 이 테스트는 훈련 환경 구성, 환경 변수에 사용된 값, 데이터 소스, 훈련 과정에서 얻은 손실 및 정확성을 출력합니다.

5단계: Amazon ECR(Amazon Elastic Container Registry)로 컨테이너 푸시

  1. 로컬 모드 테스트를 실행한 후에는 Docker 컨테이너를 Amazon ECR로 푸시한 다음, 해당 컨테이터를 사용해 훈련 작업을 실행할 수 있습니다.

    노트북 셀에서 다음 명령줄을 실행하세요.

    %%sh # Specify an algorithm name algorithm_name=pytorch-extended-container-test account=$(aws sts get-caller-identity --query Account --output text) # Get the region defined in the current configuration (default to us-west-2 if none defined) region=$(aws configure get region) fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest" # If the repository doesn't exist in ECR, create it. aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1 if [ $? -ne 0 ] then aws ecr create-repository --repository-name "${algorithm_name}" > /dev/null fi # Log into Docker aws ecr get-login-password --region ${region}|docker login --username AWS --password-stdin ${fullname} # Build the docker image locally with the image name and then push it to ECR # with the full name. docker build -t ${algorithm_name} . docker tag ${algorithm_name} ${fullname} docker push ${fullname}
  2. 컨테이너를 푸시하고 나면 SageMaker 환경 어디에서든 Amazon ECR 이미지를 호출할 수 있습니다. 이 다음의 노트북 셀에서 다음 코드 예제를 실행하세요.

    SageMaker Studio에서 이 교육 컨테이너를 사용하여 시각화 기능을 사용하려면 Studio 노트북 셀에서 다음 코드를 실행하여 교육 컨테이너의 Amazon ECR 이미지를 호출할 수도 있습니다.

    import boto3 client=boto3.client('sts') account=client.get_caller_identity()['Account'] my_session=boto3.session.Session() region=my_session.region_name algorithm_name="pytorch-extended-container-test" ecr_image='{}.dkr.ecr.{}.amazonaws.com/{}:latest'.format(account, region, algorithm_name) ecr_image # This should return something like # 12-digits-of-your-account.dkr.ecr.us-east-2.amazonaws.com/tf-2.2-test:latest
  3. 이전 단계에서 ecr_image 검색한 코드를 사용하여 SageMaker Estimator 객체를 구성합니다. 다음 코드 샘플은 추정기를 구성합니다. SageMaker PyTorch

    import sagemaker from sagemaker import get_execution_role from sagemaker.estimator import Estimator estimator=Estimator( image_uri=ecr_image, role=get_execution_role(), base_job_name='pytorch-extended-container-test', instance_count=1, instance_type='ml.p2.xlarge' ) # start training estimator.fit() # deploy the trained model predictor=estimator.deploy(1, instance_type)

6단계: 리소스 정리

시작 예제 완료 시 리소스를 정리하는 방법:
  1. SageMaker 콘솔을 열고 노트북 인스턴스를 RunScriptNotebookInstance선택한 다음 Actions를 선택하고 Stop을 선택합니다. 인스턴스가 중지하는 데 몇 분 정도 걸릴 수 있습니다.

  2. 인스턴스 상태중지됨으로 변경되고 나면 작업을 선택하고 삭제를 선택한 다음, 대화 상자에서 삭제를 선택하세요. 이 인스턴스가 삭제되기까지는 몇 분 정도 걸릴 수 있습니다. 이 노트북 인스턴스가 삭제되면 표에서도 사라집니다.

  3. Amazon S3 콘솔을 열고 모델 아티팩트 및 훈련 데이터 세트를 저장하기 위해 생성한 버킷을 삭제하세요.

  4. IAM 콘솔을 열고 IAM 역할을 삭제하세요. 권한 정책을 생성한 경우 역시 삭제할 수 있습니다.

    참고

    Docker 컨테이너는 실행 후 자동으로 종료됩니다. 삭제할 필요는 없습니다.