Condividi tramite


Eseguire il training del modello di analisi dei dati con PyTorch

Nella fase precedente di questa esercitazione è stato acquisito il set di dati che verrà usato per eseguire il training del modello di analisi dei dati con PyTorch. Ora è il momento di inserire i dati da usare.

Per eseguire il training del modello di analisi dei dati con PyTorch, è necessario completare i passaggi seguenti:

  1. Caricare i dati. Se il passaggio precedente di questa esercitazione è già stato eseguito, questo è già stato gestito.
  2. Definire una rete neurale.
  3. Definire una funzione di perdita.
  4. Eseguire il training del modello sui dati di training.
  5. Testare la rete sui dati di test.

Definire una rete neurale

In questa esercitazione si creerà un modello di rete neurale di base con tre livelli lineari. La struttura del modello è la seguente:

Linear -> ReLU -> Linear -> ReLU -> Linear

Un livello lineare applica una trasformazione lineare ai dati in ingresso. È necessario specificare il numero di funzionalità di input e il numero di funzionalità di output che devono corrispondere al numero di classi.

Un livello ReLU è una funzione di attivazione per definire tutte le funzionalità in ingresso da 0 o superiore. Pertanto, quando viene applicato un livello ReLU, qualsiasi numero minore di 0 viene modificato in zero, mentre altri vengono mantenuti uguali. Il livello di attivazione verrà applicato ai due livelli nascosti e non verrà eseguita alcuna attivazione sull'ultimo livello lineare.

Parametri del modello

I parametri del modello dipendono dall'obiettivo e dai dati di training. Le dimensioni di input dipendono dal numero di funzionalità che si inserisce nel modello, quattro nel nostro caso. Le dimensioni di output sono tre perché esistono tre tipi possibili di Iris.

Avere tre livelli lineari, (4,24) -> (24,24) -> (24,3), la rete avrà 744 pesi (96+576+72).

La frequenza di apprendimento (lr) imposta il controllo della quantità di peso della rete rispetto alla sfumatura di perdita. Più basso è, più lento sarà il training. In questa esercitazione verrà impostato lr su 0.01.

Come funziona la rete?

In questo caso si sta creando una rete di inoltro dei feed. Durante il processo di training, la rete elabora l'input attraverso tutti i livelli, calcola la perdita per comprendere quanto l'etichetta stimata dell'immagine sta cadendo da quella corretta e propaga le sfumature nella rete per aggiornare i pesi dei livelli. Eseguendo l'iterazione su un set di dati enorme di input, la rete "apprendo" per impostare i suoi pesi per ottenere i risultati migliori.

Una funzione forward calcola il valore della funzione di perdita e una funzione indietro calcola le sfumature dei parametri appresi. Quando si crea la rete neurale con PyTorch, è sufficiente definire la funzione forward. La funzione all'indietro verrà definita automaticamente.

  1. Copiare il codice seguente nel DataClassifier.py file in Visual Studio per definire i parametri del modello e la rete neurale.
# Define model parameters 
input_size = list(input.shape)[1]   # = 4. The input depends on how many features we initially feed the model. In our case, there are 4 features for every predict value  
learning_rate = 0.01 
output_size = len(labels)           # The output is prediction results for three types of Irises.  


# Define neural network 
class Network(nn.Module): 
   def __init__(self, input_size, output_size): 
       super(Network, self).__init__() 
        
       self.layer1 = nn.Linear(input_size, 24) 
       self.layer2 = nn.Linear(24, 24) 
       self.layer3 = nn.Linear(24, output_size) 


   def forward(self, x): 
       x1 = F.relu(self.layer1(x)) 
       x2 = F.relu(self.layer2(x1)) 
       x3 = self.layer3(x2) 
       return x3 
 
# Instantiate the model 
model = Network(input_size, output_size) 

Dovrai anche definire il dispositivo di esecuzione in base a quello disponibile nel PC. PyTorch non dispone di una libreria dedicata per GPU, ma è possibile definire manualmente il dispositivo di esecuzione. Il dispositivo sarà una GPU Nvidia se presente nel computer o la CPU, se non ne esiste una.

  1. Copiare il codice seguente per definire il dispositivo di esecuzione:
# Define your execution device 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
print("The model will be running on", device, "device\n") 
model.to(device)    # Convert model parameters and buffers to CPU or Cuda 
  1. Come ultimo passaggio, definire una funzione per salvare il modello:
