Estendere un container predefinito - Amazon SageMaker

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Estendere un container predefinito

Se un SageMaker container precostruito non soddisfa tutti i requisiti, puoi estendere l'immagine esistente per soddisfare le tue esigenze. Anche se è disponibile un supporto diretto per l'ambiente o il framework, è possibile aggiungere funzionalità aggiuntive o configurare l'ambiente del container in modo diverso. Estendendo un'immagine predefinita, è possibile sfruttare le librerie e le impostazioni di deep learning incluse senza dover creare un'immagine da zero. È possibile estendere il container per aggiungere librerie, modificare le impostazioni e installare dipendenze aggiuntive.

Il seguente tutorial mostra come estendere un' SageMaker immagine predefinita e pubblicarla su Amazon ECR.

Requisiti per estendere un container predefinito

Per estendere un' SageMaker immagine predefinita, devi impostare le seguenti variabili di ambiente all'interno del tuo Dockerfile. Per ulteriori informazioni sulle variabili di ambiente con SageMaker contenitori, consulta il repository SageMaker Training Toolkit. GitHub

  • SAGEMAKER_SUBMIT_DIRECTORY: La directory all'interno del container in cui si trova lo script Python per il training.

  • SAGEMAKER_PROGRAM: Lo script Python che dovrebbe essere invocato e usato come punto di ingresso per il training.

È possibile anche installare librerie aggiuntive includendo quanto segue nel Dockerfile:

RUN pip install <library>

Il tutorial seguente mostra l'utilizzo di queste variabili di ambiente.

Estendi SageMaker i contenitori per eseguire uno script Python

In questo tutorial, imparerai come estendere il SageMaker PyTorch contenitore con un file Python che utilizza il set di dati CIFAR-10. Estendendo il SageMaker PyTorch contenitore, si utilizza la soluzione di formazione esistente su misura. SageMaker Questo tutorial estende un'immagine di training, ma è possibile eseguire gli stessi passaggi per estendere un'immagine di inferenza. Per un elenco completo di immagini disponibili, consultare Immagini dei container Deep Learning disponibili.

Per eseguire il tuo modello di formazione utilizzando i SageMaker contenitori, crea un contenitore Docker tramite un' SageMaker istanza Notebook.

Passaggio 1: creare un'istanza SageMaker Notebook

  1. Apri la SageMaker console.

  2. Nel riquadro di navigazione, scegliere Notebook, scegliere Notebook instances (Istanze notebook) quindi Create notebook instance (Crea un'istanza notebook).

  3. Nella pagina Crea un'istanza notebook, immettere le seguenti informazioni:

    1. In Nome istanza notebook, immettere RunScriptNotebookInstance.

    2. Per Tipo di istanza notebook, scegliere ml.t2.medium.

    3. Nella sezione Permissions and encryption (Autorizzazioni e crittografia) e procedere come segue:

      1. Per Ruolo IAM, scegliere Crea un nuovo ruolo.

      2. Nella pagina Crea un ruolo IAM, scegliere Specifica bucket S3, specificare un bucket S3 Amazon denominato sagemaker-run-script e scegliere Crea ruolo.

        SageMaker crea un ruolo IAM denominatoAmazonSageMaker-ExecutionRole-YYYYMMDDTHHmmSS, ad esempioAmazonSageMaker-ExecutionRole-20190429T110788. Si noti che la convenzione di denominazione del ruolo di esecuzione utilizza la data e l'ora in cui il ruolo è stato creato, separati da T.

    4. Per Accesso root, scegliere Abilitato.

    5. Scegliere Crea un'istanza notebook.

  4. Nella pagina istanze Notebook, lo Status (Stato) è Pending (In sospeso). Amazon CloudWatch Internet Monitor può impiegare alcuni minuti per avviare un'istanza di calcolo di machine learning (in questo caso, avvia un'istanza notebook) e collegarvi un volume di storage ML. L'istanza notebook include un server Notebook Jupyter preconfigurato e un set di librerie Anaconda. Per ulteriori informazioni, consulta CreateNotebookInstance.

  5. Nella sezione Permissions and encryption (Autorizzazioni e crittografia), copiare il numero ARN del ruolo IAM e incollarlo in un file di blocco note per salvarlo temporaneamente. Verrà utilizzato questo numero ARN del ruolo IAM in seguito per configurare uno stimatore di training locale nell'istanza del notebook. Il numero ARN del ruolo IAM è simile al seguente: 'arn:aws:iam::111122223333:role/service-role/AmazonSageMaker-ExecutionRole-20190429T110788'

  6. Dopo che lo stato dell'istanza del notebook diventa InService, scegli Apri JupyterLab.

