1
resposta

sobre stratifiedKfold

Tenho uma dúvida relacionada a quando devo usar stratifiedKfold ou somente Kfold. Para definir se usaremos um ou o outro devemos entender se os dados estão desbalanceados ou não. Penso ser fácil determinar esse desbalanço se temos dados binários - basta utilizar .value_counts(). E em dados quantitativos contínuos ? Sugerem não estratificar e só usar o shuffle? /

1 resposta

Olá, Pietro! Tudo tranquilo por aí?

Primeiramente gostaria de pedir desculpas pela demora em te responder.

Suas colocações estão corretíssimas. O KFold divide nossos dados em k dobras sem prestar atenção no balanceamento dos dados, e pode cair na condição de seus dados serem treinados com os rótulos todos com valor 1 e quando for usado o conjunto de dados para teste, os dados contenham algum 0 lá, por exemplo. O StratifiedKFold é um pouco melhor, esse algoritmo faz a mesma coisa que o KFold mas com uma grande melhoria: Obedece ao balanceamento dos nossos rótulos.

Como nossos dados nos rótulos serão respostas para perguntas do tipo "É porco ou cachorro?", "O carro foi vendido ou não?", ou seja nosso rótulo será sempre sim ou não, 0 ou 1, logo tem-se uma distribuição balanceada ou desbalanceada de acordo com os rótulos, e é aí que o StratifiedKFold trabalha separando nossos dados para treino e teste mantendo a proporção dos rótulos nas K dobras.

Vamos a um exemplo para deixar mais claro.

# Inicio do código

import pandas as pd
import numpy as np

target = np.ones(16)
target[-4:] = 0

df = pd.DataFrame({'feature':np.random.random(16), 'rotulo':target})
df

Saída:

featurerotulo
00.05613581
10.985911
20.02392511
30.6699941
40.9611321
50.7078041
60.1331471
70.4267491
80.2939311
90.09083771
100.5128031
110.03595211
120.9187330
130.4324510
140.1920
150.3875630

Aqui estamos gerando nosso DataFrame com a coluna feature sendo número aleatórios contínuos entre 0 a 1, e a coluna rotulo com números 1´s da linha 0 a 11 e com números 0´s da linha 12 a 15.

Nossos dados estão bem desbalanceados com uma proporção de 1/3 de 0´s para 1´s.

from sklearn.model_selection import StratifiedKFold

X = df.feature
y = df.rotulo

skf = StratifiedKFold(n_splits=4, shuffle=True, random_state=42)

for treino_index, teste_index in skf.split(X, y):
    print("Treino:", treino_index, "Teste:", teste_index)

Saída:

Treino: [ 0  1  3  4  7  8  9 10 11 13 14 15] Teste: [ 2  5  6 12]
Treino: [ 0  1  2  3  5  6  7  9 11 12 14 15] Teste: [ 4  8 10 13]
Treino: [ 0  1  2  4  5  6  7  8 10 12 13 15] Teste: [ 3  9 11 14]
Treino: [ 2  3  4  5  6  8  9 10 11 12 13 14] Teste: [ 0  1  7 15]

Esses números que foram retornados são os índices de nossa amostra, ou seja 0 representa a primeira linha, 1 a segunda linha e assim sucessivamente.

Percebe que em treino, na primeira linha da saída, há 9 amostras com rótulos iguais a 1 ( 0 1 3 4 7 8 9 10 11) e 3 (13 14 15) com rótulos iguais a 0? e em teste, também na primeira linha há 3 (2 5 6) amostras com rótulos iguais a 1 e 1 com rótulo igual a 0 (12)? logo a nossa proporção de 1/3 foi mantida para todas as 4 dobras que o StratifiedKFold realizou.

Então sugiro usar o StratifiedKFold com shuffle, pois já resolve esse problema do desbalanceamento, caso tenha, e o shuffle melhora a aleatoriedade.

Espero ter ajudado, mas se ainda persistir alguma dúvida estou sempre à disposição.

:) (smile face)

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.Bons Estudos!