Evalml: BalancedClassificationDataCVSplit 每次调用都会产生不同的分割

创建于 2021-03-16  ·  3评论  ·  资料来源: alteryx/evalml

再现

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')

这与 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')

我认为这是有问题的,原因有两个:

  1. 由于 BalancedClassificationDataCVSplit 是 automl 中的默认拆分器,这意味着我们的管道在不同的拆分上进行评估
  2. 由于split修改了数据拆分器的状态,这意味着我们将在顺序引擎和并行引擎之间得到不同的结果。

所有3条评论

感谢您指出了这一点。

就我个人而言,这种行为并不困扰我。 只要每次我们用某个种子初始化,在那之后我们得到相同的输出序列,我们就很好。 如果我们不尊重随机种子,我会担心; 但这不是这个问题所追踪的。

我的建议:什么都不做。 如此,闭幕。

@freddyaboulton如果你不同意这种行为,让我们一决雌雄,我的意思是谈谈 😅

@dsherry我认为这值得改变有两个原因:

  1. 它为 automl 搜索引入了差异,因为对不同的数据评估不同的管道。 这使得排名表有点误导,因为分数不是根据相同的数据计算的。
  2. 这对并行自动搜索不利

    让我详细说明 2. 根据当前的行为,顺序引擎有望在整个搜索过程中修改数据拆分器的状态。 在并行 evalml 中,我们腌制数据拆分器并将其发送给工作人员以计算拆分。 由于工作人员获得了拆分器的副本,因此他们不会修改原始数据拆分器的状态。

这在顺序引擎和并行引擎之间引入了行为差异,因为根据评估管道的顺序,拆分将不匹配! 这意味着相同的管道/参数组合在顺序引擎和并行引擎中会得到不同的结果,我认为这是不可取的。

在我看来,第 1 点足以解决这个问题,因为如果我们希望能够有意义地比较它们,我们所有的管道都应该在相同的数据上进行评估。 但是当我们转向并行 evalml 时,我认为确保修改全局状态不是我们预期行为的一部分很重要。

推进计划:

  1. 通过修改BalancedClassificationDataCVSplit解决此问题
  2. 从长远来看,我们希望编写测试来验证我们不会在 automl 搜索中将不同的拆分提供给不同的管道。

谢谢大家的讨论!

此页面是否有帮助?
0 / 5 - 0 等级