Fase 2: Creazione e caricamento del Dockerfile e degli script di formazione Python

  1. Dopo l' JupyterLab apertura, crea una nuova cartella nella home directory del tuo JupyterLab. Nell'angolo in alto a sinistra, scegliere l'icona New Folder (Nuova cartella) e quindi inserire il nome della cartella docker_test_folder.

  2. Nella directory Dockerfile, creare un file denominato docker_test_folder.

    1. Scegliere l'icona New Launcher (Nuova utilità di avvio) (+) nell'angolo in alto a sinistra.

    2. Nel pannello di destra, nella sezione Other (Altro), scegliere Text File (File di testo).

    3. Incolla il seguente Dockerfile codice campione nel tuo file di testo.

      # 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

      Lo script Dockerfile esegue le seguenti attività:

      • FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04— Scarica l'immagine SageMaker PyTorch di base. Puoi sostituirla con qualsiasi immagine di SageMaker base che desideri utilizzare per creare contenitori.

      • ENV SAGEMAKER_SUBMIT_DIRECTORY /opt/ml/code— Imposta /opt/ml/code come directory dello script di training.

      • COPY cifar10.py /opt/ml/code/cifar10.py— Copia lo script nella posizione all'interno del contenitore prevista da SageMaker. Lo script si deve trovare in questa cartella.

      • ENV SAGEMAKER_PROGRAM cifar10.py— Imposta lo script di training cifar10.py come script del punto di ingresso.

    4. Nel riquadro di navigazione a sinistra, il nome del file di testo viene automaticamente denominato untitled.txt. Per rinominare il file, fare clic con il pulsante destro del mouse sul file, scegliere Rinomina, rinominare il file come Dockerfile senza l’estensione .txt, quindi premere Ctrl+s o Command+s per salvare il file.

  3. Crea o carica uno script di training cifar10.py in docker_test_folder. È possibile utilizzare il seguente script di esempio per questo esercizio.

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

Fase 3: Costruzione del container

  1. Nella JupyterLab home directory, apri un notebook Jupyter. Per aprire un nuovo notebook, scegliere l'icona Nuovo avvio, quindi scegliere conda_pytorch_p39 nella sezione Notebook.

  2. Esegui il comando seguente nella prima cella del notebook per passare alla directory docker_test_folder:

    % cd ~/SageMaker/docker_test_folder

    Viene restituita la directory corrente come segue:

    ! pwd

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

  3. Effettua il login a Docker per accedere al container di 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. Per compilare il container Docker, eseguire il seguente comando di compilazione Docker, incluso lo spazio seguito da un punto finale:

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

    Il comando build Docker deve essere eseguito dalla directory Docker creata, in questo caso docker_test_folder.

    Nota

    Se si riceve il seguente messaggio di errore che indica che Docker non riesce a trovare il Dockerfile, assicurarsi che il Dockerfile abbia il nome corretto e che sia stato salvato nella directory.

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

    Ricordare che docker cerca un file chiamato specificamente Dockerfile senza alcuna estensione all'interno della directory corrente. Se è stato rinominato, è possibile passare il nome del file manualmente con il flag -f. Ad esempio, se è stato denominato il Dockerfile Dockerfile-text.txt, eseguire il comando seguente:

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

Fase 4: Test del container

  1. Per eseguire il test del container localmente nell’istanza notebook, aprire un notebook Jupyter. Scegliere Nuova utilità di avvio e selezionare Notebook nel framework conda_pytorch_p39. Il resto dei frammenti di codice deve essere eseguito dall'istanza del notebook Jupyter.

  2. Scaricare il set di dati 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. Impostare role sul ruolo utilizzato per creare il notebook Jupyter. Viene utilizzato per configurare il tuo Estimator. SageMaker

    from sagemaker import get_execution_role role=get_execution_role()
  4. Incolla il seguente script di esempio nella cella di codice del notebook per configurare un SageMaker Estimator utilizzando il tuo contenitore esteso.

    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. Eseguire la cella di codice. Questo test genera la configurazione dell'ambiente utilizzato per le variabili di ambiente, l'origine dei dati e la perdita e la precisione ottenuti durante il training.

Fase 5: Invio tramite push del container ad Amazon Elastic Container Registry (Amazon ECR)

  1. Dopo aver eseguito questo test in modalità locale, è possibile eseguire il push del container Docker in Amazon ECR e utilizzarlo per eseguire processi di training.

    Eseguire le seguenti linee di comando in una cella di notebook.

    %%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. Dopo aver inviato il container, puoi richiamare l'immagine Amazon ECR da qualsiasi punto dell' SageMaker ambiente. Eseguire il seguente esempio di codice nella cella successiva del notebook.

    Se desideri utilizzare questo contenitore di formazione con SageMaker Studio per utilizzare le sue funzionalità di visualizzazione, puoi anche eseguire il codice seguente in una cella notebook Studio per richiamare l'immagine Amazon ECR del tuo contenitore di formazione.

    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. Usa quanto ecr_image recuperato dal passaggio precedente per configurare un SageMaker oggetto estimatore. Il seguente esempio di codice configura uno stimatore. 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)

Fase 6: Eliminazione delle risorse

Per eliminare le risorse al termine dell'esempio sulle Nozioni di base
  1. Apri la SageMaker console, scegli l'istanza del notebook RunScriptNotebookInstance, scegli Azioni e scegli Stop. Possono essere necessari alcuni minuti per arrestare l'istanza.

  2. Dopo che lo Stato dell’istanza diventa Stopped (Arrestato), scegliere Actions (Azioni), scegliere Delete (Elimina) e quindi scegliere Delete (Elimina) nella casella di dialogo. Possono essere necessari alcuni minuti per eliminare l'istanza. L'istanza del notebook scompare dalla tabella una volta eliminata.

  3. Aprire la console Amazon S3 ed eliminare il bucket creato per l'archiviazione degli artefatti del modello e del set di dati di training.

  4. Aprire la console IAM ed eliminare il ruolo IAM. Se hai creato policy di autorizzazione, puoi anche eliminarle.

    Nota

    Il container Docker si arresta automaticamente dopo che è stato eseguito. Non è necessario eliminarlo.