Um guia prático para construir seu primeiro modelo de rede neural convolucional

Conteúdo

Este artigo foi publicado como parte do Data Science Blogathon

Visão geral

Este artigo discutirá brevemente a CNN, uma variante especial de redes neurais projetadas especificamente para tarefas relacionadas a imagens. O artigo se concentrará principalmente na parte de implementação da CNN. Todo esforço foi feito para tornar este artigo interativo e direto.. Espero que gostem. Boas aprendizagens !!

97717gatos-cães-classificação-aprendizagem profunda-1501313

Fonte da imagem

Introdução

As redes neurais convolucionais foram introduzidas por Yann LeCun e Yoshua Bengio no ano 1995 que mais tarde foi mostrado para mostrar resultados excepcionais no domínio das imagens. Então, O que os torna especiais em comparação com as redes neurais comuns, quando aplicados no domínio da imagem? Vou explicar uma das razões com um exemplo simples. Observe que você recebeu a tarefa de classificar imagens de dígitos manuscritos e que alguns conjuntos de treinamento de amostra são mostrados abaixo.

17125dígitos-8105946

Fonte da imagem

Se você observar corretamente, você pode descobrir que todos os dígitos aparecem no centro das respectivas imagens. Treinar um modelo de rede neural normal com essas imagens pode dar um bom resultado se a imagem de teste for de um tipo semelhante. Mas, E se a imagem de teste for como abaixo?

83083digit_resized-5205563

Fonte da imagem

Aqui o número nove aparece no canto da imagem. Se usarmos um modelo de rede neural simples para classificar esta imagem, nosso modelo pode falhar abruptamente. Mas se a mesma imagem de teste for dada a um modelo da CNN, é muito provável que seja classificado corretamente. A razão para o melhor desempenho é que ele procura características espaciais na imagem. Para o caso acima em si, mesmo se o número nove estiver no canto esquerdo do quadro, o modelo treinado da CNN captura os recursos da imagem e provavelmente prevê que o número é o dígito nove. Uma rede neural normal não pode fazer esse tipo de mágica. Agora vamos discutir brevemente os principais blocos de construção da CNN.

Principais componentes da arquitetura de um modelo CNN

34881cnn_architecture_1-9806946

Fonte da imagem

Este é um modelo simples de CNN criado para classificar se a imagem contém um gato ou não. Então, os principais componentes de uma CNN são:

1. Capa convolucional

2. Camada de agrupamento

3.Camada totalmente conectada

Capa convolucional

As camadas convolucionais nos ajudam a extrair os recursos que estão presentes na imagem. Essa extração é realizada com a ajuda de filtros. Observe a seguinte operação.

36813convolution_overview-6828931

Fonte da imagem

Aqui podemos ver que uma janela desliza sobre a imagem inteira, onde a imagem é renderizada como uma grade (É assim que o computador vê as imagens em que as grades são preenchidas com números!!). Agora vamos ver como os cálculos são realizados na operação de convolução.

89792convolution_example-1304619

Fonte da imagem

Suponha que o mapa de características de entrada seja a nossa imagem e que o filtro convolucional seja a janela na qual vamos deslizar. Agora vamos dar uma olhada em uma das instâncias da operação de convolução.

578272021-07-202023_09_31-ml20practicum_20image20classification20c2a0_c2a020google20developers-1471699

Fonte da imagem

Quando o filtro de convolução é sobreposto na imagem, os respectivos elementos são multiplicados. Mais tarde, os valores multiplicados são adicionados para obter um único valor que é preenchido no mapa de recursos de saída. Esta operação continua até que deslizemos a janela pelo mapa de características de entrada., preenchendo assim o mapa de características de saída.

Camada de agrupamento

A ideia por trás do uso de uma camada de agrupamento é reduzir a dimensão do mapa de feições. Para a representação dada abaixo, usamos uma camada de agrupamento máximo de 2 * 2. Cada vez que a janela desliza sobre a imagem, pegamos o valor máximo presente na janela.

66402maxpool_animation-3565648

Fonte da imagem

Finalmente, após operação máxima do grupo, podemos ver aqui que a dimensão da entrada, quer dizer, 4 * 4, foi reduzido a 2 * 2.

Camada totalmente conectada

Esta camada está presente na seção final da arquitetura do modelo CNN, como visto antes. A entrada para a camada totalmente conectada são os ricos recursos que foram extraídos por filtros convolucionais. Isso então se propaga para a camada de saída, onde obtemos a probabilidade de que a imagem de entrada pertença a diferentes classes. O resultado previsto é a classe com a maior probabilidade de que o modelo tenha previsto.

Implementação de código

Aqui, consideramos o Fashion MNIST como nosso conjunto de dados de problemas. O conjunto de dados contém camisetas, calça, agasalho, vestidos, casacos, sandálias de dedo, camisas, sapatos, bolsas e sapatinhos. A tarefa é classificar uma determinada imagem nas classes acima mencionadas após treinar o modelo.

