A Importância da Validação Cruzada em Machine Learning

Problema da Generalização

Métodos de Validação Cruzada

1. K-fold Cross-Validation

  • Divisão dos Dados: O conjunto de dados é dividido em K subconjuntos mutuamente exclusivos, chamados de folds. O valor de K é escolhido pelo usuário, sendo 5 ou 10 valores comuns.
  • Iteração e Treinamento: O modelo é treinado K vezes. Em cada iteração, um fold diferente é usado como conjunto de validação, enquanto os K-1 folds restantes são usados como conjunto de treinamento.
  • Avaliação do Modelo: A performance do modelo é avaliada em cada uma das K iterações, gerando K métricas de performance (como acurácia, precisão, recall, F1-score, etc.).
  • Média das Métricas: Ao final das K iterações, as métricas de desempenho são médias para obter uma estimativa final do desempenho do modelo
  • Estimação mais precisa do erro de generalização: Ao realizar múltiplas iterações, a validação cruzada fornece uma estimativa mais confiável do desempenho do modelo em dados não vistos.
  • Evita viés: A divisão aleatória dos dados em folds ajuda a reduzir o viés na estimativa do erro.
  • Flexibilidade: Permite comparar diferentes modelos e ajustar hiperparâmetros de forma mais eficiente.
import numpy as np
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# Carregar o conjunto de dados
data = load_iris()
X, y = data.data, data.target

# Definir o modelo
model = RandomForestClassifier()

# Definir o K-Fold Cross-Validation
kf = KFold(n_splits=5, shuffle=True, random_state=42)

accuracies = []

# Iterar sobre cada fold
for train_index, test_index in kf.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    # Treinar o modelo
    model.fit(X_train, y_train)
    
    # Prever no conjunto de teste
    y_pred = model.predict(X_test)
    
    # Avaliar a acurácia
    accuracy = accuracy_score(y_test, y_pred)
    accuracies.append(accuracy)

# Média das acurácias
mean_accuracy = np.mean(accuracies)
print(f'Acurácia Média: {mean_accuracy}')
Acurácia Média: 0.9600000000000002

2. Stratified K-Fold Cross-Validation

  • Divisão dos Dados: O conjunto de dados é dividido aleatoriamente em K partes ou “folds”. No entanto, ao invés de uma divisão simples, a estratificação garante que a proporção das classes seja preservada em cada fold.
  • Iteração e Treinamento: O modelo é treinado K vezes. Em cada iteração, um fold diferente é usado como conjunto de validação, enquanto os K-1 folds restantes são usados como conjunto de treinamento.
  • Avaliação do Modelo: A performance do modelo é avaliada em cada uma das K iterações, gerando K métricas de performance.
  • Média das Métricas: As métricas de performance obtidas são então promediadas para fornecer uma estimativa final do desempenho do modelo.
  • Preservação da Distribuição das Classes: Garantir que cada fold tenha a mesma distribuição de classes que o conjunto de dados original ajuda a obter uma avaliação mais representativa do desempenho do modelo, especialmente em dados desbalanceados.
  • Redução de Variabilidade: Assim como no K-Fold tradicional, ao promediar os resultados de K iterações, a variabilidade na estimativa do desempenho do modelo é reduzida.
  • Melhor Generalização: Ajuda a evitar que o modelo aprenda de forma enviesada devido à distribuição desigual das classes.
import numpy as np
from sklearn.model_selection import StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# Carregar o conjunto de dados
data = load_iris()
X, y = data.data, data.target

# Definir o modelo
model = RandomForestClassifier()

# Definir o Stratified K-Fold Cross-Validation
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

accuracies = []

# Iterar sobre cada fold
for train_index, test_index in skf.split(X, y):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    # Treinar o modelo
    model.fit(X_train, y_train)
    
    # Prever no conjunto de teste
    y_pred = model.predict(X_test)
    
    # Avaliar a acurácia
    accuracy = accuracy_score(y_test, y_pred)
    accuracies.append(accuracy)

# Média das acurácias
mean_accuracy = np.mean(accuracies)
print(f'Acurácia Média: {mean_accuracy}')

Acurácia Média: 0.9533333333333335

3. Leave-One-Out Cross-Validation (LOOCV)

Caso de uso

  • Iteração sobre cada Observação: Para cada observação no conjunto de dados, essa única observação é usada como o conjunto de validação, e o restante das observações são usadas como conjunto de treinamento.
  • Treinamento e Validação: O modelo é treinado usando o conjunto de treinamento e avaliado usando o conjunto de validação.
  • Cálculo das Métricas de Desempenho: A métrica de desempenho (como acurácia, erro quadrático médio, etc.) é calculada para cada iteração.
  • Média das Métricas: As métricas de desempenho obtidas em cada iteração são então promediadas para fornecer uma estimativa final do desempenho do modelo.
  • Uso Completo dos Dados: Todos os dados são utilizados tanto para treinamento quanto para validação.
  • Redução do Viés: Como cada observação é usada como conjunto de validação, o viés na estimativa do desempenho do modelo é minimizado.
  • Detecção de Variabilidade: Fornece uma medida clara de como pequenas mudanças nos dados podem afetar o desempenho do modelo.
  • Custo Computacional Elevado: Para grandes conjuntos de dados, LOOCV pode ser computacionalmente caro, pois o modelo precisa ser treinado NNN vezes, onde NNN é o número de observações.
  • Alta Variabilidade: Pode ter alta variabilidade, especialmente em conjuntos de dados pequenos, pois cada iteração depende fortemente de uma única observação.
import numpy as np
from sklearn.model_selection import LeaveOneOut
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# Carregar o conjunto de dados
data = load_iris()
X, y = data.data, data.target

# Definir o modelo
model = RandomForestClassifier()

# Definir o Leave-One-Out Cross-Validation
loo = LeaveOneOut()

accuracies = []

# Iterar sobre cada observação
for train_index, test_index in loo.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    # Treinar o modelo
    model.fit(X_train, y_train)
    
    # Prever no conjunto de teste
    y_pred = model.predict(X_test)
    
    # Avaliar a acurácia
    accuracy = accuracy_score(y_test, y_pred)
    accuracies.append(accuracy)

# Média das acurácias
mean_accuracy = np.mean(accuracies)
print(f'Acurácia Média: {mean_accuracy}')

Acurácia Média: 0.9466666666666667

4. Validação por método Holdout

  • Divisão dos Dados: O conjunto de dados original é dividido aleatoriamente em dois subconjuntos: um conjunto de treinamento e um conjunto de teste. Uma divisão comum é usar 70-80% dos dados para treinamento e 20-30% para teste.
  • Treinamento do Modelo: O modelo de machine learning é treinado usando apenas o conjunto de treinamento.
  • Avaliação do Modelo: Após o treinamento, o modelo é avaliado no conjunto de teste usando métricas de performance adequadas (como acurácia, precisão, recall, F1-score, etc.).
  • Simplicidade e Facilidade de Implementação: O Holdout Method é simples de entender e fácil de implementar.
  • Baixo Custo Computacional: Como o modelo é treinado apenas uma vez, o custo computacional é menor em comparação com métodos como K-Fold ou LOOCV.
  • Eficiência em Conjuntos de Dados Grandes: Para conjuntos de dados grandes, uma única divisão pode ser suficiente para fornecer uma estimativa confiável do desempenho do modelo.
  • Dependência da Divisão: A performance do modelo pode variar significativamente dependendo de como os dados são divididos. Uma única divisão pode não ser representativa do desempenho real do modelo.
  • Uso Ineficiente dos Dados: Apenas uma parte dos dados é usada para treinamento, o que pode ser uma desvantagem quando se tem um conjunto de dados pequeno.
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

# Carregar o conjunto de dados
data = load_iris()
X, y = data.data, data.target

# Dividir o conjunto de dados em treinamento (70%) e teste (30%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Definir o modelo
model = RandomForestClassifier()

# Treinar o modelo no conjunto de treinamento
model.fit(X_train, y_train)

# Prever no conjunto de teste
y_pred = model.predict(X_test)

# Avaliar a acurácia
accuracy = accuracy_score(y_test, y_pred)
print(f'Acurácia: {accuracy}')
Acurácia: 1.0

Conclusão

  1. Mãos à obra aprendizado de máquina com Scikit-Learn, Keras & TensorFlow: conceitos, ferramentas e técnicas para a construção de sistemas inteligentes.
  2. Python para análise de dados
  3. Estatística Prática Para Cientistas de Dados: 50 Conceitos Essenciais
  4. An Introduction to Statistical Learning (Python e R)

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima
×