# Function to save the model 
def saveModel(): 
    path = "./NetModel.pth" 
    torch.save(model.state_dict(), path) 

Nota

Per altre informazioni sulla rete neurale, vedere PyTorch? Vedere la documentazione di PyTorch.

Definire una funzione di perdita

Una funzione di perdita calcola un valore che stima la distanza dell'output dalla destinazione. L'obiettivo principale è ridurre il valore della funzione di perdita modificando i valori del vettore di peso tramite backpropagation nelle reti neurali.

Il valore della perdita è diverso dall'accuratezza del modello. La funzione di perdita rappresenta il comportamento del modello dopo ogni iterazione di ottimizzazione nel set di training. L'accuratezza del modello viene calcolata sui dati di test e mostra la percentuale di stime corrette.

In PyTorch il pacchetto di rete neurale contiene varie funzioni di perdita che costituiscono i blocchi predefiniti delle reti neurali profonde. Per altre informazioni su queste specifiche, iniziare con la nota precedente. In questo caso si useranno le funzioni esistenti ottimizzate per la classificazione in questo modo e si userà una funzione di perdita di entropia incrociata di classificazione e un'utilità di ottimizzazione Adam. Nell'ottimizzatore, la frequenza di apprendimento (lr) imposta il controllo della quantità di peso che si sta regolando i pesi della rete rispetto al gradiente di perdita. Verrà impostato come 0,001 qui. Più basso sarà il più lento sarà il training.

  1. Copiare il codice seguente nel DataClassifier.py file in Visual Studio per definire la funzione di perdita e un ottimizzatore.
# Define the loss function with Classification Cross-Entropy loss and an optimizer with Adam optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)

Eseguire il training del modello sui dati di training.

Per eseguire il training del modello, è necessario eseguire il ciclo sull'iteratore dei dati, inserire gli input nella rete e ottimizzare. Per convalidare i risultati, è sufficiente confrontare le etichette stimate con le etichette effettive nel set di dati di convalida dopo ogni periodo di training.

Il programma visualizzerà la perdita di training, la perdita di convalida e l'accuratezza del modello per ogni periodo o per ogni iterazione completa sul set di training. Salva il modello con la massima precisione e dopo 10 periodi, il programma visualizzerà l'accuratezza finale.

  1. Aggiungere il codice seguente al DataClassifier.py file
# Training Function 
def train(num_epochs): 
    best_accuracy = 0.0 
     
    print("Begin training...") 
    for epoch in range(1, num_epochs+1): 
        running_train_loss = 0.0 
        running_accuracy = 0.0 
        running_vall_loss = 0.0 
        total = 0 
 
        # Training Loop 
        for data in train_loader: 
        #for data in enumerate(train_loader, 0): 
            inputs, outputs = data  # get the input and real species as outputs; data is a list of [inputs, outputs] 
            optimizer.zero_grad()   # zero the parameter gradients          
            predicted_outputs = model(inputs)   # predict output from the model 
            train_loss = loss_fn(predicted_outputs, outputs)   # calculate loss for the predicted output  
            train_loss.backward()   # backpropagate the loss 
            optimizer.step()        # adjust parameters based on the calculated gradients 
            running_train_loss +=train_loss.item()  # track the loss value 
 
        # Calculate training loss value 
        train_loss_value = running_train_loss/len(train_loader) 
 
        # Validation Loop 
        with torch.no_grad(): 
            model.eval() 
            for data in validate_loader: 
               inputs, outputs = data 
               predicted_outputs = model(inputs) 
               val_loss = loss_fn(predicted_outputs, outputs) 
             
               # The label with the highest value will be our prediction 
               _, predicted = torch.max(predicted_outputs, 1) 
               running_vall_loss += val_loss.item()  
               total += outputs.size(0) 
               running_accuracy += (predicted == outputs).sum().item() 
 
        # Calculate validation loss value 
        val_loss_value = running_vall_loss/len(validate_loader) 
                
        # Calculate accuracy as the number of correct predictions in the validation batch divided by the total number of predictions done.  
        accuracy = (100 * running_accuracy / total)     
 
        # Save the model if the accuracy is the best 
        if accuracy > best_accuracy: 
            saveModel() 
            best_accuracy = accuracy 
         
        # Print the statistics of the epoch 
        print('Completed training batch', epoch, 'Training Loss is: %.4f' %train_loss_value, 'Validation Loss is: %.4f' %val_loss_value, 'Accuracy is %d %%' % (accuracy))