61674fashion20mnist20dataset-5124604

Fonte da imagem

Vamos implementar o código no Google Colab, uma vez que fornecem o uso de recursos GPU gratuitos por um período fixo de tempo. Se você é novo no ambiente Colab e GPUs, verifique este blog para ter uma ideia melhor. Abaixo está a arquitetura da CNN que iremos construir.

92912inkedoverlayed_li-4824968

Paso 1: Importe as bibliotecas necessárias

importar os
importar tocha
importar torchvision
importar tarfile
de transformações de importação de torchvision
de torch.utils.data import random_split
de torch.utils.data.dataloader import DataLoader
import torch.nn as nn
de torch.nn importar funcional como F
da cadeia de importação de itertools

Paso -2: Baixando o conjunto de dados de teste e treinamento

train_set = torchvision.datasets.FashionMNIST("/usr", download = True, transformar =
                                                transforms.Compose([transforms.ToTensor()]))
test_set = torchvision.datasets.FashionMNIST("./dados", download = True, train = False, transformar =
                                               transforms.Compose([transforms.ToTensor()]))

Paso 3 Divisão do conjunto de treinamento para treinamento e validação

train_size = 48000
val_size = 60000 - train_size
train_ds,val_ds = random_split(conjunto de trem,[train_size,val_size])

Paso 4 Carregue o conjunto de dados na memória usando o Dataloader

train_dl = DataLoader(train_ds,batch_size = 20, shuffle = True)
val_dl = DataLoader(val_ds,batch_size = 20, shuffle = True)
classes = train_set.classes

Agora vamos visualizar os dados carregados,

para imgs,rótulos em train_dl:
  para img em imgs:
    arr_ = np.squeeze(img) 
    plt.show()
    pausa
  pausa
68552batch20data20visualization-1348502

Paso -5 Definindo a arquitetura

import torch.nn as nn
import torch.nn.functional as F
# definir a arquitetura CNN
classe Net(nn.Module):
    def __init__(auto):
        super(Internet, auto).__iniciar__()
        #camada convolucional-1
        self.conv1 = nn.Conv2d(1,6,5, preenchimento = 0)
        #camada convolucional-2
        self.conv2 = nn.Conv2d(6,10,5,preenchimento = 0)
        # camada de pooling máxima
        self.pool = nn.MaxPool2d(2, 2)
        # Camada totalmente conectada 1
        self.ff1 = nn.Linear(4*4*10,56)
        # Camada totalmente conectada 2
        self.ff2 = nn.Linear(56,10)
    def frente(auto, x):
        # adição de sequência de camadas convolucionais e de pooling máximo
        #input dim-28 * 28 * 1
        x = self.conv1(x)
        # Após a operação de convolução, saída dim - 24*24*6
        x = self.pool(x)
        # Após a saída máxima da operação da piscina dim - 12*12*6
        x = self.conv2(x)
        # Após a saída da operação de convolução dim - 8*8*10
        x = self.pool(x)
        # saída máxima da piscina dim 4*4*10
        x = x.view(-1,4*4*10) # Remodelar os valores para uma forma apropriada para a entrada da camada totalmente conectada
        x = F.relu(self.ff1(x)) # Aplicando Relu à saída da primeira camada
        x = F.sigmoid(self.ff2(x)) # Aplicando sigmóide à saída da segunda camada
        retornar x

# criar uma CNN completa
model_scratch = Net()
imprimir(modelo)
# mover tensores para GPU se CUDA estiver disponível
se use_cuda:
    model_scratch.cuda()

Paso 6: definição de função de perda

# Função de perda
import torch.nn as nn
import torch.optim as optim
criterion_scratch = nn.CrossEntropyLoss()
def get_optimizer_scratch(modelo):
    optimizer = optim.SGD(model.parameters(),lr = 0.04)
    otimizador de retorno

Paso 7: implementação do algoritmo de treinamento e validação

# Implementando o algoritmo de treinamento
trem def(n_epochs, carregadores, modelo, otimizador, critério, use_cuda, save_path):
    """devolve modelo treinado"""
    # inicializar rastreador para perda mínima de validação
    valid_loss_min = np.Inf
    para época no intervalo(1, n_epochs + 1):
        # inicializar variáveis ​​para monitorar a perda de treinamento e validação
        train_loss = 0.0
        valid_loss = 0.0
        # fase de trem #
        # configurando o módulo para o modo de treinamento
        model.train()
        para batch_idx, (dados, alvo) em enumerar(carregadores['Comboio']):
            # mover para GPU
            se use_cuda:
                dados, target = data.cuda(), target.cuda()
            optimizer.zero_grad()
            output = model(dados)
            perda = critério(saída, alvo)
            loss.backward()
            optimizer.step()
            train_loss = train_loss + ((1 / (batch_idx + 1)) * (loss.data.item() - perda de trem))
        # validar o modelo #
        # defina o modelo para o modo de avaliação
        model.eval()
        para batch_idx, (dados, alvo) em enumerar(carregadores['válido']):
            # mover para GPU
            se use_cuda:
                dados, target = data.cuda(), target.cuda()
            output = model(dados)
            perda = critério(saída, alvo)
            valid_loss = valid_loss + ((1 / (batch_idx + 1)) * (loss.data.item() - valid_loss))
