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?
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?
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.
valor | classe | |
---|---|---|
0 | 0.266281 | 1 |
1 | 0.103869 | 1 |
2 | 0.785274 | 1 |
3 | 0.279765 | 1 |
4 | 0.785164 | 1 |
5 | 0.0937456 | 1 |
6 | 0.126195 | 1 |
7 | 0.603127 | 1 |
8 | 0.748591 | 1 |
9 | 0.0111476 | 1 |
10 | 0.825336 | 1 |
11 | 0.809339 | 1 |
12 | 0.792485 | 1 |
13 | 0.457011 | 1 |
14 | 0.633615 | 0 |
15 | 0.43339 | 0 |
16 | 0.757643 | 0 |
17 | 0.50181 | 0 |
18 | 0.149228 | 0 |
19 | 0.882637 | 0 |
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 ^^