Repro
import joblib
from evalml.demos import load_fraud
from evalml.preprocessing.data_splitters import BalancedClassificationDataCVSplit
splitter = BalancedClassificationDataCVSplit(n_splits=3, random_seed=0, shuffle=True)
X, y = load_fraud(5000)
X = X.to_dataframe()
y = y.to_series().astype("int")
for train, test in splitter.split(X, y):
print((joblib.hash(train), joblib.hash(test)))
# Output
('75f1b95d7ce307ac6c793055330969aa', '8c89fe1a592c50a700b6d5cbb02dba8b')
('f8c849bbfbed37c13f66c5c742e237cb', '9c4879fb550fded8be9ac03e95a1bf95')
('cdc21f0d6bbf45459c9695258f7f04dc', '5b575765bbe176e732b8eb4dc1bf2822')
for train, test in splitter.split(X, y):
print((joblib.hash(train), joblib.hash(test)))
# Output
('bf462b82af243c552ac48acad2dfd748', '8c89fe1a592c50a700b6d5cbb02dba8b')
('b8341b536c63c7957c099b05e315f49c', '9c4879fb550fded8be9ac03e95a1bf95')
('780e74673b601790037fc0b17dde56fe', '5b575765bbe176e732b8eb4dc1bf2822')
for train, test in splitter.split(X, y):
print((joblib.hash(train), joblib.hash(test)
# Output
('385f6c538568ad3a33cf84f61d94144c', '8c89fe1a592c50a700b6d5cbb02dba8b')
('8db65d0a3bdf87ae0f135b9766a260dd', '9c4879fb550fded8be9ac03e95a1bf95')
('2a7293fc1308b8a572091d7c76d20205', '5b575765bbe176e732b8eb4dc1bf2822')
Esto es diferente del comportamiento del divisor sklearn:
from sklearn.model_selection import StratifiedKFold
kfold = StratifiedKFold(n_splits=3, random_state=0, shuffle=True)
for train, test in kfold.split(X, y):
print((joblib.hash(train), joblib.hash(test)))
#Output
('6c30ee6a11803927024354405389506a', '8c89fe1a592c50a700b6d5cbb02dba8b')
('df0a70e2e6ca783f12461e8c82a26ad4', '9c4879fb550fded8be9ac03e95a1bf95')
('2898e4b3d3621b436641016499f4aafb', '5b575765bbe176e732b8eb4dc1bf2822')
for train, test in kfold.split(X, y):
print((joblib.hash(train), joblib.hash(test)))
# Output
('6c30ee6a11803927024354405389506a', '8c89fe1a592c50a700b6d5cbb02dba8b')
('df0a70e2e6ca783f12461e8c82a26ad4', '9c4879fb550fded8be9ac03e95a1bf95')
('2898e4b3d3621b436641016499f4aafb', '5b575765bbe176e732b8eb4dc1bf2822')
Creo que esto es problemático por dos razones:
split
modifica el estado del divisor de datos, significa que tendremos resultados diferentes entre los motores secuencial y paralelo.Gracias por señalar esto.
Personalmente, este comportamiento no me molesta. Siempre que cada vez que inicializamos con una semilla determinada, obtengamos la misma secuencia de salida después de ese punto, estamos bien. Me preocuparía si no respetáramos la semilla aleatoria; pero eso no es lo que rastrea este problema.
Mi recomendación: no hagas nada. Como tal, cerrando.
@freddyaboulton si no está de acuerdo con este comportamiento, vamos a discutirlo, me refiero a hablar 😅
@dsherry Creo que vale la pena cambiar esto por dos razones:
Es malo para la búsqueda automática en paralelo
Permítanme profundizar en 2. Con el comportamiento actual, se espera que el motor secuencial modifique el estado del divisor de datos durante la búsqueda. En la evaluación paralela, seleccionamos el divisor de datos y lo enviamos a los trabajadores para que calculen la división. Dado que los trabajadores obtienen una copia del divisor, no modifican el estado del divisor de datos original.
Esto introduce una diferencia en el comportamiento entre los motores secuenciales y paralelos porque las divisiones no coincidirían dependiendo del orden en que se evalúe la tubería. Esto significa que la misma combinación de canalización / parámetro obtendría resultados diferentes en el motor secuencial y en el motor paralelo y creo que eso no es deseable.
En mi opinión, el punto 1 es razón suficiente para solucionar este problema porque todas nuestras canalizaciones deben evaluarse con los mismos datos si queremos poder compararlas de manera significativa. Pero a medida que avanzamos hacia la evaluación paralela, creo que es importante que nos aseguremos de que la modificación del estado global no sea parte de nuestro comportamiento esperado.
El plan avanza:
BalancedClassificationDataCVSplit
¡Gracias a todos por la discusión!