Análise de Preço Polkadot 13 Set

Rede neural convolucional - implementação de PyTorch no conjunto de dados CIFAR-10

Nó Fonte: 1866263

Este artigo foi publicado como parte do Blogathon de Ciência de Dados

Introdução

Cifar 10 | Pytorch de redes neurais convolucionais
                                    1 imagem

As redes neurais convolucionais, também chamadas de ConvNets, foram introduzidas pela primeira vez na década de 1980 por Yann LeCun, um pesquisador de ciência da computação que trabalhou em segundo plano. LeCun construiu sobre o trabalho de Kunihiko Fukushima, um cientista japonês, uma rede básica para reconhecimento de imagem.

A versão antiga da CNN, chamada LeNet (após LeCun), pode ver dígitos escritos à mão. A CNN ajuda a encontrar os códigos PIN dos correios. Mas, apesar de sua experiência, a ConvNets ficou perto da visão computacional e da inteligência artificial porque enfrentou um grande problema: eles não podiam escalar muito. As CNNs exigem muitos dados e integram recursos para funcionar bem com imagens grandes.

Na época, esse método só era aplicável a imagens de baixa resolução. Pytorch é uma biblioteca que pode fazer operações de aprendizado profundo. Podemos usar isso para realizar redes neurais convolucionais. As redes neurais convolucionais contêm muitas camadas de neurônios artificiais. Neurônios sintéticos, simulações complexas de contrapartes biológicas, são funções matemáticas que calculam a massa ponderada de várias entradas e a ativação do valor do produto.

Pytorch de redes neurais convolucionais
2 imagem

A imagem acima nos mostra um modelo da CNN que obtém uma imagem semelhante a um dígito de 2 e nos dá o resultado de qual dígito foi mostrado na imagem como um número. Discutiremos em detalhes como obtemos isso neste artigo.

CIFAR-10 é um conjunto de dados que contém uma coleção de imagens de 10 classes diferentes. Este conjunto de dados é amplamente utilizado para fins de pesquisa para testar diferentes modelos de aprendizado de máquina e, especialmente, para problemas de visão computacional. Neste artigo, tentaremos construir um modelo de rede neural usando Pytorch e testá-lo no conjunto de dados CIFAR-10 para verificar qual precisão de previsão pode ser obtida.

Importando a biblioteca PyTorch 

importar numpy como np importar pandas como pd
import torch import torch.nn.functional como F de torchvision import datasets, transforma de torch import nn import matplotlib.pyplot as plt import numpy as np import seaborn as sns #from tqdm.notebook import tqdm from tqdm import tqdm

Nesta etapa, importamos as bibliotecas necessárias. Podemos ver que usamos NumPy para operações numéricas e pandas para operações de quadro de dados. A biblioteca da tocha é usada para importar o Pytorch.

O Pytorch tem um componente nn que é usado para abstração de operações e funções de aprendizado de máquina. Isso é importado como F. ​​A biblioteca torchvision é usada para que possamos importar o conjunto de dados CIFAR-10. Esta biblioteca possui muitos conjuntos de dados de imagens e é amplamente utilizada para pesquisas. As transformações podem ser importadas para que possamos redimensionar a imagem para o mesmo tamanho para todas as imagens. O tqdm é usado para que possamos acompanhar o progresso durante o treinamento e é usado para visualização.

Leia o conjunto de dados necessário

trainData = pd.read_csv ('cifar-10 / trainLabels.csv') trainData.head ()

Depois de ler o conjunto de dados, podemos ver vários rótulos, como sapo, caminhão, veado, automóvel, etc.

Analisando os dados com PyTorch

print ("Número de pontos:", trainData.shape [0]) print ("Número de recursos:", trainData.shape [1]) print ("Recursos:", trainData.columns.values) print ("Número de Valores únicos ") para col em trainData: print (col,": ", len (trainData [col] .unique ())) plt.figure (figsize = (12,8))

Saída:

Número de pontos: 50000 Número de recursos: 2 Recursos: ['id' 'rótulo'] Número de valores exclusivos id: 50000 rótulo: 10

Nesta etapa, analisamos o conjunto de dados e vemos que nossos dados de trem têm cerca de 50000 linhas com seu id e rótulo associado. Há um total de 10 classes no nome CIFAR-10.

Obtendo o conjunto de validação usando PyTorch

de torch.utils.data import random_split val_size = 5000 train_size = len (dataset) - val_size train_ds, val_ds = random_split (dataset, [train_size, val_size]) len (train_ds), len (val_ds)

Esta etapa é igual à etapa de treinamento, mas queremos dividir os dados em conjuntos de treinamento e validação.

(45000, 5000)
from torch.utils.data.dataloader import DataLoader batch_size = 64 train_dl = DataLoader (train_ds, batch_size, shuffle = True, num_workers = 4, pin_memory = True) val_dl = DataLoader (val_ds, batch_size, num_workers = 4, pin_memory = True)

