Criar redes neurais convolucionais (CNNs) para aprimorar a visão computacional
Sobre este codelab
1. Antes de começar
Neste codelab, você aprenderá a usar CNNs para melhorar seus modelos de classificação de imagens.
Pré-requisitos
Este codelab baseia-se no trabalho concluído em duas parcelas anteriores, Criar um modelo de visão computacional, em que introduzimos parte do código que será usado aqui, e o codelab Criar convoluções e executar o pool, onde apresentamos as convoluções e o pool.
O que você aprenderá
- Como melhorar a visão e a acurácia do computador com convoluções
O que você vai criar
- Camadas para melhorar sua rede neural
O que é necessário
O código do restante do codelab está sendo executado no Colab.
Você também precisará do TensorFlow instalado e das bibliotecas instaladas no codelab anterior.
2. Melhorar a precisão da visão computacional com convoluções
Agora você sabe fazer reconhecimento de imagens de moda usando uma rede neural profunda (DNN, na sigla em inglês) com três camadas: a camada de entrada (na forma dos dados de entrada), a camada de saída (na forma da saída desejada) e uma camada oculta. Você testou vários parâmetros que influenciam a precisão final, como tamanhos diferentes de camadas ocultas e o número de períodos de treinamento.
Por conveniência, aqui está todo o código novamente. Execute-o e anote a precisão do teste exibida no final.
import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))
Sua precisão é, aproximadamente, 89% no treinamento e 87% na validação. Você pode tornar isso ainda melhor usando convoluções, que restringem o conteúdo da imagem para se concentrar em detalhes específicos e distintos.
Se você já fez o processamento de imagem usando um filtro, as convoluções parecerão muito familiares.
Em resumo, você transmite uma matriz (geralmente 3 x 3 ou 5 x 5) para a imagem. Ao alterar os pixels subjacentes com base na fórmula dentro da matriz em questão, é possível realizar operações como a detecção de borda. Por exemplo, normalmente um 3 x 3 é definido para detecção de borda em que a célula do meio é 8, e todos os vizinhos são -1. Nesse caso, para cada pixel, é necessário multiplicar o valor por 8 e depois subtrair o valor de cada vizinho. Faça isso para cada pixel e você terá uma nova imagem com bordas melhoradas.
Isso é perfeito para visão computacional, porque aprimorar recursos como as bordas ajuda o computador a distinguir um item de outro. Melhor ainda, a quantidade de informações necessárias é muito menor, porque você treinará somente nos recursos destacados.
Esse é o conceito de redes neurais convolucionais. Adicione algumas camadas para convoluir antes que haja camadas densas. Depois, as informações enviadas a elas ficarão mais focadas e possivelmente mais precisas.
3. Teste o código
Execute o código a seguir. É a mesma rede neural que antes, mas, desta vez, as camadas convolucionais foram adicionadas primeiro. Esse processo levará mais tempo, mas observe o impacto na precisão:
import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))
É provável que tenha aumentado 93% nos dados de treinamento e 91% nos dados de validação.
Agora, execute-o por mais períodos, por exemplo, 20, e analise os resultados. Os resultados do treinamento podem parecer muito bons, mas os de validação podem falhar devido a um fenômeno chamado overfitting (link em inglês).
O overfitting ocorre quando a rede aprende muito bem os dados do conjunto de treinamento. Por isso, ela é especializada para reconhecer somente esses dados e, como resultado, é menos eficaz para ver outros dados em situações mais gerais. Por exemplo, se você treinou apenas calcanhar, a rede pode ser muito boa em identificar saltos, mas os tênis podem confundir.
Veja o código novamente e confira o passo a passo para criar as convoluções.
4. Coletar os dados
A primeira etapa é coletar os dados.
Você perceberá uma mudança aqui e os dados de treinamento precisarão ser remodelados. Isso ocorre porque a primeira convolução espera um único tensor contendo tudo. Portanto, em vez de 60.000 itens de 28 x 28 x 1 em uma lista, você tem uma única lista 4D de 60.000 x 28 x 28 x 1 e a mesma para as imagens de teste. Se você não fizer isso, receberá um erro ao treinar porque as convoluções não reconhecem a forma.
import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images = training_images/255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images/255.0
5. Definir o modelo
Em seguida, defina o modelo. Em vez da camada de entrada na parte superior, você adicionará uma camada convolucional. Os parâmetros são:
- O número de convoluções que você quer gerar. Um valor como 32 é um bom ponto de partida.
- É o tamanho da matriz convolucional, neste caso uma grade 3 x 3.
- A função de ativação a ser usada. Neste caso, use
relu
. - Na primeira camada, a forma dos dados de entrada.
Você seguirá a convolução com uma camada máxima de pooling, que é projetada para comprimir a imagem enquanto mantém o conteúdo dos recursos que foram destacados pela convolução. Ao especificar (2,2) o pool máximo, o efeito é reduzir o tamanho da imagem em um fator de 4. Ele cria uma matriz de 2 x 2 pixels e escolhe o maior valor de pixel, transformando 4 pixels em 1. Isso repete a computação pela imagem e, assim, reduz pela metade o número de pixels horizontais.
Você pode chamar model.summary()
para ver o tamanho e o formato da rede. Depois de cada camada de pool máxima, o tamanho da imagem é reduzido da seguinte maneira:
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_2 (Conv2D) (None, 26, 26, 64) 640 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 13, 13, 64) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 11, 11, 64) 36928 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64) 0 _________________________________________________________________ flatten_2 (Flatten) (None, 1600) 0 _________________________________________________________________ dense_4 (Dense) (None, 128) 204928 _________________________________________________________________ dense_5 (Dense) (None, 10) 1290 =================================================================
Veja o código completo da CNN:
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
#Add another convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
#Now flatten the output. After this you'll just have the same DNN structure as the non convolutional version
tf.keras.layers.Flatten(),
#The same 128 dense layers, and 10 output layers as in the pre-convolution example:
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
6. Compile e treine o modelo
Compile o modelo, chame o método fit para fazer o treinamento e avalie a perda e a acurácia do conjunto de teste.
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_acc*100))
7. Visualizar as convoluções e os pools
Esse código mostra as convoluções graficamente. O print (test_labels[:100])
mostra os primeiros 100 rótulos no conjunto de teste, e é possível ver que aqueles no índice 0, 23 e 28 têm o mesmo valor (9). Todos são calçados. Observe o resultado da execução da convolução em cada um para começar a ver os recursos comuns entre eles. Agora, quando a DNN está treinando com esses dados, ela está trabalhando com muito menos informações e pode estar encontrando a comum entre os sapatos com base nessa combinação de convolução e pool.
print(test_labels[:100])
[9 2 1 1 6 1 4 6 5 7 4 5 7 3 4 1 2 4 8 0 2 5 7 9 1 4 6 0 9 3 8 8 3 3 8 0 7 5 7 9 6 1 3 7 6 7 2 1 2 2 4 4 5 8 2 2 8 4 8 0 7 7 8 5 1 1 2 3 9 8 7 0 2 6 2 3 1 2 8 4 1 8 5 9 5 0 3 2 0 6 5 3 6 7 1 8 0 1 4 2]
Agora você pode selecionar algumas das imagens correspondentes para esses rótulos e renderizar como elas serão exibidas pelas convoluções. Portanto, no código a seguir, FIRST_IMAGE
, SECOND_IMAGE
e THIRD_IMAGE
são todos os índices do valor 9, uma inicialização do tornozelo.
import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 6
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[0,x].grid(False)
f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[1,x].grid(False)
f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[2,x].grid(False)
Você verá algo parecido com o exemplo a seguir, em que a convolução está assumindo a essência da sola do sapato, identificando-a efetivamente como uma característica comum entre todos os sapatos.
8. Exercícios
Exercício 1
Tente editar as convoluções. Mude o número de convoluções de 32 para 16 ou 64. Qual é o impacto disso na precisão e no tempo de treinamento?
Exercício 2
Remova a convolução final. Qual é o impacto disso na precisão ou no tempo de treinamento?
Exercício 3
Adicionar mais convoluções. Qual é o impacto disso?
Exercício 4
Remova todas as convoluções, exceto a primeira. Qual é o impacto disso? Faça testes.
9. Parabéns
Você criou sua primeira CNN. Para saber como aprimorar ainda mais seus modelos de visão computacional, consulte Usar redes neurais convolucionais (CNNs) com imagens complexas.