Estenda uma imagem de contêiner predefinida - Amazon SageMaker

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Estenda uma imagem de contêiner predefinida

Se um SageMaker contêiner pré-construído não atender a todos os seus requisitos, você poderá estender a imagem existente para acomodar suas necessidades. Mesmo que haja suporte direto para seu ambiente ou estrutura, talvez você queira adicionar mais funcionalidades ou configurar seu ambiente de contêiner de forma diferente. Quando estender uma imagem predefinida, você pode aproveitar as bibliotecas e configurações de aprendizado profundo incluídas sem precisar criar uma imagem do zero. Estenda o contêiner para adicionar bibliotecas, modificar configurações e instalar dependências adicionais.

O tutorial a seguir mostra como estender uma SageMaker imagem pré-criada e publicá-la no Amazon ECR.

Requisitos para estender um contêiner predefinido

Para estender uma SageMaker imagem pré-criada, você precisa definir as seguintes variáveis de ambiente em seu Dockerfile. Para obter mais informações sobre variáveis de ambiente com SageMaker contêineres, consulte o repositório do SageMaker Training Toolkit GitHub .

  • SAGEMAKER_SUBMIT_DIRECTORY: o diretório dentro do contêiner no qual o script Python para treinamento está localizado.

  • SAGEMAKER_PROGRAM: O script Python que deve ser invocado e usado como ponto de entrada no treinamento.

Você também pode instalar mais bibliotecas incluindo o seguinte em seu Dockerfile:

RUN pip install <library>

O tutorial a seguir mostra como usar essas variáveis de ambiente.

Estender SageMaker contêineres para executar um script Python

Neste tutorial, você aprende a estender o SageMaker PyTorch contêiner com um arquivo Python que usa o conjunto de dados CIFAR-10. Ao estender o SageMaker PyTorch contêiner, você utiliza a solução de treinamento existente, feita para trabalhar com SageMaker ela. Este tutorial estende uma imagem de treinamento, mas as mesmas etapas podem ser tomadas para estender uma imagem de inferência. Para obter uma lista completa das imagens disponíveis, consulte Imagens de contêineres de aprendizado profundo.

Para executar seu próprio modelo de treinamento usando os SageMaker contêineres, crie um contêiner Docker por meio de uma instância do SageMaker Notebook.

Etapa 1: criar uma instância de SageMaker notebook

  1. Abra o console de SageMaker .

  2. No painel de navegação, escolha Caderno, e depois Instâncias do caderno e selecione Criar instância de cadernos.

  3. Na página Create notebook instance (Criar instância de bloco de anotações), forneça as seguintes informações:

    1. Para Notebook instance name (Nome da instância de bloco de anotações), insira RunScriptNotebookInstance.

    2. Em Notebook Instance type (Tipo de instância de bloco de anotações), escolha ml.t2.medium.

    3. Na seção Permissões e criptografia) e faça o seguinte:

      1. Em Perfil do IAM, selecione Criar uma nova função.

      2. Na página Create an IAM role (Criar uma função do IAM), escolha Specific S3 buckets (Buckets do S3 específicos), especifique um bucket do Amazon S3 chamado sagemaker-run-script e depois escolha Create role (Criar função).

        SageMaker cria uma função do IAM chamadaAmazonSageMaker-ExecutionRole-YYYYMMDDTHHmmSS, comoAmazonSageMaker-ExecutionRole-20190429T110788. Observe que a convenção de nomenclatura de função de execução usa a data e a hora em que a função foi criada, separada por um T.

    4. Em Root Access (Acesso raiz), escolha Enable (Habilitar).

    5. Escolha Create notebook instance (Criar instância de bloco de anotações).

  4. Na página de Instâncias de cadernos, o status é Pendente. Pode levar alguns minutos para o Amazon CloudWatch Internet Monitor iniciar uma instância computacional de aprendizado de máquina — nesse caso, ele inicia uma instância de notebook — e anexa um volume de armazenamento de ML a ela. A instância de caderno conta com a pré-configuração de um servidor de cadernos Jupyter e de um conjunto de bibliotecas da Anaconda. Para obter mais informações, consulte CreateNotebookInstance.

  5. Na seção Permissões e criptografia, copie o número ARN da função do IAM e cole-o em um arquivo dos cadernos para salvá-lo temporariamente. Posteriormente, você usa esse número ARN da função do IAM para configurar um estimador de treinamento local na instância de cadernos. The IAM role ARN number (O número do ARN da função do IAM) é semelhante ao seguinte: 'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'

  6. Depois que o status da instância do notebook mudar para InService, escolha Abrir JupyterLab.

