Manual

do

Maker

.

com

Rede neural com Keras (mais anotações)

Rede neural com Keras (mais anotações)

Rede Neural com keras

Como estou estudando continuamente esse mundo, decidi transformar meus estudos em artigos de anotações. É mais ou menos como estudar em grupo; o tema é lançado e cada um contribui com seu pouco. Meu pouco hoje é sobre a construção de uma rede Neural com keras (uma simples).

O que é Keras

Keras é uma biblioteca para rede neural de alto-nível escrita em Python e roda como frontend em TensorFlow ou Theano. O bacana disso é que você pode substituir uma rede neural por outra utilizando Keras. Ela foi desenvolvida para facilitar experimentações rápidas, isto é, sem que você tenha que dominar cada um dos backgrounds, de maneira rápida e eficiente.

A curta e clara descrição está na página inicial do site do projeto nesse link. A biblioteca é aplicável nas seguintes condições:

  • Prototipagem rápida e fácil (total modularidade, minimalismo e extensibilidade).
  • Suporte a redes convolucionais e recorrentes, incluindo combinação de ambas.
  • Suporte a esquemas de conectividade arbitrária (incluindo treino de N para N).
  • Rodar na CPU ou GPU.

Aplicabilidade

De que adianta tanta teoria sem aplicação? É o que normalmente acontece na escola no primeiro e segundo grau, onde a galera não tem muito incentivo pra gostar de matemática porque não é aplicada. Bem, um dos principais temas do meu site é embarcados e tudo o que escrevo deve ser relacionado. Estou com um robô quadrupede aqui para escrever artigo e pretendo colocar ao menos um pouco de visão computacional nele e para reconhecimento facial, vou utilizar remotamente o OpenFace (desse outro artigo). Devagar vou aplicando em diversas arquiteturas, incluindo Arduino (com o processamento remoto, claro), mas acompanhe os artigos precedentes, apenas como uma leitura de apreciação, caso não queira executar nenhum dos exercícios.

Testes iniciais dos tutoriais de deep learning

Alguns tutoriais virão de estudo das respectivas documentações, outros de tutoriais modificados e outros, de livros. Os de livros sempre são mais elaborados e cheios de minúcias, mas farei com que sejam breves e claros o suficiente, baseado no meu entendimento (que poderá ocasionalemente conter enganos).

Instalação

No tutorial anterior mostrei a instalação do TensorFlow utilizando o virtualenv. Siga o tutorial como primeiro passo e depois incremente a instalação com os próximos passos. Se você já tem o virtualenv com o TensorFlow do artigo anterior, então inicie o ambiente virtual para seguir:

source ~/tensorflow/bin/activate

Se você digitar 'pip search keras' dentro do virtualenv, é capaz de você querer instalar tudo, mas vamos por partes:

pip install Keras learningml scipy

Essa instalação auto-incluirá o Theano, não se assuste.

Os 6 passos finais

Após a instalação, os 6 passos finais são totalmente relacionados ao código, mas se olhar de um modo geral, esse é o último passo. No tutorial que encontrei para fazer o primeiro teste o processo está descrito de forma similar.

Gerar semente e carregar os dados

Essa parte do processo auxiliará a obter os mesmos resultados toda a vez que rodar os testes, de modo que você poderá demonstrar os resultados ou debugar. Isso se resume a 1 única linha, mas como é o começo do código, tem os cabeçalhos e tal:

from keras.models import Sequential
from keras.layers import Dense
import numpy

numpy.random.seed(7)

Esse tutorial que me baseei utiliza um conjunto de dados de 5 anos de estudo de diabetes hereditária (esse aqui) feito com meninas de 21 anos de idade. A classificação é binária, onde diabetes é 1 e a negativa é 0. Acredito que a escolha tenha se baseado nesse fator pela facilidade de redirecionar esses dados para a rede neural. Baixe o conjunto de dados e coloque-o em seu diretório de trabalho, juntamente ao arquivo de código que estamos escrevendo.

wget -c http://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data 
mv pima-indians-diabetes.data pima-indians-diabetes.csv

O arquivo será carregado completamente para a memória e então manipulado. Nesse ponto você já deve ter percebido que para um largo número de dados será necessária uma quantidade vasta de memória, exceto suas manipulações adotem outro meio. Para esse tutorial, não teremos problemas com esse conjunto de dados. As próximas linhas de código dividem o conjunto de dados em entradas e saídas (X e Y, respectivamente):

dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
X = dataset[:,0:8]
Y = dataset[:,8]

Definição do modelo de dados

Os modelos em Keras são definidos como uma sequência de camadas. Ainda entraremos em detalhes sobre modelos e classificadores em outro artigo, por ora vamos manter o foco no tutorial. Isto facilita a criação do modelo, bastando inserir uma camada por vez até que estejamos satisfeitos com a topologia da rede. Tudo ficará mais claro, apenas acompanhe a leitura para assimilar as ideias e assim podermos em breve construir algo para embarcados.

A primeira coisa a se fazer é garantir que a camada de entrada tem o número correto de inputs. Isto pode ser especificado enquanto criando a primeira camada com o argumento 'input_dim',  atribuindo-lhe 8, para o variáveis de entrada.

