使用多处理时无法重现 scikit-learn 和 numpy 相关代码

Failure to reproduce scikit-learn and numpy dependent code when multiprocessing is used

n_jobs=1cross_validate 函数时,下面的代码是完全可重现的,但当 n_jobs=-12.

时则不然
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_validate,RepeatedStratifiedKFold

class DecisionTree(DecisionTreeClassifier):
    def fit(self,X,Y):
        weight = np.random.uniform(size=Y.shape)
        return super().fit(X,Y,sample_weight=weight)

def main():
    X,Y = load_iris(return_X_y=True)
    rks = RepeatedStratifiedKFold(n_repeats=2,n_splits=5,random_state=42)
    clf = DecisionTree(random_state=42)
    res = cross_validate(clf,X,Y,cv=rks,n_jobs=2)['test_score']*100
    return res.mean(),res.std()

if __name__=='__main__':
    np.random.seed(42)
    print(main())

请注意 np.random.uniformfit 函数中的调用。如果没有这样的 numpy 调用,代码也可以完全重现。提到了 here that numpy.random.seed is not thread-safe. But I saw no mention of this in sklearn's FAQ,据此在任何地方提供 random_state 就足够了。

有没有办法在 sklearn 中同时使用 numpy 随机调用和多处理,同时保持完全的可重复性?

编辑:我认为如果我们将 n_jobs>1 放入接受它的估计器中,同时实例化 RandomForestClassifier 例如,它可以很好地重现。

看起来你的 DecisionTree class 应该使用传入的 random_state。我得到一致的结果:

from sklearn.utils import check_random_state

class DecisionTree(DecisionTreeClassifier):
    def fit(self, X, Y):
        rng = check_random_state(self.random_state)
        weight = rng.uniform(size=Y.shape)
        return super().fit(X, Y, sample_weight=weight)

但除此之外照你做的做。请注意,通过此更改,您还可以删除对 np.random.seed(42) 的调用,因为 RNG 状态已在需要的任何地方明确设置