Evalml: BalancedClassificationDataCVSplit produce diferentes divisiones cada vez que se llama

Creado en 16 mar. 2021  ·  3Comentarios  ·  Fuente: alteryx/evalml

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:

  1. Dado que BalancedClassificationDataCVSplit es el divisor predeterminado en automl, significa que nuestras tuberías se evalúan en diferentes divisiones
  2. Dado que split modifica el estado del divisor de datos, significa que tendremos resultados diferentes entre los motores secuencial y paralelo.
bug

Todos 3 comentarios

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:

  1. Introduce variaciones en la búsqueda automática porque las diferentes canalizaciones se evalúan en diferentes datos. Esto hace que la tabla de clasificación sea un poco engañosa porque las puntuaciones no se calculan con los mismos datos.
  2. 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:

  1. Solucione este problema modificando BalancedClassificationDataCVSplit
  2. A largo plazo, nos gustaría escribir pruebas que verifiquen que no alimentamos diferentes divisiones a diferentes tuberías en la búsqueda automática.

¡Gracias a todos por la discusión!

¿Fue útil esta página
0 / 5 - 0 calificaciones