Existe uma questão muito difícil a considerar, que é o número de camadas e seus tipos. O método heurístico certamente é uma grande opção para encontrar a melhor estrutura de rede, mas o problema é que você precisará de tempo para aprender a fazer tunnings. Por exemplo, quando iniciei minhas pesquisas em reconhecimento facial, passei por uma série complexa de experimentação até que (graças a Deus) iniciei experimentos com o OpenFace. Apesar de ser uma caixa de mágicas, levou praticamente um mês até que eu compreendesse alguns níveis importantes dessa estrutura para então chegar a 100% de confiabilidade em uma base de 40 pessoas. Conforme a base aumenta, a confidência diminui, mas nada mal chegar a 100% em uma base de treinamento com poucos minutos de sua criação.

No exemplo que peguei com Keras, a estrutura de rede é fully-connected com 3 camadas. Isto é, todos os neurônios se comunicam antes da saída.

Nós podemos especificar o número de neurônios na camada como primeiro argumento, o método de inicialização como segundo argmento sendo 'init' e especificar a funão de ativação utilizando o argumento 'activation'.

Neste caso, nós inicializamos o peso da rede para um pequeno número randômico gerado a partir de uma distribuição uniforme ('uniform'), entre 0 e 0.05, nesse caso, porque esse é o peso padrão da distribuição uniforme no Keras. Uma alternativa tradicional seria o 'normal', gerando assim pequenos números randômicos a partir de uma distribuição gaussiana.

Também será usada a função retificadora 'relu' nas primeiras duas camadas e a função sigmoide na camada de saída. O resultado deverá ser algo entre 0 e 1 com um threshold  padrão de 0.5.

Enfim, montando o código, você pode notar que a primeira camada tem 12 neurôniose espera 8 variáveis de entrada. A segunda camada  possui 8 neurônios e finalmente a saída tem 1 neurônio fazendo a predição da classe alvo (início de diabetes ou não).

model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))

Compilação do modelo

A compilação do mdelo usa uma eficiente biblioteca numérica de backend, como Theano or TensorFlow. O backend automaticamente escolhe o melhor caminho para representar a rede e fazer predições.

Será necessário em algum momento especificar a função de per para avaliar os pesos. Nesse exemplo foi definido o uso da função de perda logarítmica, definido em Keras como "binary_crossentropy". Também é utilizado o algorítmo gradiente de descida 'adam'. Repare que diversos nomes foram utilizados nos últimos parágrafos. Essas são as maiores dificuldades para iniciar-se em redes neurais e visão computacional, porque é necessário ter ao menos uma noção do que se trata, para poder posteriormente aplicá-las conforme a necessidade surgir. Eu estou baseando-me em um post de terceiro (em inglês, referenciado ao final do artigo) para ter o primeiro contato e a partir daí, aprender de uma forma mais suave. Isso significa que você não encontrará fórmulas prontas para todas as suas necessidades, mas você deverá sim criar suas próprias "receitas". Ocasionalmente, alguns padrões podem trazer resultados satisfatórios.

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

Ajuste ou treino

Nós podemos fazer essa tarefa com o método '.fit()' do modelo para ajustar o número de iterações, utilizando o argumento nb_epoch. Por fim, com 'batch_size' ajustamos o número de instâncias. Esses valores podem ser ajustados por tentativa e erro:

model.fit(X, Y, nb_epoch=150, batch_size=10)

Avaliando o modelo

O treinamento da rede neural foi feita sobre o conjunto completo de dados e a performance da rede neural pode ser avaliada no mesmo conjunto de dados, o que nos dará uma boa ideia do quão bem modelada foi a rede. Mais que óbvio,  utiliza-se a função evaluate() no modelo, passando o mesmo núermo de inputs e outputs usados no treinamento. Isto gerará uma predição para cada entrada e saída e coletará pontuação, incluindo média de perda e qualquer métrica que tenha sido configurada, como a acurácia.

scores = model.evaluate(X, Y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

Atando os nós

O tutorial no qual me baseei mostrou o quão fácil pode ser modelar uma rede neural com Keras (claro que isso não significa que sua rede neural será supimpa sem os devidos ajustes e experimentações). Colocando todo o código junto, o resultado é isso:

# Create first network with Keras
from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, nb_epoch=150, batch_size=10)
# evaluate the model
scores = model.evaluate(X, Y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

São 24 linhas, incluindo os comentários!

Utilizando o modelo em um novo conjunto de dados

O tutorial no qual me baseei adicionou mais duas linhas de código para gerar novas previsões, resultando nesse código:

# Create first network with Keras
from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, nb_epoch=150, batch_size=10,  verbose=2)
# calculate predictions
predictions = model.predict(X)
# round predictions
rounded = [round(x) for x in predictions]
print(rounded)

Se manja de inglês e quer um bom site como referência, sugiro o site desse tutorial em que me baseei para escrever esse post.

Algumas informações sobre o Keras eu peguei no site oficial.

A saída da execução do código de exemplo, mas utilizando TensorFlow como backend (do artigo anterior) é algo como:

keras1.webp

Esse foi apenas um primeiro contato, em breve teremos artigos aplicáveis aos nossos embarcados, nãodeixe de acompanhar.

Uma novidade por aqui é que agora contaremos com o mestre do OpenCV e redes neurais, Leonardo Lontra, que tem sido meu mentor nessa empreitada, já tendo me tirado de diversos sufocos ao longo dos últimos 5 meses. Ele escreverá esporadicamente, conforme o que lhe der vontade, sendo técnico ou não, guiado por sua inspiração. E sinceramente, espero que ele se inspire muito para escrever artigos.

 

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.