Preparação dos Dados
Primeiramente, são importadas as bibliotecas necessárias e definida a pasta contendo as imagens:
from tensorflow.keras import layers, models
import numpy as np
import matplotlib.pyplot as plt
import os
import pathlib
from PIL import Image
# Caminho personalizado para o diretório de dados
data_dir = pathlib.Path("C:/users/CuiWanbing/Desktop/coffee")
Processamento de Imagens
O conjunto de dados é carregado com base em rótulos pré-definidos — neste caso, quatro categorias distintas de grãos de café. As imagens são visualizadas para verifciar a qualidade e distribuição dos dados.
Configuração do Conjunto de Treinamento
O pipeline de preparação segue padrões estabelecidos nas semanas anteriores: divisão em conjuntos de treino e validação, normalização e aumento de dados (se aplicável).
Implementação da Arquitetura VGG-16
A seguir, é construída uma versão personalizada da arquitetura VGG-16, adaptada para o problema de reconhecimento de grãos de café.
- Vantagens do VGG-16: Estrutura simples com camadas convolucionais uniformes (3x3) e pooling (2x2), facilitando a implementação e análise.
- Desvantagens: Alto custo computacional, grande consumo de memória (arquivos de pesos superiores a 500 MB) e lentidão em dispositivos sem GPU.
def build_vgg16(num_classes, input_shape):
inputs = layers.Input(shape=input_shape)
# Bloco 1
x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='conv_block1_1')(inputs)
x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='conv_block1_2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='pool_block1')(x)
# Bloco 2
x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='conv_block2_1')(x)
x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='conv_block2_2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='pool_block2')(x)
# Bloco 3
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='conv_block3_1')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='conv_block3_2')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='conv_block3_3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='pool_block3')(x)
# Bloco 4
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block4_1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block4_2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block4_3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='pool_block4')(x)
# Bloco 5
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block5_1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block5_2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='conv_block5_3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='pool_block5')(x)
# Camadas totalmente conectadas
x = layers.Flatten()(x)
x = layers.Dense(4096, activation='relu', name='fc1')(x)
x = layers.Dense(4096, activation='relu', name='fc2')(x)
outputs = layers.Dense(num_classes, activation='softmax', name='output_layer')(x)
return models.Model(inputs, outputs)
# Construção do modelo
model = build_vgg16(len(class_names), (img_width, img_height, 3))
model.summary()
Compilação do Modelo
Define-se uma taxa de aprendizado inicial com decaimento exponencial e utiliza-se o otimizador Adam:
initial_lr = 1e-4
lr_decay = tf.keras.optimizers.schedules.ExponentialDecay(
initial_lr,
decay_steps=30,
decay_rate=0.92,
staircase=True
)
optimizer = tf.keras.optimizers.Adam(learning_rate=initial_lr)
model.compile(
optimizer=optimizer,
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['accuracy']
)
Treinamento do Modelo
Executa-se o treinamento por 20 épocas com dados de treino e validação:
epochs = 20
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
Conclusão Pessoal
Arquitetura VGG-16 possui:
- 13 camadas convolucionais (identificadas como
conv_blockX_Y) - 3 camadas densas (fc1, fc2, output_layer)
- 5 camadas de pooling (pool_blockX)
O nome "VGG-16" deriva do total de 16 camadas ocultas (13 convolucionais + 3 densas). Observou-se que o processamento em CPU é extremamante lento, especialmente com aumento de épocas. Recomenda-se utilizar hardware com GPU para acelerar o treinamento em etapas futuras.