# imprimir estatísticas de treinamento / validação
        imprimir('Época: {} t Perda de treinamento: {:.6f} tValidation Loss: {:.6f}'.formato(
            época, 
            perda de trem,
            valid_loss
            ))
## Se a perda de valiação diminuiu, então salvando o modelo
        if valid_loss <= valid_loss_min:
            imprimir('Perda de validação diminuída ({:.6f} --> {:.6f}).  Salvando modelo ... '. Formato(
            valid_loss_min,
            valid_loss))
            torch.save(model.state_dict(), save_path)
            valid_loss_min = valid_loss
    modelo de retorno

Paso 8: Fase de treinamento e avaliação

num_epochs = 15
model_scratch = train(num_epochs, loaders_scratch, model_scratch, get_optimizer_scratch(model_scratch), 
                      criterion_scratch, use_cuda, 'model_scratch.pt')
71233treinamento 20 e 20 validação 20 fase-5227760

Observe que, a cada vez que a perda de validação diminui, estamos salvando o estado do modelo.

Paso 9 Fase de teste

teste de def(carregadores, modelo, critério, use_cuda):
# monitorar a perda e a precisão do teste
    test_loss = 0.
    correto = 0.
    total = 0.
# defina o módulo para o modo de avaliação
    model.eval()
    para batch_idx, (dados, alvo) em enumerar(carregadores['teste']):
          # mover para GPU
          se use_cuda:
            dados, target = data.cuda(), target.cuda()
          # Passar para a frente: computar saídas previstas passando entradas para o modelo
          output = model(dados)
          # calcular a perda
          perda = critério(saída, alvo)
          # atualizar perda média de teste
          test_loss = test_loss + ((1 / (batch_idx + 1)) * (loss.data.item() - test_loss))
          # converter probabilidades de saída em classe prevista
          pred = output.data.max(1, keepdim = True)[1]
          # compare as previsões com o rótulo verdadeiro
        correto + = np.sum(np.squeeze(pred.eq(target.data.view_as(pred)),eixo = 1).CPU().entorpecido())
        total + = data.size(0)
 imprimir('Perda de teste: {:.6f}n'.format(test_loss))
imprimir(Precisão do 'nTest: %2d %% (%2d/-)' % (
        100. * correto / total, correto, total))
# carregue o modelo que obteve a melhor precisão de validação
model_scratch.load_state_dict(torch.load('model_scratch.pt'))
teste(loaders_scratch, model_scratch, criterion_scratch, use_cuda)
98117test_phase-2728290

Paso 10 Teste com uma amostra

A função definida para testar o modelo com uma única imagem.

def Predict_image(img, modelo):
    # Converter para um lote de 1
    xb = img.unsqueeze(0)
    # Obtenha previsões do modelo
    yb = modelo(xb)
    # Escolha o índice com maior probabilidade
    _, preds = tocch.max(yb, dim = 1)
    # imprimindo a imagem
    plt.imshow(img.squeeze( ))
    #retornando o rótulo da classe relacionado à imagem
    return train_set.classes[preds[0].item()]
img,label = test_set[9]
Predict_image(img,model_scratch)
46606single20test20case-1771345

conclusão

Aqui, discutimos brevemente as principais operações em uma rede neural convolucional e sua arquitetura. Um modelo de rede neural convolucional simples também foi implementado para dar uma ideia melhor do caso de uso prático. Você pode encontrar o código implementado em meu Repositório GitHub. O que mais, você pode melhorar o desempenho do modelo implantado aumentando o conjunto de dados, usando técnicas de regularização, como normalização em lote e abandono em camadas totalmente conectadas da arquitetura. O que mais, observe que modelos CNN pré-treinados também estão disponíveis, que foram treinados com grandes conjuntos de dados. Usando esses modelos de última geração, você sem dúvida alcançará as melhores pontuações métricas para um determinado problema.

Referências

  1. https://www.youtube.com/watch?v = EHuACSjijbI – Jovian
  2. https://www.youtube.com/watch?v = 2-Ol7ZB0MmU&t = 1503s- Uma introdução amigável a redes neurais convolucionais e reconhecimento de imagem

Sobre o autor

Meu nome é adwait dathan, Atualmente, estou cursando meu mestrado em Inteligência Artificial e Ciência de Dados. Sinta-se à vontade para se conectar comigo por meio Linkedin.

A mídia mostrada neste artigo não é propriedade da DataPeaker e é usada a critério do autor.

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.