CEAO-802 — Metodos de Analise de Dados
Note
As imagens já vinham pré-rotuladas pelo nome do arquivo. Exemplo: C10_2023_06_M_01_RGB.tiff → classe C10 (Piscina), junho de 2023, manhã
O problema é de classificação supervisionada: aprende-se com exemplos rotulados e avalia-se em exemplos não vistos.
| Classe | Descrição |
|---|---|
| C1 | Vegetação Arbórea |
| C2 | Vegetação Rasteira |
| C3 | Solo Exposto |
| C4 | Pavimento Asfáltico |
| C5 | Pavimento de Solo Estabilizado |
| C6 | Telhado Cerâmico |
| C7 | Telhado de Fibrocimento |
| Classe | Descrição |
|---|---|
| C8 | Telhado Metálico |
| C9 | Placa Fotovoltaica |
| C10 | Piscina |
| C11 | Pedra Sabão |
| C12 | Caixa D’água |
| C13 | Veículos |
MobileNetV2 pré-treinada no ImageNet
Esses 1280 valores capturam padrões visuais complexos: bordas, texturas, formas e estruturas aprendidas em milhões de imagens.
| Tradicional | Transfer | |
|---|---|---|
| Features | ~60 | 1280 |
| Tipo | Manual | CNN |
| Exemplos | Média RGB | Padrões visuais |
| Treinamento | Não | Pré-treinado |
Tip
Não é necessário treinar a rede do zero — apenas reutilizamos o que ela já aprendeu.
library(keras3)
# Carregar MobileNetV2 sem a camada de classificação
modelo_base <- application_mobilenet_v2(
include_top = FALSE, # remove a camada final de 1000 classes
weights = "imagenet",# pesos pré-treinados no ImageNet
pooling = "avg", # GlobalAveragePooling -> vetor 1D
input_shape = c(224L, 224L, 3L)
)
# modelo_base$output_shape --> (None, 1280)
# Extrair features de uma imagem
img <- image_load(arquivo, target_size = c(224L, 224L))
arr <- image_to_array(img) # array 224x224x3
arr <- array_reshape(arr, c(1L, 224L, 224L, 3L)) # batch de 1
arr <- (arr / 127.5) - 1.0 # normalização MobileNetV2
feat <- predict(modelo_base, arr, verbose = 0L)
# feat: matrix 1 x 1280| # | Modelo | Kernel / Tipo | Parâmetros |
|---|---|---|---|
| 1 | SVM linear | Linear | cost = 1 |
| 2 | SVM radial | RBF | cost = 10, gamma = 0.01 |
| 3 | SVM radial ajustado | RBF | cost e gamma via grid search |
| 4 | PCA + SVM radial | RBF | PCA (≥95% variância) + RBF |
| 5 | Random Forest | — | 500 árvores |
Note
SVM (Support Vector Machine): encontra o hiperplano que maximiza a margem entre as classes. Com kernel RBF, fronteiras não-lineares são possíveis via kernel trick.
library(e1071); library(randomForest); library(caret)
# Pré-processamento: remover NZV e normalizar (center + scale)
preproc <- preProcess(x_treino, method = c("center", "scale"))
x_treino_n <- predict(preproc, x_treino)
x_teste_n <- predict(preproc, x_teste)
# Modelo 1: SVM linear
modelo_linear <- svm(x = x_treino_n, y = y_treino,
kernel = "linear", cost = 1, scale = FALSE)
# Modelo 3: Ajuste automático de hiperparâmetros (grid search + CV interna)
ajuste <- tune.svm(x = x_treino_n, y = y_treino, kernel = "radial",
cost = c(0.1, 1, 10, 100),
gamma = c(0.001, 0.01, 0.05, 0.1),
tunecontrol = tune.control(cross = 5))
# Modelo 5: Random Forest
modelo_rf <- randomForest(x = x_treino_n, y = y_treino,
ntree = 500, importance = TRUE)O que é?
Limitação: o resultado depende de como essa divisão ocorreu. Com datasets pequenos, pode ser instável.
O que é?
Vantagem: toda imagem aparece no teste exatamente uma vez — estimativa mais robusta e confiável.
folds <- createFolds(dados$classe, k = 5, list = TRUE, returnTrain = FALSE)
for (fold_i in seq_len(5)) {
idx_teste <- folds[[fold_i]]
idx_treino <- setdiff(seq_len(nrow(dados)), idx_teste)
# Pré-processar com base APENAS no treino do fold
pp <- preProcess(dados[idx_treino, preditores], method = c("center","scale"))
x_tr <- predict(pp, dados[idx_treino, preditores])
x_te <- predict(pp, dados[idx_teste, preditores])
# Treinar modelos
m_linear <- svm(x = x_tr, y = dados$classe[idx_treino],
kernel = "linear", cost = 1, scale = FALSE)
# Avaliar
pred <- predict(m_linear, x_te)
cm <- confusionMatrix(pred, dados$classe[idx_teste])
# Guardar métricas do fold
metricas_folds[[fold_i]] <- extrair_metricas(cm)
}
resultados_kfold <- bind_rows(metricas_folds) %>%
group_by(modelo) %>%
summarise(across(everything(), mean))Resultado principal
Por que SVM linear ganhou do radial?
Os 1280 atributos da MobileNetV2 já são suficientemente representativos para que as classes sejam aproximadamente linearmente separáveis nesse espaço — o kernel RBF não agrega ganho relevante.
Trabalhos futuros
CEAO-802 — Metodos de Analise de Dados