Exercício – Treinar uma rede neural para classificar com precisão as rochas espaciais em fotos

Concluído

Agora temos um modelo de IA que incorpora uma rede neural. Fornecemos alguns dados para nosso programa para ensinar a ele as diferentes características de rochas espaciais. O programa tem muitos neurônios e eles estão conectados em uma rede de aprendizado profundo.

Agora, é hora de treinar nosso programa. Vamos usar nossos dados de treinamento da NASA. Vamos adicionar código para ajudar nosso programa a se tornar preciso ao classificar rochas espaciais.

Iterar nos dados e aumentar a precisão

Nesta seção do código, procure a variável epochs. Essa variável informa ao programa quantas vezes pesquisar associações em recursos. Em nosso exemplo, vamos definir o número inicial de iterações como 5.

Observação

Você pode aumentar o número de iterações para aprimorar ainda mais a precisão do modelo. Tenha em mente que aumentar o número de iterações torna a execução do código mais lenta.

Para treinar nosso modelo, carregamos a entrada da imagem da variável trainloader que criamos no módulo Analisar imagens de rochas com IA. Os dados são armazenados no dispositivo já selecionado. Chamamos a função optimizer.zero_grad() para zerar gradientes e evitar o acúmulo de gradientes entre iterações de treinamento.

A entrada da imagem é passada pelo modelo usando a função model.forward(inputs), que retorna as probabilidades de log de cada rótulo. A função criterion(logps, labels) executa as probabilidades de log por meio do critério para obter o grafo de saída. A função loss.backward() usa o grafo de perda para computar os gradientes. A função optimizer.step() então atualiza os parâmetros com base no gradiente atual.

Durante o treinamento e o teste, acompanhamos os valores de perda para cada iteração e o lote completo. A cada cinco epochs, avaliamos o modelo. Usamos a função model.eval() com a função torch.no_grad() para desligar partes do modelo que se comportam de modo diferente durante o treinamento versus a avaliação. Usamos esse par de funções para refinar a precisão da previsão sem atualizar os gradientes.

A função torch.exp(logps) é usada para obter um novo tensor com as probabilidades verdadeiras. A maior probabilidade e classe do novo tensor ao longo de uma determinada dimensão é retornada da função ps.topk(1, dim=1). O tensor é remodelado para corresponder à mesma forma que a classe superior.

Por fim, computamos a precisão geral.

Treinar a rede neural

Siga estas etapas para treinar a rede neural em seu modelo de IA.

  1. Volte para o Visual Studio Code e abra o arquivo do Jupyter Notebook. Em nosso exemplo, estamos usando o arquivo ClassifySpaceRockProgram.ipynb.

  2. Verifique se você está executando o kernel correto do Jupyter. Nos cantos superior direito e inferior esquerdo do Visual Studio, altere para o ambiente Anaconda ('myenv') que você criou antes.

  3. Adicione o código a seguir em uma nova célula e depois execute a célula.

    # Set the initial number of iterations to search for associations
    epochs = 5
    print_every = 5
    
    # Initialize the loss variables
    running_loss = 0
    train_losses, test_losses = [], []
    
    # Track the current training step, start at 0
    steps = 0
    
    # Search for associations in the features
    for epoch in range(epochs):
    
       # Count each epoch
       epoch += 1
    
       # Load in all of the image inputs and labels from the TRAIN loader 
       for inputs, labels in trainloader:
    
          # Count each training step
          steps += 1
          print('Training step ', steps)
    
          # Load the inputs and labels to the already selected device
          inputs, labels = inputs.to(device), labels.to(device)
    
          # Zero out gradients to avoid accumulations of gradiants across training iterations
          optimizer.zero_grad()
    
          # Pass the images through the model, return the log probabilities of each label
          logps = model.forward(inputs)
    
          # Run the log probabilities through the criterion to get the output graph
          loss = criterion(logps, labels)
    
          # Use the loss graph to compute gradients
          loss.backward()
    
          # Update the parameters based on the current gradient
          optimizer.step()
    
          # Add the actual loss number to the running loss total
          running_loss += loss.item()
    
          # Every 5 steps, evaluate the model
          if steps % print_every == 0:
    
             # Initialize loss and accuracy
             test_loss = 0
             accuracy = 0
    
             # Start the model evaluation
             model.eval()
    
             # Refine the accuracy of the prediction without updating the gradients
             with torch.no_grad():
    
                # Load in all of the image inputs and labels from the TEST loader 
                for inputs, labels in testloader:
    
                   # Load the inputs and labels to the already selected device
                   inputs, labels = inputs.to(device), labels.to(device)
    
                   # Pass the images through the model, return the log probabilities of each label
                   logps = model.forward(inputs)
    
                   # Run the log probabilities through the criterion to get the output graph
                   batch_loss = criterion(logps, labels)
    
                   # Add the actual loss number to the running loss total for the test batch
                   test_loss += batch_loss.item()
    
                   # Return a new tensor with the true probabilities
                   ps = torch.exp(logps)
    
                   # Return the largest probability and class of the new tensor along a given dimension
                   top_p, top_class = ps.topk(1, dim=1)
    
                   # Reshape the tensor to match the same shape as the top class
                   equals = top_class == labels.view(*top_class.shape)
    
                   # Compute the accuracy and add it to the running accuracy count for the test batch
                   accuracy += torch.mean(equals.type(torch.FloatTensor)).item()
    
             # Append the training and testing losses
             train_losses.append(running_loss/len(trainloader))
             test_losses.append(test_loss/len(testloader))  
    
             # Display the accuracy of the prediction with 3 digits in the fractional part of the decimal
             print(f"\n     Epoch {epoch}/{epochs}: "
                   f"Train loss: {running_loss/print_every:.3f}.. "
                   f"Test loss: {test_loss/len(testloader):.3f}.. "
                   f"Test accuracy: {accuracy/len(testloader):.3f}\n")
    
             # Train the model
             running_loss = 0
             model.train()
    
             # After 5 training steps, start the next epoch
             # Break here in case the trainloader has remaining data
             break
    

    À medida que o build progride, a saída mostra cada etapa de treinamento e época concluída:

    Training step 1
    Training step 2
    Training step 3
    Training step 4
    Training step 5
    
         Epoch 1/5: Train loss: 0.550.. Test loss: 0.282.. Test accuracy: 0.902
    
    Training step 6
    Training step 7
    Training step 8
    Training step 9
    Training step 10
    
         Epoch 2/5: Train loss: 0.451.. Test loss: 0.311.. Test accuracy: 0.842
    
    Training step 11
    Training step 12
    Training step 13
    ...
    

    Você percebe que a saída de cada época sucessiva demora um pouco mais para ser exibida do que a anterior?

Analisar a saída de treinamento

Depois que cinco épocas forem concluídas, o sistema atingirá nosso limite epoch.

...
Training step 19
Training step 20

     Epoch 4/5: Train loss: 0.216.. Test loss: 0.189.. Test accuracy: 0.906

Training step 21
Training step 22
Training step 23
Training step 24
Training step 25

     Epoch 5/5: Train loss: 0.234.. Test loss: 0.175.. Test accuracy: 0.935

A saída mostra a precisão da previsão para cada iteração de época com perdas de treinamento e teste e a precisão do teste.

Aqui estão os resultados de nosso teste com cinco épocas. Seus resultados específicos serão diferentes porque o computador escolhe um conjunto de imagens aleatórias para cada execução de teste. Os resultados revelam a perda de treinamento, a perda de teste e a precisão. Tudo isso depende da imagem escolhida.

Época Perda de treinamento Perda de teste Precisão de teste
1 0,550 0,282 0,902
2 0,451 0,311 0,842
3 0,342 0,233 0,902
4 0,216 0,189 0,906
5 0,234 0,175 0,935