Join us at TensorFlow World, Oct 28-31. Use code TF20 for 20% off select passes. Register now

Treine a sua primeira rede neural: Classificação Básica

Veja em TensorFlow.org Execute em Google Colab Veja a fonte em GitHub

Este guia treina um modelo de uma rede neural para classificar imagens de roupa, como ténis ou camisolas. Não há problema se não perceber os detalhes, isto é uma revisão rápida de um programa completo em TensorFlow com os detalhes explicados à medida que avançamos.

Este guia usa tf.keras, uma API de alto nivel para construir e treinar modelos em TensorFlow.

from __future__ import absolute_import, division, print_function, unicode_literals, unicode_literals

# TensorFlow e tf.keras
import tensorflow as tf
from tensorflow import keras

# Bibliotecas de ajuda
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
2.0.0-rc1

Importar o dataset Fashion MNIST

Este guia usa a base de dados Fashion MNIST que contém 70.000 imagens a preto e branco de 10 categorias diferentes. As imagens apresentam peças de roupa individuais com pouca resolução (28 por 28 píxeis), como podem ser vistas aqui:

Fashion MNIST sprite
Figure 1. Fashion-MNIST samples (by Zalando, MIT License).
 

Fashion MNIST tem a intenção de substituir a base de dados clássica MNIST, que é usualmente utilizada como "Olá, Mundo" de programas de aprendizagem de máquina para visão computacional. A base de dados MNIST contém imagens de dígitos manuscritos (0, 1, 2, etc) num formato idêntico ao dos artigos de roupa que vamos utilizar aqui.

Este guia utiliza Fashion MNIST para variedade, e porque é um problema ligeiramente mais desafiante do que a MNIST. Ambas as bases de dados são relativamente pequenas e são utilizadas para verificar se os algoritmos trabalham como é esperado. São um bom início para testar e depurar o código.

Vamos utilizar 60.000 imagens para treinar a rede e 10.000 imagens para avaliar quão bem a rede aprendeu a classificar as imagens. Você pode acessar a base de dados Fashion MNIST diretamente a partir do TensorFlow, basta importar os dados:

fashion_mnist = keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 2s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

Carregar a base de dados retorna quatro NumPy arrays:

  • As train_images e train_labels arrays são o training set— os dados que o modelo utiliza para aprender
  • O modelo é testado no test set, os arrays de test_images e os test_labels.

As images são 28x28 Numpy arrays, onde os valores de cada pixel variam entre 0 e 255. Os labels são um vetor de inteiros, que varia entre 0 e 9. Estes correspondem à classe de roupa que a imagem representa:

Label Class
0 T-shirt/top
1 Trouser
2 Pullover
3 Dress
4 Coat
5 Sandal
6 Shirt
7 Sneaker
8 Bag
9 Ankle boot

Cada imagem é mapeada para um único label. Uma vez que os nomes das classes não estão incluídos na base de dados, guardamos aqui para mais tarde usar nos gráficos das images:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

Explorar os dados

Vamos explorar o formato da base de dados antes de treinar o modelo. De seguida, mostra-se que existem 60.000 imagens nos dados de treino, com cada imagem representada com 28x28 píxeis:

train_images.shape
(60000, 28, 28)

De igual forma, existem 60.000 labels no dados de treino:

len(train_labels)
60000

Cada label é um inteiro entre 0 e 9:

train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)

Existem 10.000 imagens nos dados de teste. Cada imagem é novamente representada por 28 x 28 píxeis:

test_images.shape
(10000, 28, 28)

E os dados de teste contém 10.000 labels de image:

len(test_labels)
10000

Pré-processamento dos dados

Os dados devem ser pré-processados antes de treinar a rede. Se observar a primeira imagem dos dados de treino, vai ver que o valor de cada píxel vai estar no intervalo entre 0 e 255:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

png

Nós escalamos estes valores para estarem no intervalo de 0 a 1 antes de entrar no modelo neural. Para isso, dividimos os valores por 255. É importante que os dados de treino e os dados de teste sejam processados da mesma forma:

train_images = train_images / 255.0

test_images = test_images / 255.0

Mostre as primeiras 25 imagens dos dados de treino e a classe a que pertence por baixo de cada imagem. Verifique que os dados estão no formato correto e estamos prontos para contruir e treinar a rede.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

png

Construir o modelo

Construir a rede neural requer a configuração das camadas do modelo, e depois a compilação do modelo.

Configurar as camadas

O bloco básico de uma rede neural é a layer (camada). As camadas extraem representações dos dados que as alimentam. E, esperançosamente, estas representações têm mais significado para o problema em mãos.

A maioria do deep learning consiste em encadear camadas simples. A maioria das camadas, como tf.keras.layers.Dense, têm parâmetros que são aprendidos durante o treino.

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])

A primeira camada desta rede, tf.keras.layers.Flatten, transforma o formato das imagens de um vector 2D (de 28 por 28 píxeis), num vetor 1D de 28 * 28 = 784 píxeis. Considere esta camada como retirar as linhas de píxeis da imagem e alinhá-las. Esta camada não tem parâmetros para aprender; apenas re-formata os dados.

Depois de os píxeis estarem alinhados, a rede consiste numa sequência de duas camadas tf.keras.layers.Dense. Estas são categorizadas como densely-connected, ou fully-connected. A primeira camada Dense tem 128 nós (ou neurónios). A segunda (e última) é uma camada softmax com 10 nós - isto retorna um vetor com 10 valores de probabilidade que soma 1. Cada nó contém o valor que indica a probabilidade que a image atual pertence a uma das 10 classes.

Compila o modelo

