Reconhecimento de Grãos de Café com VGG-16

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.

Tags: deep learning VGG-16 tensorflow Classificação de Imagens CNN

Publicado em 10-2 04:43