Reserve a data! O Google I / O retorna de 18 a 20 de maio Registre-se agora
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Rede Neural Convolucional (CNN)

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Este tutorial demonstra o treinamento de uma Rede Neural Convolucional (CNN) simples para classificar imagens CIFAR . Como este tutorial usa a API Sequencial Keras , criar e treinar nosso modelo exigirá apenas algumas linhas de código.

Import TensorFlow

import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

Baixe e prepare o conjunto de dados CIFAR10

O conjunto de dados CIFAR10 contém 60.000 imagens coloridas em 10 classes, com 6.000 imagens em cada classe. O conjunto de dados é dividido em 50.000 imagens de treinamento e 10.000 imagens de teste. As classes são mutuamente exclusivas e não há sobreposição entre elas.

(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170500096/170498071 [==============================] - 11s 0us/step

Verifique os dados

Para verificar se o conjunto de dados parece correto, vamos plotar as primeiras 25 imagens do conjunto de treinamento e exibir o nome da classe abaixo de cada imagem.

class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

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)
    # The CIFAR labels happen to be arrays, 
    # which is why you need the extra index
    plt.xlabel(class_names[train_labels[i][0]])
plt.show()

png

Crie a base convolucional

Os 6 linhas de código abaixo definir a base convolucional utilizando um padrão comum: uma pilha de Conv2D e MaxPooling2D camadas.

Como entrada, um CNN assume tensores de forma (image_height, image_width, color_channels), ignorando o tamanho do lote. Se você é novo nessas dimensões, color_channels se refere a (R, G, B). Neste exemplo, você configurará nosso CNN para processar entradas de forma (32, 32, 3), que é o formato de imagens CIFAR. Você pode fazer isso passando o argumento input_shape para nossa primeira camada.

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

Vamos mostrar a arquitetura do nosso modelo até agora.

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 4, 4, 64)          36928     
=================================================================
Total params: 56,320
Trainable params: 56,320
Non-trainable params: 0
_________________________________________________________________

Acima, você pode ver que a saída de cada camada Conv2D e MaxPooling2D é um tensor 3D de forma (altura, largura, canais). As dimensões de largura e altura tendem a diminuir à medida que você se aprofunda na rede. O número de canais de saída para cada camada Conv2D é controlado pelo primeiro argumento (por exemplo, 32 ou 64). Normalmente, à medida que a largura e a altura diminuem, você pode (computacionalmente) adicionar mais canais de saída em cada camada Conv2D.

Adicionar camadas densas no topo

Para completar nosso modelo, você alimentará o último tensor de saída da base convolucional (de formato (4, 4, 64)) em uma ou mais camadas Densas para realizar a classificação. Camadas densas recebem vetores como entrada (que são 1D), enquanto a saída atual é um tensor 3D. Primeiro, você nivelará (ou desenrolará) a saída 3D em 1D e, em seguida, adicionará uma ou mais camadas Densas na parte superior. CIFAR tem 10 classes de saída, então você usa uma camada Densa final com 10 saídas.

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))

Aqui está a arquitetura completa do nosso modelo.

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 4, 4, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 1024)              0         
_________________________________________________________________
dense (Dense)                (None, 64)                65600     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 122,570
Trainable params: 122,570
Non-trainable params: 0
_________________________________________________________________

Como você pode ver, nossas (4, 4, 64) saídas foram achatadas em vetores de forma (1024) antes de passar por duas camadas densas.

Compilar e treinar o modelo

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(train_images, train_labels, epochs=10, 
                    validation_data=(test_images, test_labels))
Epoch 1/10
1563/1563 [==============================] - 18s 4ms/step - loss: 1.7606 - accuracy: 0.3488 - val_loss: 1.2753 - val_accuracy: 0.5504
Epoch 2/10
1563/1563 [==============================] - 6s 4ms/step - loss: 1.1977 - accuracy: 0.5751 - val_loss: 1.0409 - val_accuracy: 0.6371
Epoch 3/10
1563/1563 [==============================] - 6s 4ms/step - loss: 1.0137 - accuracy: 0.6439 - val_loss: 0.9613 - val_accuracy: 0.6597
Epoch 4/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.8844 - accuracy: 0.6908 - val_loss: 0.9272 - val_accuracy: 0.6766
Epoch 5/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.7950 - accuracy: 0.7205 - val_loss: 0.8712 - val_accuracy: 0.6923
Epoch 6/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.7410 - accuracy: 0.7388 - val_loss: 0.8894 - val_accuracy: 0.6943
Epoch 7/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.6924 - accuracy: 0.7547 - val_loss: 0.8980 - val_accuracy: 0.6993
Epoch 8/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.6453 - accuracy: 0.7728 - val_loss: 0.8695 - val_accuracy: 0.7109
Epoch 9/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.5999 - accuracy: 0.7881 - val_loss: 0.8887 - val_accuracy: 0.7098
Epoch 10/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.5461 - accuracy: 0.8088 - val_loss: 0.8840 - val_accuracy: 0.7157

Avalie o modelo

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
313/313 - 1s - loss: 0.8840 - accuracy: 0.7157

png

print(test_acc)
0.7156999707221985

Nosso CNN simples alcançou uma precisão de teste de mais de 70%. Nada mal para algumas linhas de código! Para outro estilo de CNN, veja um exemplo usando a API de subclasse de Keras e umtf.GradientTape aqui .