Testare il modello sui dati di test.

Dopo aver eseguito il training del modello, è possibile testare il modello con il set di dati di test.

Verranno aggiunte due funzioni di test. Il primo verifica il modello salvato nella parte precedente. Testerà il modello con il set di dati di test di 45 elementi e stamperà l'accuratezza del modello. Il secondo è una funzione facoltativa per testare la fiducia del modello nella stima di ognuna delle tre specie iris, rappresentate dalla probabilità di successo della classificazione di ogni specie.

  1. Aggiungere il codice seguente al file DataClassifier.py.
# Function to test the model 
def test(): 
    # Load the model that we saved at the end of the training loop 
    model = Network(input_size, output_size) 
    path = "NetModel.pth" 
    model.load_state_dict(torch.load(path)) 
     
    running_accuracy = 0 
    total = 0 
 
    with torch.no_grad(): 
        for data in test_loader: 
            inputs, outputs = data 
            outputs = outputs.to(torch.float32) 
            predicted_outputs = model(inputs) 
            _, predicted = torch.max(predicted_outputs, 1) 
            total += outputs.size(0) 
            running_accuracy += (predicted == outputs).sum().item() 
 
        print('Accuracy of the model based on the test set of', test_split ,'inputs is: %d %%' % (100 * running_accuracy / total))    
 
 
# Optional: Function to test which species were easier to predict  
def test_species(): 
    # Load the model that we saved at the end of the training loop 
    model = Network(input_size, output_size) 
    path = "NetModel.pth" 
    model.load_state_dict(torch.load(path)) 
     
    labels_length = len(labels) # how many labels of Irises we have. = 3 in our database. 
    labels_correct = list(0. for i in range(labels_length)) # list to calculate correct labels [how many correct setosa, how many correct versicolor, how many correct virginica] 
    labels_total = list(0. for i in range(labels_length))   # list to keep the total # of labels per type [total setosa, total versicolor, total virginica] 
  
    with torch.no_grad(): 
        for data in test_loader: 
            inputs, outputs = data 
            predicted_outputs = model(inputs) 
            _, predicted = torch.max(predicted_outputs, 1) 
             
            label_correct_running = (predicted == outputs).squeeze() 
            label = outputs[0] 
            if label_correct_running.item():  
                labels_correct[label] += 1 
            labels_total[label] += 1  
  
    label_list = list(labels.keys()) 
    for i in range(output_size): 
        print('Accuracy to predict %5s : %2d %%' % (label_list[i], 100 * labels_correct[i] / labels_total[i])) 

Aggiungere infine il codice principale. Verrà avviato il training del modello, salvato il modello e verranno visualizzati i risultati sullo schermo. Verranno eseguite solo due iterazioni [num_epochs = 25] sul set di training, quindi il processo di training non richiederà troppo tempo.

  1. Aggiungere il codice seguente al file DataClassifier.py.
if __name__ == "__main__": 
    num_epochs = 10
    train(num_epochs) 
    print('Finished Training\n') 
    test() 
    test_species() 

Eseguiamo il test. Assicurarsi che i menu a discesa nella barra degli strumenti superiore siano impostati su Debug. Modificare in Solution Platform x64 per eseguire il progetto nel computer locale se il dispositivo è a 64 bit o x86 se è a 32 bit.

  1. Per eseguire il progetto, fare clic sul Start Debugging pulsante sulla barra degli strumenti oppure premere F5.

Verrà visualizzata la finestra della console e verrà visualizzato il processo di training. Come definito, il valore di perdita verrà stampato ogni periodo. L'aspettativa è che il valore di perdita diminuisce con ogni ciclo.

Al termine del training, si dovrebbe prevedere di visualizzare l'output simile al seguente. I numeri non saranno esattamente gli stessi: il training dipende da molti fattori e non restituirà sempre risultati identificali, ma dovrebbe essere simile.

Output from initial model training

Passaggi successivi

Ora che è disponibile un modello di classificazione, il passaggio successivo consiste nel convertire il modello nel formato ONNX.