Este trabalho aplica tecnicas de classificacao supervisionada ao dataset RGB disponibilizado na disciplina CEAO-802 - Metodos de Analise de Dados.
O documento de datasets apresenta um problema de classificacao de cenas urbanas com imagens RGB e TIR coletadas por drone sobre Guaratingueta (SP), com 13 classes de cobertura urbana. Nesta analise sera utilizada apenas a parte RGB do dataset, armazenada localmente em D:/Vitor/Documents/CEAO/802/HAB/DADOS CEAO 2026/RGB.
A abordagem adotada segue a sugestao do material da disciplina: em vez de extrair atributos estatisticos simples (media, desvio, histogramas), serao utilizadas redes neurais convolucionais pre-treinadas como extratores de atributos (transfer learning). A rede MobileNetV2, pre-treinada no ImageNet, e carregada sem a camada de classificacao final. Cada imagem e redimensionada para 224x224 pixels e processada pela rede, que produz um vetor de 1280 atributos representando caracteristicas visuais de alto nivel aprendidas em milhoes de imagens. Esses vetores sao entao usados como entrada para os classificadores SVM e Random Forest.
A aula de Support Vector Machine (SVM) apresentou o metodo como um classificador baseado na busca de um hiperplano de separacao entre classes. A ideia central e encontrar uma fronteira que maximize a margem entre os grupos. Quando os dados nao sao linearmente separaveis, o SVM pode usar variaveis de folga, controladas pelo parametro cost, e tambem kernels, como o kernel radial ou RBF, para criar fronteiras de decisao nao lineares por meio do chamado kernel trick.
Como a pasta RGB possui grande volume de dados, sera usada uma amostra estratificada e balanceada de 50 imagens por classe. Essa escolha torna o processamento viavel em um computador comum, preservando a comparacao entre as classes.
Em R, e mais seguro usar barras / no caminho, mesmo no Windows.
# ============================================================# 2. Caminho do dataset RGB# ============================================================caminho_rgb <-"D:/Vitor/Documents/CEAO/802/HAB/DADOS CEAO 2026/RGB"if (!dir.exists(caminho_rgb)) {stop("A pasta do dataset RGB nao foi encontrada. Verifique o caminho informado em caminho_rgb.")}caminho_rgb
O codigo procura imagens dentro da pasta RGB. Se o dataset estiver organizado em subpastas, o nome da subpasta sera usado como classe. No dataset usado neste trabalho, os arquivos TIFF estao diretamente na pasta RGB, entao a classe e inferida pelo prefixo do nome do arquivo, como C1, C2, …, C13.
# ============================================================# 3. Listar imagens# ============================================================extensoes_imagem <-"\\.(jpg|jpeg|png|bmp|tif|tiff)$"arquivos <-list.files(path = caminho_rgb,pattern = extensoes_imagem,recursive =TRUE,full.names =TRUE,ignore.case =TRUE)if (length(arquivos) ==0) {stop("Nenhuma imagem foi encontrada na pasta RGB.")}length(arquivos)
A amostragem estratificada foi usada para manter a mesma quantidade de imagens em cada classe. Isso evita que classes maiores dominem o treinamento e reduz o tempo de processamento.
# ============================================================# 5. Criar amostra balanceada por classe# ============================================================set.seed(123)max_imagens_por_classe <-50metadados <- metadados_completo %>%group_by(classe) %>%group_modify(~ { qtd <-min(max_imagens_por_classe, nrow(.x))slice_sample(.x, n = qtd) }) %>%ungroup() %>%mutate(classe =factor(classe, levels =paste0("C", 1:13)))cat("Total de imagens no dataset completo:", nrow(metadados_completo), "\n")
Total de imagens no dataset completo: 1248
cat("Total de imagens na amostra:", nrow(metadados), "\n")
Total de imagens na amostra: 650
metadados %>%count(classe, name ="n_imagens_amostra") %>%arrange(classe) %>%kable()
classe
n_imagens_amostra
C1
50
C2
50
C3
50
C4
50
C5
50
C6
50
C7
50
C8
50
C9
50
C10
50
C11
50
C12
50
C13
50
ggplot(metadados, aes(x = classe)) +geom_bar(fill ="#2C7FB8") +coord_flip() +labs(title ="Distribuicao de imagens por classe na amostra",x ="Classe",y ="Numero de imagens" ) +theme_minimal()
6 Modelo pre-treinado (Transfer Learning)
A estrategia de transfer learning consiste em usar uma rede neural convolucional (CNN) ja treinada em um grande dataset — neste caso, o ImageNet, com mais de 1 milhao de imagens e 1000 classes — e aproveitá-la como extrator de atributos.
A rede escolhida e a MobileNetV2, uma arquitetura compacta e eficiente desenvolvida pelo Google. Ela e carregada sem a camada de classificacao final (include_top = FALSE) e com pooling global medio (pooling = "avg"), o que produz um vetor de 1280 atributos por imagem. Esses atributos representam caracteristicas visuais de alto nivel (bordas, texturas, formas, padroes complexos) que a rede aprendeu ao longo de seu treinamento no ImageNet.
cat("Dimensao do vetor de features:", modelo_base$output_shape[[2]], "\n")
Dimensao do vetor de features: 1280
7 Extracao de atributos por Transfer Learning
Cada imagem e redimensionada para 224x224 pixels (formato padrao do MobileNetV2), normalizada com a funcao de preprocessamento especifica da rede e entao passada pela CNN. O vetor de saida e armazenado como atributos da imagem.
O processamento e feito em lotes (batch) para maior eficiencia, e o resultado e armazenado em cache para evitar reprocessamento em execucoes posteriores.
treino %>%count(classe, name ="treino") %>%full_join( teste %>%count(classe, name ="teste"),by ="classe" ) %>%arrange(classe) %>%kable()
classe
treino
teste
C1
35
15
C2
35
15
C3
35
15
C4
35
15
C5
35
15
C6
35
15
C7
35
15
C8
35
15
C9
35
15
C10
35
15
C11
35
15
C12
35
15
C13
35
15
9 Pre-processamento
Como o SVM e sensivel a escala das variaveis, os atributos serao centralizados e padronizados. Tambem serao removidas variaveis com variancia quase nula.
# ============================================================# 9. Preparar matrizes X e vetor y# ============================================================colunas_nao_preditoras <-c("arquivo", "classe", "tamanho_mb")x_treino <- treino %>%select(-all_of(colunas_nao_preditoras))x_teste <- teste %>%select(-all_of(colunas_nao_preditoras))y_treino <-droplevels(treino$classe)y_teste <-factor(teste$classe, levels =levels(y_treino))variaveis_nzv <-nearZeroVar(x_treino)if (length(variaveis_nzv) >0) { x_treino <- x_treino[, -variaveis_nzv, drop =FALSE] x_teste <- x_teste[, colnames(x_treino), drop =FALSE]}preproc <-preProcess( x_treino,method =c("center", "scale"))x_treino_norm <-predict(preproc, x_treino)x_teste_norm <-predict(preproc, x_teste)cat("Preditores usados nos modelos:", ncol(x_treino_norm), "\n")
Preditores usados nos modelos: 1265
10 Modelo 1: SVM linear
O SVM linear tenta separar as classes por hiperplanos lineares. E o modelo mais simples e serve como referencia inicial.
O kernel radial, tambem chamado de RBF, permite construir fronteiras de decisao nao lineares. Nesta primeira versao, serao usados valores fixos para cost e gamma.
12 Modelo 3: Ajuste de hiperparametros do SVM radial
O parametro cost controla o quanto o modelo penaliza erros de classificacao. O parametro gamma influencia o alcance do kernel radial. Valores maiores podem gerar fronteiras mais complexas.
O PCA transforma os atributos originais em componentes principais. Aqui, serao mantidos componentes suficientes para explicar pelo menos 95% da variancia, com limite maximo de 30 componentes.
scores_pca <-as_tibble(pca$x[, 1:2, drop =FALSE]) %>%mutate(classe = y_treino)ggplot(scores_pca, aes(x = PC1, y = PC2, color = classe)) +geom_point(alpha =0.8) +labs(title ="Visualizacao do conjunto de treino no espaco PCA",x ="PC1",y ="PC2",color ="Classe" ) +theme_minimal()
14 Modelo 5: Random Forest
O Random Forest sera usado como classificador de comparacao. Ele costuma lidar bem com relacoes nao lineares e tambem permite estimar a importancia das variaveis.
importancia_df %>%slice_head(n =20) %>%ggplot(aes(x =reorder(variavel, importancia), y = importancia)) +geom_col(fill ="#2C7FB8") +coord_flip() +labs(title ="20 variaveis mais importantes segundo o Random Forest",x ="Variavel",y ="Importancia" ) +theme_minimal()
Na abordagem anterior (holdout), o conjunto de dados foi dividido uma unica vez em treino (70%) e teste (30%). Isso pode gerar uma estimativa otimista ou pessimista do desempenho real, dependendo de como a divisao ocorreu.
A validacao cruzada k-fold resolve esse problema dividindo o dataset em k partes iguais e estratificadas. Em cada rodada, uma parte diferente e usada como teste e as restantes como treino. O desempenho final e a media das k rodadas, o que aproveita todas as observacoes para avaliacao e produz uma estimativa mais estavel.
Nesta etapa, sera usado k=5. Para manter a avaliacao independente do holdout, o SVM radial ajustado tera cost e gamma reotimizados dentro de cada fold, usando apenas os dados de treino daquele fold.
cat("Acuracia maxima - K-Fold: ", round(melhor_kf, 4), "\n")
Acuracia maxima - K-Fold: 0.4015
cat("Metodo adotado como referencia:", melhor_metodo, "\n")
Metodo adotado como referencia: K-Fold (k=5)
21 Discussao
Os resultados permitem comparar diferentes classificadores aplicados sobre atributos extraidos por transfer learning com a rede MobileNetV2, e tambem avaliar o impacto da estrategia de avaliacao adotada.
A extracao de atributos por CNN pre-treinada substitui o calculo manual de medias, desvios e histogramas de cor por um vetor de 1280 atributos que codificam padroes visuais de alto nivel aprendidos em mais de um milhao de imagens do ImageNet. Essa representacao tende a ser muito mais discriminativa para problemas de classificacao de cenas.
O SVM linear busca fronteiras lineares nesse espaco de 1280 dimensoes. O SVM radial permite fronteiras nao lineares, sendo mais flexivel. O PCA reduz a dimensionalidade antes do SVM, eliminando redundancias entre as 1280 features da CNN. O Random Forest serve como referencia nao-linear e permite identificar quais atributos foram mais relevantes.
Sobre a estrategia de avaliacao: na primeira abordagem, o dataset foi dividido uma unica vez em 70% treino e 30% teste (holdout). Embora simples, esse metodo pode gerar estimativas instáveis com datasets de tamanho moderado, pois o resultado depende de como essa divisao ocorreu. Para verificar se os resultados eram representativos, o experimento foi repetido com validacao cruzada k-fold com k=5: o dataset e dividido em 5 partes estratificadas e, em cada rodada, uma parte diferente e usada como teste. O desempenho final e a media das 5 rodadas.
if (melhor_kf >= melhor_holdout) {cat("O k-fold produziu acuracia igual ou superior ao holdout, sendo adotado como resultado principal.\n")} else {cat("O holdout produziu acuracia superior ao k-fold. Isso pode indicar que a divisao holdout foi favoravel.\n","O k-fold e metodologicamente mais robusto, mas neste caso o holdout resultou em estimativa mais otimista.\n")}
O k-fold produziu acuracia igual ou superior ao holdout, sendo adotado como resultado principal.
22 Conclusao
Este trabalho implementou uma pipeline de classificacao de imagens RGB baseada em transfer learning, reducao de dimensionalidade e classificadores supervisionados, avaliada por duas estrategias distintas.
A estrategia de usar a MobileNetV2 pre-treinada como extrator de atributos, seguida de SVM ou Random Forest, combina o poder de representacao das redes neurais com a interpretabilidade dos classificadores classicos, sem necessidade de treinar a CNN do zero.
cat(sprintf("O melhor resultado foi obtido com '%s' usando a estrategia '%s', com acuracia de %.1f%%.\n", resultados_finais$modelo[1], melhor_metodo,max(resultados_finais$acuracia) *100))
O melhor resultado foi obtido com 'SVM linear' usando a estrategia 'K-Fold (k=5)', com acuracia de 40.2%.
Como expansao futura, o trabalho pode ser repetido com outros extratores CNN presentes no material da disciplina (EfficientNetB0, ResNet50, VGG19) e com a incorporacao das imagens TIR ao vetor de atributos, aproveitando a informacao termica disponivel no dataset.