<jupyter_start><jupyter_text>Copyright 2018 The TensorFlow Authors.<jupyter_code>#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.<jupyter_output><empty_output><jupyter_text>Classificação de Imagens       Ver em TensorFlow.org        Executar no Google Colab        Código Fonte no GitHub        Baixar notebook   Este tutorial mostra como classificar gatos ou cães a partir de imagens. Ele constrói um classificador de imagens usando um modelo `tf.keras.Sequential` e carrega dados usando `tf.keras.preprocessing.image.ImageDataGenerator`. Você obterá alguma experiência prática e desenvolverá a intuição para os seguintes conceitos:* Criando pipelines de entrada de dados_ usando a classe `tf.keras.preprocessing.image.ImageDataGenerator` para trabalhar com eficiência com os dados no disco para usar com o modelo.* _Overfitting_ - Como identificar e evitá-lo.* _Aumento de dados_ e _dropout_ - Técnicas-chave para combater o overfitting em tarefas de visão computacional para incorporar no pipeline de dados e no modelo classificador de imagens.Este tutorial segue um fluxo de trabalho básico de aprendizado de máquina:1. Examine e entenda os dados2. Construa um pipeline de entrada3. Construa o modelo4. Treine o modelo5. Teste o modelo6. Melhore o modelo e repita o processo  Importar pacotes Vamos começar importando os pacotes necessários. O pacote `os` é usado para ler arquivos e estrutura de diretórios, o NumPy é usado para converter a lista python em um array numpy e executar operações matriciais necessárias e `matplotlib.pyplot` para plotar o gráfico e exibir imagens nos dados de treinamento e validação.<jupyter_code>from __future__ import absolute_import, division, print_function, unicode_literals<jupyter_output><empty_output><jupyter_text>Importe o Tensorflow e as classes Keras necessárias para construir nosso modelo.<jupyter_code>try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator

import os
import numpy as np
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Carregando Dados Comece baixando o conjunto de dados. Este tutorial usa a versão filtrada do conjunto de dados Dogs vs Cats do Kaggle. Baixe a versão de arquivo do conjunto de dados e armazene-a no diretório "/tmp/".<jupyter_code>_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'

path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)

PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')<jupyter_output><empty_output><jupyter_text>O conjunto de dados tem a seguinte estrutura de diretórios:cats_and_dogs_filtered|__ train    |______ cats: [cat.0.jpg, cat.1.jpg, cat.2.jpg ....]    |______ dogs: [dog.0.jpg, dog.1.jpg, dog.2.jpg ...]|__ validation    |______ cats: [cat.2000.jpg, cat.2001.jpg, cat.2002.jpg ....]    |______ dogs: [dog.2000.jpg, dog.2001.jpg, dog.2002.jpg ...] Após extrair seu conteúdo, atribua variáveis com o caminho de arquivo adequado para o conjunto de treinamento e validação.<jupyter_code>train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
train_cats_dir = os.path.join(train_dir, 'cats')  # diretório com as imagens de gato para treinamento
train_dogs_dir = os.path.join(train_dir, 'dogs')  # diretório com as imagens de cães para treinamento
validation_cats_dir = os.path.join(validation_dir, 'cats')  # diretório com as imagens de gatos para validação
validation_dogs_dir = os.path.join(validation_dir, 'dogs')  # diretório com as imagens de cães para validação<jupyter_output><empty_output><jupyter_text>Entendendo os Dados Vejamos quantas imagens de cães e gatos estão nos diretórios de treinamento e validação:<jupyter_code>num_cats_tr = len(os.listdir(train_cats_dir))
num_dogs_tr = len(os.listdir(train_dogs_dir))

num_cats_val = len(os.listdir(validation_cats_dir))
num_dogs_val = len(os.listdir(validation_dogs_dir))

total_train = num_cats_tr + num_dogs_tr
total_val = num_cats_val + num_dogs_val
print('total training cat images:', num_cats_tr)
print('total training dog images:', num_dogs_tr)

