Lab10 - Algumas dicas
Data Augmentation¶
O aumento de dados é uma técnica amplamente utilizada no campo do aprendizado profundo e da visão computacional para melhorar a generalização e o desempenho dos modelos de aprendizado de máquina. Essa técnica é especialmente útil em cenários onde os conjuntos de dados são limitados ou desequilibrados, pois ajuda a criar variações nos dados existentes, aumentando assim a quantidade de dados disponíveis para treinamento e reduzindo o overfitting.
O overfitting ocorre quando um modelo de aprendizado de máquina aprende padrões específicos do conjunto de dados de treinamento e não consegue generalizar adequadamente para novos dados. Isso pode levar a um desempenho ruim quando o modelo é exposto a dados não vistos anteriormente. A técnica de aumento de dados aborda esse problema criando exemplos sintéticos, aplicando transformações às imagens originais, como rotação, translação, redimensionamento e inversão. Essas transformações geram variações das imagens originais que podem ajudar o modelo a aprender características mais generalizáveis e a se tornar mais robusto a possíveis variações nos dados de entrada.
De forma geral em imagens pode ser aplicado as transformaçõs:
- Rotação
- Translação (deslocamento horizontal e vertical)
- Zoom (in e out)
- Inversão horizontal e vertical
- Ajuste de brilho e contraste
- Ruído (adicionar ruído gaussiano ou salt-and-pepper)
- Corte aleatório (Random Cropping)
- Existem mais....
Como usar Data Augmentation¶
Para demonstrar, vamos aplicar essa técnica no dataset do Cifar10.
# Carrega os dados
from keras.datasets import cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
import matplotlib.pyplot as plt
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
# Função para exibir imagens do conjunto de dados
def show_images(images, labels, n_rows=2, n_cols=5):
fig, axes = plt.subplots(n_rows, n_cols, figsize=(10, 4))
for i, ax in enumerate(axes.flat):
ax.imshow(images[i])
ax.set_title(class_names[labels[i][0]])
ax.axis('off')
plt.show()
show_images(x_train, y_train)
No Keras usamos o pacote ImageDataGenerator
.
A partir dele vamos aplicar várias transformações nas imagens do conjunto de dados durante o treinamento do modelo
from keras.preprocessing.image import ImageDataGenerator
data_gen = ImageDataGenerator(
rotation_range=15,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest',
rescale=1./255)
import numpy as np
def show_augmented_images(data_gen, image, label, n_rows=2, n_cols=5):
fig, axes = plt.subplots(n_rows, n_cols, figsize=(10, 4))
img_iterator = data_gen.flow(np.array([image]), np.array([label]))
for i, ax in enumerate(axes.flat):
img, lbl = next(img_iterator)
ax.imshow(img[0])
ax.set_title(class_names[lbl[0].item()])
ax.axis('off')
plt.show()
# Selecionar uma imagem do conjunto de dados
image_index = 0
image = x_train[image_index]
label = y_train[image_index]
# Exibir imagens aumentadas
show_augmented_images(data_gen, image, label)
Note nas variações criadas a partir de uma única imagem.
## Vamos treinar com um modelo de arquitetura simples e generico apenas para testes
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
# Definir o número de imagens aumentadas por imagem original
augmentation_factor = 5
# Criar listas vazias para armazenar as imagens e rótulos aumentados
x_train_augmented = []
y_train_augmented = []
# Aplicar a augmentação de dados
for img, lbl in zip(x_train, y_train):
x_train_augmented.append(img) # Adicionar a imagem original
y_train_augmented.append(lbl) # Adicionar o rótulo original
for _ in range(augmentation_factor - 1):
# Gerar uma imagem aumentada
augmented_img = data_gen.random_transform(img)
# Adicionar a imagem e o rótulo aumentado às listas
x_train_augmented.append(augmented_img)
y_train_augmented.append(lbl)
# Converter as listas em arrays numpy
x_train_augmented = np.array(x_train_augmented)
y_train_augmented = np.array(y_train_augmented)
# Normalizar as imagens
x_train_augmented = x_train_augmented / 255.0
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-11-cb5fafc7baac> in <module> 13 for _ in range(augmentation_factor - 1): 14 # Gerar uma imagem aumentada ---> 15 augmented_img = data_gen.random_transform(img) 16 17 # Adicionar a imagem e o rótulo aumentado às listas c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras_preprocessing\image.py in random_transform(self, x, seed) 1315 """ 1316 params = self.get_random_transform(x.shape, seed) -> 1317 return self.apply_transform(x, params) 1318 1319 def fit(self, x, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras_preprocessing\image.py in apply_transform(self, x, transform_parameters) 1276 img_channel_axis = self.channel_axis - 1 1277 -> 1278 x = apply_affine_transform(x, transform_parameters.get('theta', 0), 1279 transform_parameters.get('tx', 0), 1280 transform_parameters.get('ty', 0), c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras_preprocessing\image.py in apply_affine_transform(x, theta, tx, ty, shear, zx, zy, row_axis, col_axis, channel_axis, fill_mode, cval) 331 final_offset = transform_matrix[:2, 2] 332 --> 333 channel_images = [scipy.ndimage.interpolation.affine_transform( 334 x_channel, 335 final_affine_matrix, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras_preprocessing\image.py in <listcomp>(.0) 331 final_offset = transform_matrix[:2, 2] 332 --> 333 channel_images = [scipy.ndimage.interpolation.affine_transform( 334 x_channel, 335 final_affine_matrix, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\scipy\ndimage\interpolation.py in affine_transform(input, matrix, offset, output_shape, output, order, mode, cval, prefilter) 606 mode, cval, npad, False) 607 else: --> 608 _nd_image.geometric_transform(filtered, None, None, matrix, offset, 609 output, order, mode, cval, npad, None, 610 None) KeyboardInterrupt:
batch_size = 64
steps_per_epoch = len(x_train) // batch_size
history = model.fit_generator(data_gen.flow(x_train, y_train, batch_size=batch_size),
steps_per_epoch=steps_per_epoch,
epochs=20,
validation_data=(x_test / 255, y_test))
c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py:1915: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators. warnings.warn('`Model.fit_generator` is deprecated and '
Epoch 1/20 218/781 [=======>......................] - ETA: 1:20 - loss: 2.0232 - accuracy: 0.1337
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-10-5c79c9165d79> in <module> 2 steps_per_epoch = len(x_train) // batch_size 3 ----> 4 history = model.fit_generator(data_gen.flow(x_train, y_train, batch_size=batch_size), 5 steps_per_epoch=steps_per_epoch, 6 epochs=20, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch) 1916 'will be removed in a future version. ' 1917 'Please use `Model.fit`, which supports generators.') -> 1918 return self.fit( 1919 generator, 1920 steps_per_epoch=steps_per_epoch, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing) 1156 _r=1): 1157 callbacks.on_train_batch_begin(step) -> 1158 tmp_logs = self.train_function(iterator) 1159 if data_handler.should_sync: 1160 context.async_wait() c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\def_function.py in __call__(self, *args, **kwds) 887 888 with OptionalXlaContext(self._jit_compile): --> 889 result = self._call(*args, **kwds) 890 891 new_tracing_count = self.experimental_get_tracing_count() c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\def_function.py in _call(self, *args, **kwds) 915 # In this case we have created variables on the first call, so we run the 916 # defunned version which is guaranteed to never create variables. --> 917 return self._stateless_fn(*args, **kwds) # pylint: disable=not-callable 918 elif self._stateful_fn is not None: 919 # Release the lock early so that multiple threads can perform the call c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\function.py in __call__(self, *args, **kwargs) 3021 (graph_function, 3022 filtered_flat_args) = self._maybe_define_function(args, kwargs) -> 3023 return graph_function._call_flat( 3024 filtered_flat_args, captured_inputs=graph_function.captured_inputs) # pylint: disable=protected-access 3025 c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\function.py in _call_flat(self, args, captured_inputs, cancellation_manager) 1958 and executing_eagerly): 1959 # No tape is watching; skip to running the function. -> 1960 return self._build_call_outputs(self._inference_function.call( 1961 ctx, args, cancellation_manager=cancellation_manager)) 1962 forward_backward = self._select_forward_and_backward_functions( c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\function.py in call(self, ctx, args, cancellation_manager) 589 with _InterpolateFunctionError(self): 590 if cancellation_manager is None: --> 591 outputs = execute.execute( 592 str(self.signature.name), 593 num_outputs=self._num_outputs, c:\Users\junior\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\eager\execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name) 57 try: 58 ctx.ensure_initialized() ---> 59 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name, 60 inputs, attrs, num_outputs) 61 except core._NotOkStatusException as e: KeyboardInterrupt: