Conteúdo[Esconder][Mostrar]
O cérebro é comparável às redes neurais. Essa é a analogia que normalmente é usada para ajudar alguém novo no assunto a entender as ideias por trás do aprendizado de máquina e das redes neurais artificiais.
Como existem várias camadas de cálculos matemáticos e estatísticos acontecendo nos bastidores, definir essas redes como uma função matemática é um método mais avançado.
Isto é para as pessoas que estão realmente interessadas em aprendizado de máquina e querem ver como o código de rede neural Python é escrito.
Neste artigo, demonstraremos como construir uma rede neural profunda (DNN) totalmente conectada a partir do zero em Python 3.
Uma visão geral da estrutura de arquivos para nosso código de rede neural Python
Haverá três arquivos criados aqui. O primeiro é o arquivo nn.py simples, que será discutido em “Configurando funções auxiliares” e “Construindo a rede neural do zero”.
Teremos também um arquivo chamado mnist loader.py para carregar os dados de teste, conforme descrito em “Carregando dados MNIST”.
Por fim, teremos um arquivo chamado test.py que será lançado no terminal para testar nossa rede neural.
Este arquivo é descrito em detalhes em “Executando Testes”.
Instalação
A biblioteca NumPy Python deve ser baixada para seguir este tutorial. Você pode fazer isso usando o seguinte comando no terminal:
Importando Módulos e configurando a função Helper
As únicas duas bibliotecas que precisamos são random e NumPy, que importaremos imediatamente. Para os pesos iniciais da nossa rede neural, vamos embaralhá-los usando a biblioteca aleatória.
Para acelerar nossos cálculos, usaremos NumPy ou np (por convenção, geralmente é importado como np). Nossas duas funções auxiliares serão feitas após nossas importações. Duas funções sigmoid: one e sigmoid prime.
A regressão logística classificará os dados usando a função sigmoid, enquanto a retropropagação calculará o delta ou gradiente usando a função sigmoid prime.
Criando classe de rede
Construir uma rede neural totalmente vinculada é o único foco desta seção. A classe de rede abrangerá todas as funções que vêm depois. A função Object() { [código nativo] } será criada inicialmente em nossa classe de rede.
Um argumento, tamanhos, é requerido pela função Object() { [código nativo] }. A variável de tamanhos é uma coleção de valores numéricos que representa o número de nós de entrada presentes em cada camada de nossa rede neural.
Inicializamos quatro propriedades em nosso método __init__. As variáveis de entrada, tamanhos, são usadas para definir a lista de tamanhos de camada e o número de camadas, num camadas, respectivamente.
O primeiro passo é atribuir aleatoriamente os vieses iniciais de nossa rede para cada camada que segue a camada de entrada.
Por fim, cada link entre as camadas de entrada e saída tem seus pesos gerados aleatoriamente. Np.Random.Randn() fornece uma amostra aleatória extraída da distribuição normal para o contexto.
Função de avanço
Em uma rede neural, as informações são enviadas pela função feedforward. Um argumento, a, indicando o vetor de ativação atual, será requerido por esta função.
Essa função estima as ativações em cada camada iterando sobre todas as tendências e pesos na rede. A resposta dada é a previsão, que são as ativações da última camada.
Descida de gradiente de minilote
O cavalo de batalha da nossa classe Network é Gradient Descent. Nesta versão, usamos gradiente descendente mini-lote (estocástico), uma variação modificada do gradiente descendente.
Isso indica que um pequeno lote de pontos de dados será usado para atualizar nosso modelo. Quatro argumentos obrigatórios e um opcional são passados para este método. As quatro variáveis necessárias são o conjunto de dados de treinamento, o número de épocas, o tamanho dos mini-lotes e a taxa de aprendizado (eta).
Os dados de teste estão disponíveis mediante solicitação. Forneceremos dados de teste quando avaliarmos essa rede. O número de amostras nesta função é inicialmente definido para o comprimento da lista, uma vez que os dados de treinamento tenham sido transformados em um tipo de lista.
Também aplicamos o mesmo processo para testar os dados fornecidos. Isso ocorre porque, em vez de nos retornarem como listas, eles são realmente zips de listas. Quando carregarmos as amostras de dados MNIST posteriormente, aprenderemos mais sobre isso.
Se pudermos garantir que fornecemos os dois tipos de dados como listas, essa conversão de tipos não é necessariamente essencial.
Uma vez que temos os dados, passamos pelas épocas de treinamento em um loop. Um período de treinamento é apenas uma rodada de treinamento de rede neural. Primeiro, embaralhamos os dados em cada época para garantir aleatoriedade antes de fazer uma lista de minilotes.
A função de atualização de minilote, discutida abaixo, será chamada para cada minilote. A precisão do teste também será retornada se os dados do teste estiverem disponíveis.
Função auxiliar de derivação de custo
Vamos desenvolver uma função auxiliar chamada derivada de custo antes de realmente criarmos o código de retropropagação. Se cometermos um erro em nossa camada de saída, a função derivada de custo o mostrará.
Ele requer duas entradas: a matriz de ativações de saída e as coordenadas y dos valores de saída antecipados.
Função de retropropagação
Nosso presente vetor de ativação, ativação, bem como quaisquer outros vetores de ativação, ativações e vetores z, zs, devem ser mantidos em mente. Uma camada chamada camada de entrada é ativada primeiro.
Passaremos por cada viés e peso depois de colocá-los. Cada loop envolve o cálculo do vetor z como o produto escalar dos pesos e a ativação, adicionando-o à lista de zs, recalculando a ativação e adicionando a ativação atualizada à lista de ativações.
Por fim, a matemática. O delta, que é igual ao erro da camada anterior multiplicado pelo primo sigmóide do último elemento dos vetores zs, é calculado antes de iniciarmos nossa passagem para trás.
A última camada de nabla b é definida como o delta, e a camada final de nabla w é definida como o produto escalar do delta e a penúltima camada de ativações (transposta para que possamos realmente fazer as contas) .
Procedemos como antes, começando com a segunda camada e concluindo com a última, e repetimos o processo após completar essas últimas camadas. As nablas são então devolvidas como uma tupla.
Atualizando a descida de gradiente de minilote
Nosso método SGD (descida de gradiente estocástico) de antes incorpora atualização de mini-lote. Como é utilizado no SGD, mas também requer backprop, debati onde colocar essa função.
Por fim, resolvi postar aqui. Ele começa gerando 0 vetores dos nablas de bias e weights, assim como nossa função backprop fez.
Ele requer o mini-lote e a taxa de aprendizado eta como suas duas entradas. No mini-lote, usamos a função backprop para obter o delta de cada array nabla para cada entrada, x, e saída, y. As listas nabla são então atualizadas com esses deltas.
Por fim, usamos a taxa de aprendizado e os nablas para atualizar os pesos e vieses da rede. Cada valor é atualizado para o valor mais recente, menos a taxa de aprendizado, multiplicado pelo tamanho do minilote e adicionado ao valor nabla.
Avalie a função
A função de avaliação é a última que precisamos escrever. Os dados de teste são a única entrada para esta função. Nesta função, comparamos apenas as saídas da rede com o resultado antecipado, y. Alimentando a entrada, x, para frente, as saídas da rede são determinadas.
Código Completo
Quando combinamos todo o código, é assim que aparece.
Testando a rede neural
Carregando dados MNIST
A Dados MNIST está no formato .pkl.gz, que vamos abrir usando GZIP e carregar com pickle. Vamos escrever um método rápido para carregar esses dados como uma tupla de tamanho três, dividida em dados de treinamento, validação e teste.
Para tornar nossos dados mais fáceis de gerenciar, escreveremos outra função para codificar o y em uma matriz de 10 itens. A matriz será toda 0s, exceto por um 1 que corresponde ao dígito correto da imagem.
Usaremos os dados básicos de carregamento e um método de codificação a quente para carregar nossos dados em um formato legível. Outra função será escrita que converterá nossos valores x em uma lista de tamanho 784, correspondendo aos 784 pixels da imagem, e nossos valores y em sua única forma de vetor codificado a quente.
Em seguida, combinaremos os valores x e y de modo que um índice corresponda ao outro. Isso se aplica aos conjuntos de dados de treinamento, validação e teste. Em seguida, retornamos os dados alterados.
Executando testes
Faremos um novo arquivo chamado “mnist loader” que importará tanto a rede neural que estabelecemos anteriormente (simples nn) quanto o carregador do conjunto de dados MNIST antes de começarmos a testar.
Nesse arquivo, tudo o que precisamos fazer é importar os dados, construir uma rede com um tamanho de camada de entrada de 784 e um tamanho de camada de saída de 10, executar a função SGD da rede nos dados de treinamento e testá-la usando os dados de teste.
Tenha em mente que para nossa lista de camadas de entrada, não faz diferença quais sejam os números entre 784 e 10. Podemos alterar as outras camadas da maneira que quisermos; apenas os tamanhos de entrada e saída são fixos.
Três camadas não são necessárias; podemos usar quatro, cinco ou mesmo apenas dois. Divirta-se experimentando com ele.
Conclusão
Aqui, usando Python 3, criamos uma rede neural do zero. Junto com matemática de alto nível, também discutimos as especificidades da implementação.
Começamos implementando funções auxiliares. Para que os neurônios funcionem, as funções primárias sigmóide e sigmóide são cruciais. Colocamos então em prática a função feedforward, que é o processo fundamental para alimentar os dados na rede neural.
Em seguida, criamos a função gradiente descendente em Python, o mecanismo que impulsiona nossa rede neural. Para localizar “mínimos locais” e otimizar seus pesos e vieses, nossa rede neural usa gradiente descendente. Criamos a função backpropagation usando Gradiente descendente.
Ao fornecer atualizações quando as saídas não correspondem aos rótulos adequados, essa função permite que a rede neural “aprenda”.
Por fim, colocamos nosso novíssimo Python rede neural para o teste usando o conjunto de dados MNIST. Tudo funcionou normalmente.
Boa Codificação!
Deixe um comentário