print('total validation cat images:', num_cats_val)
print('total validation dog images:', num_dogs_val)
print("--")
print("Total training images:", total_train)
print("Total validation images:", total_val)<jupyter_output><empty_output><jupyter_text>Por conveniência, configure variáveis a serem usadas durante o pré-processamento do conjunto de dados e o treinamento da rede.<jupyter_code>batch_size = 128
epochs = 15
IMG_HEIGHT = 150
IMG_WIDTH = 150<jupyter_output><empty_output><jupyter_text>Preparação dos Dados Formate as imagens em tensores de ponto flutuante pré-processados adequadamente antes de alimentar a rede:1. Leia imagens do disco.2. Decodifique o conteúdo dessas imagens e converta-o no formato de grade apropriado, conforme o conteúdo RGB.3. Converta-os em tensores de ponto flutuante.4. Redimensione os tensores de valores entre 0 e 255 para valores entre 0 e 1, pois as redes neurais preferem lidar com pequenos valores de entrada.Felizmente, todas essas tarefas podem ser realizadas com a classe `ImageDataGenerator` fornecida pelo `tf.keras`. Ele pode ler imagens do disco e pré-processá-las em tensores adequados. Ele também configurará geradores que convertem essas imagens em batchs de tensores - úteis ao treinar a rede.<jupyter_code>train_image_generator = ImageDataGenerator(rescale=1./255) # Gerador para nossos dados de treinamento
validation_image_generator = ImageDataGenerator(rescale=1./255) # Gerador para nossos dados de validação<jupyter_output><empty_output><jupyter_text>Depois de definir os geradores para imagens de treinamento e validação, o método `flow_from_directory` carrega imagens do disco e redimensiona as imagens nas dimensões necessárias.<jupyter_code>train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size,
                                                           directory=train_dir,
                                                           shuffle=True,
                                                           target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                           class_mode='binary')
val_data_gen = validation_image_generator.flow_from_directory(batch_size=batch_size,
                                                              directory=validation_dir,
                                                              target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                              class_mode='binary')<jupyter_output><empty_output><jupyter_text>Visualizando as imagens de treinamento Visualize as imagens de treinamento extraindo um batch de imagens do gerador de treinamento - que são 32 imagens neste exemplo - e plote cinco delas com `matplotlib`.<jupyter_code>sample_training_images, _ = next(train_data_gen)<jupyter_output><empty_output><jupyter_text>A função `next` retorna um batch do conjunto de dados. O valor de retorno da função `next` está na forma de `((x_train, y_train)` onde x_train está treinando características e y_train, seus rótulos. Descarte os rótulos para visualizar apenas as imagens de treinamento.<jupyter_code># Esta função plotará imagens na forma de uma tabela com 1 linha e 5 colunas onde as imagens são colocadas em cada coluna.
def plotImages(images_arr):
    fig, axes = plt.subplots(1, 5, figsize=(20,20))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
        ax.axis('off')
    plt.tight_layout()
    plt.show()