Antes de o modelo estar pronto para treinar, este precisa de mais algumas configurações. Estas são adicionadas no passo compile:

  • Função de custo - Isto mede quão bem o modelo classifica durante o treino. Nós queremos minimizar esta função para ajustar o modelo na direção correta

  • Otimizador - Isto é utilizado para atualizar o modelo com base nos dados e na função de custo.

  • Métricas - São utilizadas para monitorizar os passos de treino e teste. O próximo exemplo usa exatidão, a fração das images que são corretamente classificadas.

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

Treinar o modelo

Treinar o modelo da rede neural requer os seguintes passos:

  1. Alimentar o modelo com os dados de treino, neste caso os vetores train_images e train_labels.
  2. O modelo aprende a associar as imagens e os labels.
  3. Nós pedimos ao modelo para fazer uma previsão nos dados de teste - neste exemplo, o vetor test_images. Verificamos as previsões com o vetor de labels test_labels.

Para começar a treinar, chamamos o método mode.fit- o modelo vai ser a aproximado para descrever os dados de treino:

model.fit(train_images, train_labels, epochs=5)
WARNING: Logging before flag parsing goes to stderr.
W0702 23:56:34.255494 140351298828032 deprecation.py:323] From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where

Train on 60000 samples
Epoch 1/5
60000/60000 [==============================] - 5s 90us/sample - loss: 0.5006 - accuracy: 0.8237
Epoch 2/5
60000/60000 [==============================] - 5s 77us/sample - loss: 0.3748 - accuracy: 0.8654
Epoch 3/5
60000/60000 [==============================] - 5s 75us/sample - loss: 0.3360 - accuracy: 0.8771
Epoch 4/5
60000/60000 [==============================] - 5s 77us/sample - loss: 0.3092 - accuracy: 0.8867
Epoch 5/5
60000/60000 [==============================] - 5s 80us/sample - loss: 0.2932 - accuracy: 0.8924

<tensorflow.python.keras.callbacks.History at 0x7fa5ed381898>

À medida que o modelo treina, a função de custo e as métricas de exatidão são mostradas. Este modelo atinge uma exatidão de cerca de 0.88 (ou 88%) nos dados de treino.

Avaliar a exatidão

De seguida, compare como o modelo se comporta nos dados de test:

test_loss, test_acc = model.evaluate(test_images, test_labels)

print('Test accuracy:', test_acc)
10000/10000 [==============================] - 1s 68us/sample - loss: 0.3412 - accuracy: 0.8753
Test accuracy: 0.8753

Ao que parece, a exatidão nos dados de teste é um pouco menor do que a exatidão nos dados de treino. Esta lacuna entre a exatidão de treino e de teste é um exemplo de overfitting. Que significa quando um modelo de aprendizagem automática funciona pior em dados novos do que naqueles em que foi treinado.

Fazer previsões

Com o modelo treinado, podemos utiliza-lo para fazer previsões sobre algumas imagens.

predictions = model.predict(test_images)

Aqui, o modelo previu o label para cada imagem nos dados de treino. Vamos observar a primeira previsão:

predictions[0]
array([1.7124327e-07, 2.6024756e-08, 5.7676910e-08, 4.3003692e-07,
       6.7086056e-08, 9.8296814e-03, 4.5813707e-07, 7.4312976e-03,
       2.6895632e-05, 9.8271090e-01], dtype=float32)

A previsão é um vetor de 10 números. Este descrevem a "confiança" que o modelo tem de que esta imagem pertence a cada um dos 10 artigos diferentes de roupa. Podemos ver qual o rótulo apresenta a maior confiança:

np.argmax(predictions[0])
9

Então o modelo está mais confiante de que a image é ankle boot, ou class_names[9]. E podemos verificar o label do teste para verificar que está correto:

test_labels[0]
9

Podemos criar o gráfico para observar todos os 10 canais.

def plot_image(i, predictions_array, true_label, img):
  predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  predictions_array, true_label = predictions_array[i], true_label[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

Vamos observar a imagem 0, as previsões, e o vector de previsão.

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()

png

i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()

png

Vamos criar o gráfico com várias imagens e as suas previsões. As previsões correta encontram-se a azul e as incorretas a vermelho. O número indica a percentagem (em 100) para o label previsto. De notar, que pode estar errado mesmo quando o nível de confiança é elevado.

# Criar o gráfico das primeiras X imagens, o label previsto e o label correto
# Colorir as previsões corretas a azul e as incorretas a vermelho
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions, test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions, test_labels)
plt.show()

png

Finalmente, use o modelo treinado para fazer previsões sobre uma única imagem.

# Escolha uma imagem dos dados de teste
img = test_images[0]

print(img.shape)
(28, 28)

Os modelos tf.keras estão otimizados para fazer previsões num batch, ou coleção, de exemplos de uma vez. Então, ainda que só estejamos a utilizar uma imagem temos de adicioná-la a uma lista:

# Adicione a imagem a batch onde é o único membro.
img = (np.expand_dims(img,0))

print(img.shape)
(1, 28, 28)

Agora faça uma previsão sobre a imagem:

predictions_single = model.predict(img)

print(predictions_single)
[[1.7124295e-07 2.6024704e-08 5.7676910e-08 4.3003692e-07 6.7085921e-08
  9.8296721e-03 4.5813707e-07 7.4312938e-03 2.6895606e-05 9.8271090e-01]]
plot_value_array(0, predictions_single, test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)

png

model.predict retorna uma lista de listas, uma para cada imagem do batch de dados. Selecione a previsão para a única image do batch:

np.argmax(predictions_single[0])
9

E tal como antes, o modelo prevê o label 9.

#@title MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.