O torch.utils tem um carregador de dados que pode nos ajudar a carregar os dados necessários, ignorando vários parâmetros como número do trabalhador ou tamanho do lote.

Definindo as funções necessárias

@ torch.no_grad () def precisão (saídas, rótulos): _, preds = torch.max (saídas, dim = 1) return torch.tensor (torch.sum (preds == rótulos) .item () / len (preds )) class ImageClassificationBase (nn.Module): def training_step (self, batch): images, labels = batch out = self (images) # Generate predictions loss = F.cross_entropy (out, labels) # Calculate loss accu = exatidão (out , labels) return loss, accu def validation_step (self, batch): images, labels = batch out = self (images) # Generate predictions loss = F.cross_entropy (out, labels) # Calculate loss acc = exatidão (out, labels) # Calcular precisão retornar {'Loss': loss.detach (), 'Accuracy': acc} def validation_epoch_end (self, outputs): batch_losses = [x ['Loss'] para x nas saídas] epoch_loss = torch.stack (batch_losses ) .mean () # Combine as perdas batch_accs = [x ['Accuracy'] para x nas saídas] epoch_acc = torch.stack (batch_accs) .mean () # Combine as precisões return {'Loss': epoch_loss.item (), ' Precisão ': epoch_acc.item ()} def epoch_end (self, epoch, result): pr int ("Epoch:", epoch + 1) print (f'Train Accuracy: {result ["train_accuracy"] * 100: .2f}% Precisão de validação: {result ["Accuracy"] * 100: .2f}% ' ) print (f'Perda de trem: {result ["train_loss"] :. 4f} Perda de validação: {result ["Loss"] :. 4f} ')

Como podemos ver aqui, usamos a implementação de classe de ImageClassification e leva um parâmetro que é nn.Module. Dentro desta classe, podemos implementar as várias funções ou várias etapas como treinamento, validação, etc. As funções aqui são implementações simples de Python.

A etapa de treinamento obtém imagens e rótulos em lotes. usamos entropia cruzada para função de perda e calculamos a perda e retornamos a perda. Isso é semelhante à etapa de validação, como podemos ver na função. Os fins de época combinam perdas e acertos e por fim, imprimimos acertos e perdas.

Implementação do módulo de rede neural convolucional