plotImages(sample_training_images[:5])<jupyter_output><empty_output><jupyter_text>Criando o Modelo O modelo consiste em três blocos de convolução com uma camada `max pool` em cada um deles. Há uma camada totalmente conectada com 512 unidades em cima, ativada por uma função de ativação `relu`. O modelo gera probabilidades de classe com base na classificação binária pela função de ativação `sigmoid`.<jupyter_code>model = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)),
    MaxPooling2D(),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1, activation='sigmoid')
])<jupyter_output><empty_output><jupyter_text>Compilando o ModeloPara esse tutorial, escolhemos o otimizador *ADAM* e a função de perda *binary cross entropy*. Para visualizar a acurácia do treinamento e validação  a cada época de treinamento, passamos o argumento `metrics`.<jupyter_code>model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])<jupyter_output><empty_output><jupyter_text>Resumo do ModeloVeja todas as camadas da rede usando o método `summary` do modelo:<jupyter_code>model.summary()<jupyter_output><empty_output><jupyter_text>Treinando o Modelo Use o método `fit_generator` da classe `ImageDataGenerator` para treinar a rede.<jupyter_code>history = model.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)<jupyter_output><empty_output><jupyter_text>Visualizando resultados do treinamento Agora visualize os resultados depois de treinar a rede.<jupyter_code>acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()<jupyter_output><empty_output><jupyter_text>Como você pode ver nas plotagens, a acurácia do treinamento e a acurácia da validação são reduzidas por uma grande margem e o modelo alcançou apenas cerca de ** 70% ** de acurácia no conjunto de validação.Vamos analisar o que deu errado e tentar aumentar o desempenho geral do modelo.  Overfitting Nas plotagens acima, a acurácia do treinamento aumenta linearmente ao longo do tempo, enquanto a acurácia da validação fica em torno de 70% no processo de treinamento. Além disso, a diferença de acurácia entre treinamento e validação é perceptível - um sinal de *overfitting*.Quando há um pequeno número de exemplos de treinamento, o modelo algumas vezes aprende com ruídos ou detalhes indesejados dos exemplos de treinamento - a ponto de impactar negativamente o desempenho do modelo em novos exemplos. Esse fenômeno é conhecido como overfitting. Isso significa que o modelo está superajustado e terá dificuldade em generalizar um novo conjunto de dados.Existem várias maneiras de combater o excesso de ajustes no processo de treinamento. Neste tutorial, você usará *data augmentation* e adicionará *dropout* ao nosso modelo.  Data augmentation O overfitting geralmente ocorre quando há um pequeno número de exemplos de treinamento. Uma maneira de corrigir esse problema é aumentar o conjunto de dados para que ele tenha um número suficiente de exemplos de treinamento. O aumento de dados adota a abordagem de gerar mais dados de treinamento a partir de amostras de treinamento existentes, aumentando as amostras usando transformações aleatórias que produzem imagens com aparência crível. O objetivo é que o modelo nunca veja exatamente a mesma imagem duas vezes durante o treinamento. Isso ajuda a expor o modelo a mais aspectos dos dados e a generalizar melhor.Implemente isso no `tf.keras` usando a classe `ImageDataGenerator`. Passe diferentes transformações para o conjunto de dados e ele se encarregará de aplicá-lo durante o processo de treinamento.  Aumentando e Visualizando os Dados Comece aplicando rotações horizontais aleatórias ao conjunto de dados e veja como são as imagens individuais após a transformação.  Aplicanco rotação horizontal Passe `horizontal_flip` como argumento para a classe `ImageDataGenerator` e defina-o como `True` para aplicar esse aumento.<jupyter_code>image_gen = ImageDataGenerator(rescale=1./255, horizontal_flip=True)
train_data_gen = image_gen.flow_from_directory(batch_size=batch_size,
                                               directory=train_dir,
                                               shuffle=True,
                                               target_size=(IMG_HEIGHT, IMG_WIDTH))<jupyter_output><empty_output><jupyter_text>Pegue uma imagem de amostra dos exemplos de treinamento e repita-a cinco vezes para que o aumento seja aplicado à mesma imagem cinco vezes.<jupyter_code>augmented_images = [train_data_gen[0][0][0] for i in range(5)]
# Reutilize a mesma função de plotagem personalizada definida e usada
# acima para visualizar as imagens de treinamento
plotImages(augmented_images)<jupyter_output><empty_output><jupyter_text>Rotacione a Imagem Aleatoriamente Vamos dar uma olhada em um aumento diferente chamado rotação e aplicar 45 graus de rotação aleatoriamente nos exemplos de treinamento.<jupyter_code>image_gen = ImageDataGenerator(rescale=1./255, rotation_range=45)
train_data_gen = image_gen.flow_from_directory(batch_size=batch_size,
                                               directory=train_dir,
                                               shuffle=True,
                                               target_size=(IMG_HEIGHT, IMG_WIDTH))

augmented_images = [train_data_gen[0][0][0] for i in range(5)]
plotImages(augmented_images)<jupyter_output><empty_output><jupyter_text>Aplique aumento de zoom Aplique um aumento de zoom ao conjunto de dados para ampliar imagens até 50% aleatoriamente.<jupyter_code># zoom_range de 0 - 1 onde 1 = 100%.
image_gen = ImageDataGenerator(rescale=1./255, zoom_range=0.5) # 
train_data_gen = image_gen.flow_from_directory(batch_size=batch_size,
                                               directory=train_dir,
                                               shuffle=True,
                                               target_size=(IMG_HEIGHT, IMG_WIDTH))

