如何使scikit确定性?

5 投票
1 回答
2042 浏览
提问于 2025-04-18 05:14

我正在使用 scikit-learn 来训练一些分类器。我进行了交叉验证,然后计算了 AUC(曲线下面积)。但是每次运行测试时,我得到的 AUC 数值都不一样,尽管我确保使用了种子和 RandomState。我希望我的测试结果是确定性的。以下是我的代码:

from sklearn.utils import shuffle
SEED = 0
random_state = np.random.RandomState(SEED)
X, y = shuffle(data, Y, random_state=random_state)
X_train, X_test, y_train, y_test = \
        cross_validation.train_test_split(X, y, test_size=test_size, random_state=random_state)
clf = linear_model.LogisticRegression()
kfold = cross_validation.KFold(len(X), n_folds=n_folds)
mean_tpr = 0.0
mean_fpr = np.linspace(0, 1, 100)

for train, test in kfold:
        probas_ = clf.fit(X[train], Y[train]).predict_proba(X[test])
        fpr, tpr, thresholds = roc_curve(Y[test], probas_[:, 1])
        mean_tpr += interp(mean_fpr, fpr, tpr)
        mean_tpr[0] = 0.0

mean_tpr /= len(kfold)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)

我的问题是:

  1. 我的代码中是否有什么问题导致每次运行结果都不同?
  2. 有没有全局的方法可以让 scikit 保持结果的确定性?

编辑:

我刚刚尝试了这个:

test_size = 0.5
X = np.random.randint(10, size=(10,2))
Y = np.random.randint(2, size=(10))
SEED = 0
random_state = np.random.RandomState(SEED)
X_train, X_test, y_train, y_test = \
    cross_validation.train_test_split(X, Y, test_size=test_size, random_state=random_state)

print X_train # I recorded the result

然后我做了:

X_train, X_test, y_train, y_test = \
    cross_validation.train_test_split(X, Y, test_size=test_size, random_state=6) #notice the change in random_state

接着我又做了:

X_train, X_test, y_train, y_test = \
    cross_validation.train_test_split(X, Y, test_size=test_size, random_state=random_state)

print X_train #the result is different from the first one!!!!

如你所见,尽管我使用了相同的 random_state,我还是得到了不同的结果!该怎么解决呢?

1 个回答

4

LogisticRegression这个工具在内部会用到随机性,并且有一个(还没文档说明,稍后会修复)叫做random_state的参数。

没有一个全局的方法来设置这个随机状态,因为不幸的是,LogisticRegression和SVM的代码只能用一种比较“hacky”的方式来设置随机状态。这是因为这些代码来自Liblinear和LibSVM,它们使用的是C语言标准库的rand函数,而这个函数不能用一种规范的方式来设置种子。

编辑 上面的说法是对的,但可能不是问题的根本原因。你在调用时只传递了一个np.random.RandomState,而应该传递相同的整数种子,这样更容易复现结果。

撰写回答