Parte 2 - utilizzo di AWS Amazon FSX per NetApp ONTAP (FSX ONTAP) come origine dati per il training sui modelli in SageMaker
Questo articolo è un tutorial sull'utilizzo di Amazon FSX per NetApp ONTAP (FSX ONTAP) per la formazione dei modelli PyTorch in SageMaker, in particolare per un progetto di classificazione della qualità degli pneumatici.
Autore(i):
Jian Jian (Ken), Senior Data & Applied Scientist, NetApp
Introduzione
Questo tutorial offre un esempio pratico di un progetto di classificazione della computer vision, che fornisce un'esperienza pratica nella creazione di modelli ML che utilizzano FSX ONTAP come origine dati all'interno dell'ambiente SageMaker. Il progetto si concentra sull'utilizzo di PyTorch, un framework di apprendimento approfondito, per classificare la qualità degli pneumatici in base alle immagini degli pneumatici. Enfatizza lo sviluppo di modelli di machine learning utilizzando FSX ONTAP come origine dati in Amazon SageMaker.
Che cos'è FSX ONTAP
Amazon FSX ONTAP è in realtà una soluzione storage completamente gestita offerta da AWS. Sfrutta il file system ONTAP di NetApp per fornire storage affidabile e dalle performance elevate. Grazie al supporto per protocolli come NFS, SMB e iSCSI, permette l'accesso perfetto da diversi container e istanze di calcolo. Il servizio è progettato per offrire performance eccezionali, garantendo operazioni sui dati rapide ed efficienti. Inoltre, offre high Availability e durata elevata per garantire che i tuoi dati rimangano accessibili e protetti. Inoltre, la capacità storage di Amazon FSX ONTAP è scalabile e ti permette di regolarla facilmente in base alle tue esigenze.
Prerequisito
Ambiente di rete
FSX ONTAP (Amazon FSX ONTAP) è un servizio di storage AWS. Include un file system in esecuzione sul sistema NetApp ONTAP e una SVM (System Virtual Machine) gestita da AWS che si connette all'IT. Nel diagramma fornito, il server NetApp ONTAP gestito da AWS si trova all'esterno del VPC. La SVM funge da intermediario tra SageMaker e il sistema NetApp ONTAP, ricevendo le richieste operative da SageMaker e inoltrandole allo storage sottostante. Per accedere a FSX ONTAP, SageMaker deve essere posizionato nello stesso VPC della distribuzione di FSX ONTAP. Questa configurazione garantisce la comunicazione e l'accesso ai dati tra SageMaker e FSX ONTAP.
Accesso ai dati
Negli scenari reali, i data scientist utilizzano in genere i dati esistenti memorizzati in FSX ONTAP per creare i propri modelli di machine learning. Tuttavia, per scopi dimostrativi, poiché il file system FSX ONTAP è inizialmente vuoto dopo la creazione, è necessario caricare manualmente i dati di formazione. Questo può essere ottenuto montando FSX ONTAP come volume su SageMaker. Una volta montato correttamente il file system, è possibile caricare il set di dati nella posizione montata, rendendolo accessibile per l'addestramento dei modelli all'interno dell'ambiente SageMaker. Questo approccio ti consente di sfruttare la capacità di storage e le funzionalità di FSX ONTAP, lavorando contemporaneamente con SageMaker per lo sviluppo e il training dei modelli.
Il processo di lettura dei dati implica la configurazione di FSX ONTAP come bucket S3 privato. Per istruzioni dettagliate sulla configurazione, fare riferimento alla "Parte 1 - integrazione di Amazon FSX per NetApp ONTAP (FSX ONTAP)) come bucket S3 privato in AWS SageMaker"
Panoramica sull'integrazione
Il flusso di lavoro dell'utilizzo dei dati di formazione in FSX ONTAP per creare un modello di apprendimento approfondito in SageMaker può essere riassunto in tre fasi principali: Definizione di Data Loader, formazione dei modelli e distribuzione. Ad alto livello, questi passaggi costituiscono la base di una pipeline MLOps. Tuttavia, ogni fase prevede diverse fasi secondarie dettagliate per un'implementazione completa. Queste fasi secondarie comprendono varie attività come la pre-elaborazione dei dati, la suddivisione del dataset, la configurazione del modello, la regolazione dell'iperparametro, la valutazione del modello, e distribuzione dei modelli. Questi passaggi garantiscono un processo completo ed efficace per la creazione e la distribuzione di modelli di apprendimento approfondito utilizzando i dati di formazione di FSX ONTAP all'interno dell'ambiente SageMaker.
Integrazione step-by-step
Caricatore dati
Per addestrare una rete di apprendimento profondo PyTorch con i dati, viene creato un caricatore dati per facilitare l'alimentazione dei dati. Il caricatore dati non solo definisce la dimensione del batch, ma determina anche la procedura di lettura e pre-elaborazione di ciascun record all'interno del batch. Configurando il data loader, possiamo gestire l'elaborazione dei dati in batch, consentendo la formazione della rete di deep learning.
Il caricatore dati è composto da 3 parti.
Funzione di pre-elaborazione
from torchvision import transforms
preprocess = transforms.Compose([
transforms.ToTensor(),
transforms.Resize((224,224)),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
])
Il frammento di codice riportato sopra illustra la definizione delle trasformazioni di pre-elaborazione delle immagini utilizzando il modulo torchvision.Transforms. In questa turtorial, l'oggetto di pre-elaborazione viene creato per applicare una serie di trasformazioni. In primo luogo, la trasformazione ToTensor() converte l'immagine in una rappresentazione tensoriale. Successivamente, la trasformazione Ridimensiona((224.224) ridimensiona l'immagine a una dimensione fissa di 224x224 pixel. Infine, la trasformazione Normalize() normalizza i valori del tensore sottraendo la media e dividendo per la deviazione standard lungo ciascun canale. I valori di deviazione media e standard utilizzati per la normalizzazione sono comunemente impiegati in modelli di rete neurale pre-addestrati. Nel complesso, questo codice prepara i dati dell'immagine per un'ulteriore elaborazione o immissione in un modello pre-addestrato convertendoli in un tensore, ridimensionandoli e normalizzando i valori dei pixel.
Classe dataset PyTorch
import torch
from io import BytesIO
from PIL import Image
class FSxNImageDataset(torch.utils.data.Dataset):
def __init__(self, bucket, prefix='', preprocess=None):
self.image_keys = [
s3_obj.key
for s3_obj in list(bucket.objects.filter(Prefix=prefix).all())
]
self.preprocess = preprocess
def __len__(self):
return len(self.image_keys)
def __getitem__(self, index):
key = self.image_keys[index]
response = bucket.Object(key)
label = 1 if key[13:].startswith('defective') else 0
image_bytes = response.get()['Body'].read()
image = Image.open(BytesIO(image_bytes))
if image.mode == 'L':
image = image.convert('RGB')
if self.preprocess is not None:
image = self.preprocess(image)
return image, label
Questa classe fornisce funzionalità per ottenere il numero totale di record nell'insieme di dati e definisce il metodo di lettura dei dati per ogni record. All'interno della funzione getitem, il codice utilizza l'oggetto bucket boto3 S3 per recuperare i dati binari da FSX ONTAP. Lo stile del codice per l'accesso ai dati da FSX ONTAP è simile alla lettura dei dati da Amazon S3. La spiegazione successiva si sofferma sul processo di creazione dell'oggetto S3 privato bucket.
FSX ONTAP come repository S3 privato
seed = 77 # Random seed
bucket_name = '<Your ONTAP bucket name>' # The bucket name in ONTAP
aws_access_key_id = '<Your ONTAP bucket key id>' # Please get this credential from ONTAP
aws_secret_access_key = '<Your ONTAP bucket access key>' # Please get this credential from ONTAP
fsx_endpoint_ip = '<Your FSx ONTAP IP address>' # Please get this IP address from FSXN
import boto3
# Get session info
region_name = boto3.session.Session().region_name
# Initialize Fsxn S3 bucket object
# --- Start integrating SageMaker with FSXN ---
# This is the only code change we need to incorporate SageMaker with FSXN
s3_client: boto3.client = boto3.resource(
's3',
region_name=region_name,
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
use_ssl=False,
endpoint_url=f'http://{fsx_endpoint_ip}',
config=boto3.session.Config(
signature_version='s3v4',
s3={'addressing_style': 'path'}
)
)
# s3_client = boto3.resource('s3')
bucket = s3_client.Bucket(bucket_name)
# --- End integrating SageMaker with FSXN ---
Per leggere i dati da FSX ONTAP in SageMaker, viene creato un gestore che punta allo storage FSX ONTAP utilizzando il protocollo S3. In questo modo FSX ONTAP può essere trattato come un bucket S3 privato. La configurazione del gestore include l'indicazione dell'indirizzo IP della SVM di FSX ONTAP, del nome del bucket e delle credenziali necessarie. Per una spiegazione completa su come ottenere questi elementi di configurazione, fare riferimento al documento all'indirizzo "Parte 1 - integrazione di Amazon FSX per NetApp ONTAP (FSX ONTAP) come bucket S3 privato in AWS SageMaker".
Nell'esempio sopra menzionato, l'oggetto bucket viene utilizzato per creare un'istanza dell'oggetto dataset PyTorch. L'oggetto dataset verrà ulteriormente spiegato nella sezione successiva.
Il caricatore dati PyTorch
from torch.utils.data import DataLoader
torch.manual_seed(seed)
# 1. Hyperparameters
batch_size = 64
# 2. Preparing for the dataset
dataset = FSxNImageDataset(bucket, 'dataset/tyre', preprocess=preprocess)
train, test = torch.utils.data.random_split(dataset, [1500, 356])
data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
Nell'esempio fornito, viene specificata una dimensione batch di 64, che indica che ogni batch conterrà 64 record. Combinando la classe PyTorch dataset, la funzione di pre-elaborazione e la dimensione del batch di training, otteniamo il caricatore dati per la formazione. Questo caricatore dati facilita il processo di iterazione del set di dati in batch durante la fase di training.
Training sui modelli
from torch import nn
class TyreQualityClassifier(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(3,32,(3,3)),
nn.ReLU(),
nn.Conv2d(32,32,(3,3)),
nn.ReLU(),
nn.Conv2d(32,64,(3,3)),
nn.ReLU(),
nn.Flatten(),
nn.Linear(64*(224-6)*(224-6),2)
)
def forward(self, x):
return self.model(x)
import datetime
num_epochs = 2
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = TyreQualityClassifier()
fn_loss = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
model.to(device)
for epoch in range(num_epochs):
for idx, (X, y) in enumerate(data_loader):
X = X.to(device)
y = y.to(device)
y_hat = model(X)
loss = fn_loss(y_hat, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"Current Time: {current_time} - Epoch [{epoch+1}/{num_epochs}]- Batch [{idx + 1}] - Loss: {loss}", end='\r')
Questo codice implementa un processo di formazione PyTorch standard. Definisce un modello di rete neurale chiamato TyreQualityClassifier utilizzando strati convoluzionali e uno strato lineare per classificare la qualità dei pneumatici. Il ciclo di training itera i batch di dati, calcola la perdita e aggiorna i parametri del modello utilizzando la backpropagation e l'ottimizzazione. Inoltre, stampa l'ora corrente, l'epoca, il batch e la perdita a scopo di monitoraggio.
Implementazione dei modelli
Implementazione
import io
import os
import tarfile
import sagemaker
# 1. Save the PyTorch model to memory
buffer_model = io.BytesIO()
traced_model = torch.jit.script(model)
torch.jit.save(traced_model, buffer_model)
# 2. Upload to AWS S3
sagemaker_session = sagemaker.Session()
bucket_name_default = sagemaker_session.default_bucket()
model_name = f'tyre_quality_classifier.pth'
# 2.1. Zip PyTorch model into tar.gz file
buffer_zip = io.BytesIO()
with tarfile.open(fileobj=buffer_zip, mode="w:gz") as tar:
# Add PyTorch pt file
file_name = os.path.basename(model_name)
file_name_with_extension = os.path.split(file_name)[-1]
tarinfo = tarfile.TarInfo(file_name_with_extension)
tarinfo.size = len(buffer_model.getbuffer())
buffer_model.seek(0)
tar.addfile(tarinfo, buffer_model)
# 2.2. Upload the tar.gz file to S3 bucket
buffer_zip.seek(0)
boto3.resource('s3') \
.Bucket(bucket_name_default) \
.Object(f'pytorch/{model_name}.tar.gz') \
.put(Body=buffer_zip.getvalue())
Il codice salva il modello PyTorch in Amazon S3 perché SageMaker richiede che il modello venga memorizzato in S3 per la distribuzione. Caricando il modello su Amazon S3, diventa accessibile a SageMaker, consentendo la distribuzione e l'inferenza sul modello distribuito.
import time
from sagemaker.pytorch import PyTorchModel
from sagemaker.predictor import Predictor
from sagemaker.serializers import IdentitySerializer
from sagemaker.deserializers import JSONDeserializer
class TyreQualitySerializer(IdentitySerializer):
CONTENT_TYPE = 'application/x-torch'
def serialize(self, data):
transformed_image = preprocess(data)
tensor_image = torch.Tensor(transformed_image)
serialized_data = io.BytesIO()
torch.save(tensor_image, serialized_data)
serialized_data.seek(0)
serialized_data = serialized_data.read()
return serialized_data
class TyreQualityPredictor(Predictor):
def __init__(self, endpoint_name, sagemaker_session):
super().__init__(
endpoint_name,
sagemaker_session=sagemaker_session,
serializer=TyreQualitySerializer(),
deserializer=JSONDeserializer(),
)
sagemaker_model = PyTorchModel(
model_data=f's3://{bucket_name_default}/pytorch/{model_name}.tar.gz',
role=sagemaker.get_execution_role(),
framework_version='2.0.1',
py_version='py310',
predictor_cls=TyreQualityPredictor,
entry_point='inference.py',
source_dir='code',
)
timestamp = int(time.time())
pytorch_endpoint_name = '{}-{}-{}'.format('tyre-quality-classifier', 'pt', timestamp)
sagemaker_predictor = sagemaker_model.deploy(
initial_instance_count=1,
instance_type='ml.p3.2xlarge',
endpoint_name=pytorch_endpoint_name
)
Questo codice facilita la distribuzione di un modello PyTorch su SageMaker. Definisce un serializzatore personalizzato, TyreQualitySerializer, che preelabora e serializza i dati di input come un tensor PyTorch. La classe TyreQualityPredictor è un predittore personalizzato che utilizza il serializzatore definito e un JSONDeserializer. Il codice crea inoltre un oggetto PyTorchModel per specificare la posizione S3 del modello, il ruolo IAM, la versione del framework e il punto di ingresso per l'inferenza. Il codice genera un indicatore data e ora e costruisce un nome endpoint in base al modello e all'indicatore data e ora. Infine, il modello viene distribuito utilizzando il metodo Deploy, specificando il numero di istanze, il tipo di istanza e il nome dell'endpoint generato. In questo modo, il modello PyTorch può essere distribuito e accessibile per l'inferenza su SageMaker.
Inferenza
image_object = list(bucket.objects.filter('dataset/tyre'))[0].get()
image_bytes = image_object['Body'].read()
with Image.open(with Image.open(BytesIO(image_bytes)) as image:
predicted_classes = sagemaker_predictor.predict(image)
print(predicted_classes)
Questo è l'esempio di utilizzo dell'endpoint distribuito per l'inferenza.