Etapa 2: Como criar e fazer upload do Dockerfile e dos scripts de treinamento do Python

  1. Depois de JupyterLab abrir, crie uma nova pasta no diretório inicial do seu JupyterLab. No canto superior esquerdo, escolha o ícone Nova pasta e insira o nome da pasta docker_test_folder.

  2. Crie um arquivo de texto Dockerfile no diretório docker_test_folder.

    1. Escolha o ícone Novo inicializador (+) no canto superior esquerdo.

    2. No painel à direita, na seção Outro, selecione Arquivo de texto.

    3. Cole o código de amostra Dockerfile a seguir no seu arquivo de texto.

      # 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

      O script do Dockerfile executa as seguintes tarefas:

      • FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04— Faz o download SageMaker PyTorch da imagem base. Você pode substituí-la por qualquer imagem SageMaker base que queira trazer para criar contêineres.

      • ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code – Define /opt/ml/code como o diretório do script de treinamento.

      • COPY cifar10.py /opt/ml/code/cifar10.py— Copia o script para o local dentro do contêiner que é esperado pelo SageMaker. O script deve estar localizado nessa pasta.

      • ENV SAGEMAKER_PROGRAM cifar10.py – Define seu script de treinamento cifar10.py como o script do ponto de entrada.

    4. No painel de navegação do diretório à esquerda, o nome do arquivo de texto é nomeado automaticamente como untitled.txt. Para renomear o arquivo, clique com o botão direito do mouse no arquivo, escolha Rename (Renomear), renomeie o arquivo como Dockerfile sem a extensão .txt e pressione Ctrl+s ou Command+s para salvar o arquivo.

  3. Crie ou faça upload de um script de treinamento cifar10.py no docker_test_folder. Você pode usar o seguinte script de exemplo neste exercício:

    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())

Etapa 3: Definir o Contêiner

  1. No diretório JupyterLab inicial, abra um notebook Jupyter. Para abrir um novo bloco de anotações, escolha o ícone New Launch (Novo lançamento) e depois conda_pytorch_p39 na seção Notebook.

  2. Execute o comando a seguir na primeira célula do notebook para mudar para o diretório docker_test_folder:

    % cd ~/SageMaker/docker_test_folder

    Isso retorna o diretório atual da seguinte forma:

    ! pwd

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

  3. Faça login no Docker para acessar o contêiner de base:

    ! aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com
  4. Para criar o contêiner do Docker, execute o seguinte comando de criação do Docker, incluindo o espaço, seguido por ponto final.

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

    O comando de criação do Docker deve ser executado no diretório que você criou, neste caso, o docker_test_folder.

    nota

    Se você receber a mensagem de erro a seguir informando que o Docker não consegue encontrar o Dockerfile, verifique se o Dockerfile tem o nome correto e foi salvo no diretório.

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

    Lembre-se de que docker procura um arquivo chamado especificamente Dockerfile sem nenhuma extensão no diretório atual. Se você deu outro nome, poderá transmitir o nome de arquivo manualmente com a bandeira -f. Por exemplo, se você chamou o Dockerfile de Dockerfile-text.txt, execute o seguinte comando:

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

Etapa 4: Testar o Contêiner

  1. Para testar o contêiner no local na instância do bloco de anotações, abra um bloco de anotações do Jupyter. Escolha New Launcher (Novo inicializador) e depois Notebook (Bloco de anotações) na estrutura de trabalho conda_pytorch_p39. O restante dos trechos de código deve ser executado na instância do bloco de anotações Jupyter.

  2. Baixe o conjunto de dados 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. Defina role na função usada para criar seu bloco de anotações Jupyter. Isso é usado para configurar seu SageMaker Estimador.

    from sagemaker import get_execution_role role=get_execution_role()
  4. Cole o script de exemplo a seguir na célula de código do notebook para configurar um SageMaker Estimador usando seu contêiner estendido.

    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. Execute a célula de código. Esse teste mostra a configuração do ambiente de treinamento, os valores usados para as variáveis de ambiente, a fonte dos dados e a perda e precisão obtidas durante o treinamento.

Etapa 5: Envie o contêiner para o Amazon Elastic Container Registry (Amazon ECR)

  1. Depois de executar com êxito este teste de modo local, você pode enviar a imagem para o Amazon ECR e usá-la para executar trabalhos de treinamento.

    É possível executar as linhas de comandos a seguir em uma célula do bloco de anotações.

    %%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. Depois de enviar o contêiner, você pode chamar a imagem do Amazon ECR de qualquer lugar no SageMaker ambiente. Execute o exemplo de código a seguir na próxima célula do bloco de anotações.

    Se quiser usar esse contêiner de treinamento com o SageMaker Studio para usar seus recursos de visualização, você também pode executar o código a seguir em uma célula de notebook do Studio para chamar a imagem Amazon ECR do seu contêiner de treinamento.

    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. Use o ecr_image recuperado da etapa anterior para configurar um objeto SageMaker estimador. O exemplo de código a seguir configura um SageMaker PyTorch estimador.

    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)

Etapa 6: Limpar os Recursos

Para limpar recursos quando terminar com o exemplo de Get Started (introdução)
  1. Abra o SageMaker console, escolha a instância do notebook RunScriptNotebookInstance, escolha Ações e escolha Parar. Pode demorar alguns minutos para que a instância pare.

  2. Depois que o status da instância mudar para Interrompido, escolha Ações, escolha Excluir e, em seguida, escolha Excluir na caixa de diálogo. Pode demorar alguns minutos para a exclusão da instância. A instância dos blocos de anotações desaparece da tabela quando é excluída.

  3. Abra o console do Amazon S3 e exclua o bucket criado para armazenar artefatos do modelo e o conjunto de dados de treinamento.

  4. Abra o console do IAM e exclua a função do IAM. Se você criou políticas de permissões, poderá excluí-las também.

    nota

    O contêiner do Docker é desligado automaticamente depois de ser executado. Você não precisa excluí-lo.