class Cifar10CnnModel (ImageClassificationBase): def __init __ (self): super () .__ init __ () self.network = nn.Sequential (nn.Conv2d (3, 32, kernel_size = 3, padding = 1), nn.ReLU (), nn.Conv2d (32, 64, kernel_size = 3, passo = 1, preenchimento = 1), nn.ReLU (), nn.MaxPool2d (2, 2), # saída: 64 x 16 x 16 nn.BatchNorm2d (64) , nn.Conv2d (64, 128, kernel_size = 3, passo = 1, preenchimento = 1), nn.ReLU (), nn.Conv2d (128, 128, kernel_size = 3, passo = 1, preenchimento = 1), nn .ReLU (), nn.MaxPool2d (2, 2), # saída: 128 x 8 x 8 nn.BatchNorm2d (128), nn.Conv2d (128, 256, kernel_size = 3, passo = 1, preenchimento = 1), nn.ReLU (), nn.Conv2d (256, 256, kernel_size = 3, passo = 1, preenchimento = 1), nn.ReLU (), nn.MaxPool2d (2, 2), # saída: 256 x 4 x 4 nn.BatchNorm2d (256), nn.Flatten (), nn.Linear (256 * 4 * 4, 1024), nn.ReLU (), nn.Linear (1024, 512), nn.ReLU (), nn.Linear (512, 10)) def forward (self, xb): return self.network (xb)

Esta é a parte mais importante da implementação da rede neural. Ao longo, usamos o módulo nn que importamos da tocha. Como podemos ver na primeira linha, o Conv2d é um módulo que ajuda a implementar uma rede neural convolucional. O primeiro parâmetro 3 aqui representa que a imagem é colorida e no formato RGB. Se fosse uma imagem em tons de cinza, teríamos optado por 1.

32 é o tamanho do canal de saída inicial e quando vamos para a próxima camada conv2d teríamos este 32 como canal de entrada e 64 como canal de saída.

O terceiro parâmetro da primeira linha é chamado de tamanho do kernel e nos ajuda a cuidar dos filtros usados. A operação de preenchimento é o último parâmetro.

A operação de convolução está conectada a uma camada de ativação e Relu aqui. Depois de duas camadas Conv2d, temos uma operação de pooling máximo de tamanho 2 * 2. O valor que sai disso é normalizado em lote para estabilidade e para evitar o deslocamento interno da covariável. Essas operações são repetidas com mais camadas para aprofundar a rede e reduzir o tamanho. Finalmente, nivelamos a camada para que possamos construir uma camada linear para mapear os valores para 10 valores. A probabilidade de cada neurônio desses 10 neurônios determinará a qual classe uma determinada imagem pertence com base na probabilidade máxima.

Treine o modelo

@ torch.no_grad () def Evalu (model, data_loader): model.eval () outputs = [model.validation_step (batch) para lote em data_loader] return model.validation_epoch_end (saídas) def fit (model, train_loader, val_loader, epochs = 10, learning_rate = 0.001): best_valid = None history = [] optimizer = torch.optim.Adam (model.parameters (), learning_rate, weight_decay = 0.0005) para época no intervalo (épocas): # Fase de treinamento model.train ( ) train_losses = [] train_accuracy = [] para lote em tqdm (train_loader): perda, accu = model.training_step (lote) train_losses.append (perda) train_accuracy.append (accu) loss.backward () optimizer.step () otimizador .zero_grad () # Resultado da fase de validação = avaliar (modelo, val_loader) resultado ['train_loss'] = torch.stack (train_losses) .mean (). item () resultado ['train_accuracy'] = torch.stack (train_accuracy). mean (). item () model.epoch_end (epoch, result) if (best_valid == Nenhum ou best_valid
histórico = ajuste (modelo, train_dl, val_dl)

Esta é uma etapa básica para treinar nosso modelo para obter o resultado desejado. a função de ajuste aqui ajustará os dados de trem e Val com o modelo que criamos. A função de ajuste recebe inicialmente uma lista chamada histórico que cuida dos dados de iteração de cada época. Executamos um loop for para que possamos iterar em cada época. Para cada lote, certificamo-nos de mostrar o progresso usando tqdm. Chamamos a etapa de treinamento que implementamos antes e calculamos a precisão e a perda. Vamos para a propagação para trás e execute o otimizador que definimos anteriormente. Assim que fizermos isso, monitoramos nossa lista e as funções nos ajudam a imprimir os detalhes e o progresso.

A função de avaliação, por outro lado, usa a função eval e, para cada etapa, pegamos o lote carregado do carregador de dados e a saída é calculada. O valor então é passado para o final da época de validação que definimos anteriormente e o respectivo valor é retornado.

Traçando os resultados

Nesta etapa, visualizaremos a precisão em relação a cada época. Podemos observar que conforme a época aumenta, a precisão do sistema continua aumentando e da mesma forma a perda continua diminuindo. A linha vermelha aqui indica o progresso dos dados de treinamento e azul para a validação. Podemos ver que houve uma boa quantidade de overfitting em nossos resultados, pois os dados de treinamento estão superando o resultado da validação e de forma semelhante em caso de perda. Após 10 épocas, os dados do trem parecem ignorar a precisão de 90%, mas apresentam uma perda de cerca de 0.5. Os dados de teste chegam a 81% e as perdas são próximas de 0.2.

def plot_accuracies (history): Validation_accuracies = [x ['Accuracy'] para x no histórico] Training_Accuracies = [x ['train_accuracy'] para x no histórico] plt.plot (Training_Accuracies, '-rx') plt.plot (Validation_accuracies , '-bx') plt.xlabel ('época') plt.ylabel ('precisão') plt.legend (['Treinamento', 'Validação']) plt.title ('Precisão vs. número de épocas') ; plot_accuracies (história)
Gráficos de precisão
def plot_losses (histórico): train_losses = [x.get ('train_loss') para x no histórico] val_losses = [x ['Loss'] para x no histórico] plt.plot (train_losses, '-bx') plt.plot (val_losses, '-rx') plt.xlabel ('epoch') plt.ylabel ('loss') plt.legend (['Training', 'Validation']) plt.title ('Loss vs. No. of epochs '); plot_losses (história)

test_dataset = ImageFolder (data_dir + '/ test', transform = ToTensor ()) test_loader = DeviceDataLoader (DataLoader (test_dataset, batch_size), dispositivo) resultado = avaliar (final_model, test_loader) imprimir (f'Test Precisão: {resultado ["Precisão" ] * 100: .2f}% ')
Precisão do teste: 81.07%

Podemos perceber que acabamos com uma precisão de 81.07%.

Conclusão:

Imagem: https: //unsplash.com/photos/5L0R8ZqPZHk

Sobre mim: Sou um Aluno Pesquisador interessado na área de Aprendizado Profundo e Processamento de Linguagem Natural e atualmente cursando pós-graduação em Inteligência Artificial.

Image Source

  1. Image 1: https://becominghuman.ai/cifar-10-image-classification-fd2ace47c5e8
  2. Imagem 2: https://www.analyticsvidhya.com/blog/2021/05/convolutional-neural-networks-cnn/

Sinta-se à vontade para se conectar comigo em:

  1.  Linkedin: https://www.linkedin.com/in/siddharth-m-426a9614a/
  2.  Github: https://github.com/Siddharth1698

As mídias mostradas neste artigo não são propriedade da Analytics Vidhya e são usadas a critério do autor.

Fonte: https://www.analyticsvidhya.com/blog/2021/09/convolutional-neural-network-pytorch-implementation-on-cifar10-dataset/

Carimbo de hora:

Mais de Análise Vidhya