2
respostas

Como usar estes recursos na prática?

Apendo melhor quando vejo esses modelos e recursos serem usados em casos reais, em que caso vou usá-lo para ajudar a ter melhores resultados?

2 respostas

Oii Darlan, tudo bem contigo? Espero que sim!

Desculpa a demora em te dar um retorno por aqui.

Você vai usar o StratifiedKFold ao invés do KFold principalmente quando tiver um conjunto de dados desbalanceados, ou seja, que tem mais uma categoria do que outra. Quando temos dados desbalanceados, os conjuntos de treino e teste precisam conter números compatíveis com as nossas amostras, por exemplo, em um caso que temos 20 amostras e 14 delas tem classe 1 e apenas 6 tem classe 0, temos um conjunto de dados desbalanceado, então precisamos ter certeza de que pelo menos 4 ou 5 valores desses 6 da classe 0 estarão presentes no conjunto de treinamento, pois pense comigo, caso o seu modelo esteja acostumado a prever apenas dados de classe 1, quando chegar algum de classe 0 ele vai erroneamente classificar como 1 e a acurácia do seu modelo cai demais.

Preparei um exemplo pra ti, afim de ficar mais visual e mais fácil de entender. Considere o mesmo exemplo acima, 20 amostras com 14 delas de classe 1 e apenas 6 de classe 0, dessa forma:

import pandas as pd 
import numpy as np

target = np.ones (20) 
target [-6:] = 0

df = pd.DataFrame ({'valor': np.random.random (20), 
                  'classe': target})
df

Gerando a tabela de valores aleatórios que temos a seguir.

valorclasse
00.2662811
10.1038691
20.7852741
30.2797651
40.7851641
50.09374561
60.1261951
70.6031271
80.7485911
90.01114761
100.8253361
110.8093391
120.7924851
130.4570111
140.6336150
150.433390
160.7576430
170.501810
180.1492280
190.8826370

Podemos dividir esse nosso dataset de 3 formas diferentes aqui para notar a diferença. A primeira delas é utilizando o train_test_split, que é o método convencional utilizado. No train_test_split nós temos diversos parâmetros que podem ser usados, um deles é o shuffle, ou seja o modo aleatório, e no primeiro resultado o valor de shuffle é False e no segundo usaremos True, e em alguns casos essa aleatoriedade é o suficiente para nos auxiliar.

Usando Shuffle=False

from sklearn.model_selection import train_test_split
X = df.valor
y = df.classe
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
print("Treino:", X_train.index, "Teste:", X_test.index)
`

Saída

Treino: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], dtype='int64') Teste: Int64Index([16, 17, 18, 19], dtype='int64')

Usando Shuffle=True

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
print("Treino:", X_train.index, "Teste:", X_test.index)

Saída

Treino: Int64Index([10, 6, 4, 19, 14, 13, 8, 17, 12, 11, 2, 18, 7, 5, 15, 0], dtype='int64') Teste: Int64Index([3, 9, 16, 1], dtype='int64')

Você consegue notar a diferença de resultados apenas utilizando o shuffle? No primeiro caso, muito provavelmente nossos valores seriam classificados como classe 1 mesmo sendo classe 0, mas quando fazemos a aleatoriedade isso muda e provavelmente o número 16 seria classificado corretamente.

Partindo para a segunda forma, que é utilizando o KFold, faremos uma comparação semelhante. Todos esses modelos tem um parâmetro chamado random_state que é onde definimos nossa SEED e inserimos o valor dela para que o resultado seja aleatório mas ainda seja replicável, então no primeiro exemplo não vou definir nenhum valor de Shuffle nem de random_state, e depois faremos o uso deles.

Utilizando apenas o parâmetro n_splits

from sklearn.model_selection import KFold

X = df.valor
y = df.classe

kf = KFold(n_splits=4)

for train_index, test_index in kf.split(X):
    print("Treino:", train_index, "Teste:", test_index)

Saída

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

Resposta continua...

Continuação da resposta:

Agora utilizando também os parâmetros Shuffle=True e definindo um valor para o random_state:

kf = KFold(n_splits=4, shuffle=True, random_state=1)

for train_index, test_index in kf.split(X):
    print("Treino:", train_index, "Teste:", test_index)

Saída

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

Você consegue notar que no primeiro caso, sem utilizar a aleatoriedade, temos o mesmo problema do train_test_split? Onde nosso conjunto seria classificado de forma errada? E mesmo usando a aleatoriedade, os conjuntos não estão bem divididos, pois ele não leva em conta esse desbalanço das classes.

Por fim, vamos usar o StratifiedKFold, com os mesmos termos que já levei em conta no KFold, e comparar os resultados entre eles.

Utilizando apenas o parâmetro n_splits

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=4)
for train_index, test_index in skf.split(X, y):
    print("Treino:", train_index, "Teste:", test_index)

Saída:

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

Agora utilizando também os parâmetros Shuffle=True e definindo um valor para o random_state:

skf = StratifiedKFold(n_splits=4, shuffle=True, random_state=1)
for train_index, test_index in skf.split(X, y):
     print("Treino:", train_index, "Teste:", test_index)

Saída:

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

Você consegue perceber que todos os nossos conjuntos de treino tem pelo menos 4 valores da classe 0, para que cada classe seja representada na classe de treino e na classe de teste? É por isso que o uso do StratifiedKFold é recomendado em relação ao Kfold, ele faz com que o modelo não perca acurácia por conta de dados desbalanceados.

Espero ter te ajudado, mas qualquer outra dúvida estou por aqui, ok?

Bons estudos ^^

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