augmented_images = [train_data_gen[0][0][0] for i in range(5)]
plotImages(augmented_images)<jupyter_output><empty_output><jupyter_text>Coloque tudo junto Aplique todos os aumentos anteriores. Aqui, você aplicou redimensionamento, rotação de 45 graus, deslocamento de largura, deslocamento de altura, aumento horizontal de zoom e zoom nas imagens de treinamento.<jupyter_code>image_gen_train = ImageDataGenerator(
                    rescale=1./255,
                    rotation_range=45,
                    width_shift_range=.15,
                    height_shift_range=.15,
                    horizontal_flip=True,
                    zoom_range=0.5
                    )
train_data_gen = image_gen_train.flow_from_directory(batch_size=batch_size,
                                                     directory=train_dir,
                                                     shuffle=True,
                                                     target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                     class_mode='binary')<jupyter_output><empty_output><jupyter_text>Visualize como uma única imagem ficaria cinco vezes diferentes ao passar esses aprimoramentos aleatoriamente para o conjunto de dados.<jupyter_code>augmented_images = [train_data_gen[0][0][0] for i in range(5)]
plotImages(augmented_images)<jupyter_output><empty_output><jupyter_text>Crie o gerador de dados de validação Geralmente, aplique apenas o aumento de dados aos exemplos de treinamento. Nesse caso, apenas redimensione novamente as imagens de validação e as converta em batch usando o `ImageDataGenerator`.<jupyter_code>image_gen_val = ImageDataGenerator(rescale=1./255)
val_data_gen = image_gen_val.flow_from_directory(batch_size=batch_size,
                                                 directory=validation_dir,
                                                 target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                 class_mode='binary')<jupyter_output><empty_output><jupyter_text>Dropout Outra técnica para reduzir o overfitting é introduzir *dropout* na rede. É uma forma de *regularização* que força os pesos na rede a aceitar apenas valores pequenos, o que torna a distribuição dos valores de peso mais regular e a rede pode reduzir o excesso de ajustes em pequenos exemplos de treinamento. O abandono é uma das técnicas de regularização usadas neste tutorialQuando você aplica a dropout a uma camada, ela remove aleatoriamente (definido como zero) o número de unidades de saída da camada aplicada durante o processo de treinamento. A desistência recebe um número fracionário como valor de entrada, na forma de 0.1, 0.2, 0.4 etc. Isso significa eliminar 10%, 20% ou 40% das unidades de saída aleatoriamente da camada aplicada.Ao aplicar o abandono de 0.1 a uma determinada camada, ele mata aleatoriamente 10% das unidades de saída em cada época de treinamento.Crie uma arquitetura de rede com esse novo recurso de eliminação e aplique-a a diferentes convoluções e camadas totalmente conectadas.  Criando uma Nova Rede com Dropouts Aqui, você aplica o dropout à primeira e à última camada máxima do pool. A aplicação de dropout definirá aleatoriamente 20% dos neurônios para zero durante cada época de treinamento. Isso ajuda a evitar ajustes excessivos no conjunto de dados de treinamento.<jupyter_code>model_new = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', 
           input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)),
    MaxPooling2D(),
    Dropout(0.2),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Dropout(0.2),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1, activation='sigmoid')
])<jupyter_output><empty_output><jupyter_text>Compilando o Modelo Depois de introduzir desistências na rede, compile o modelo e visualize o resumo das camadas.<jupyter_code>model_new.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

model_new.summary()<jupyter_output><empty_output><jupyter_text>Treinando o Modelo Depois de introduzir com sucesso os aprimoramentos de dados nos exemplos de treinamento e adicionar dropout à rede, treine esta nova rede:<jupyter_code>history = model_new.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)<jupyter_output><empty_output><jupyter_text>Visualizando o Modelo Visualize o novo modelo após o treinamento, você pode ver que há muito menos ajuste do que antes. A acurácia deve aumentar após o treinamento do modelo por mais épocas.<jupyter_code>acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07128915780228359, 'fraction_numerical': 0.01132038645457207, 'mean_word_length': 4.068001978239367, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 109, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '394175', 'license': 'Apache-2.0', 'n_tokens_mistral': 6628, 'n_tokens_neox': 6362, 'n_words': 2001, 'path': 'site/pt/tutorials/images/classification.ipynb', 'repo_name': 'smoreira/docs', 'size': '20494'}