【问题标题】:Different results with StratifiedShuffleSplit function (scikit-learn) when random_state is None当 random_state 为 None 时,StratifiedShuffleSplit 函数(scikit-learn)的不同结果
【发布时间】:2014-05-15 14:11:36
【问题描述】:

我正在执行交叉验证以正确分类。首先,我使用了 scikit-learn 中的 StratifiedKfold 函数。在某个时候,我想进行更多的迭代,于是我改为使用 StratifiedShuffleSplit。有了这个新功能,我得到的结果发生了变化。最后,我意识到,如果我指定一个 random_state,我会再次获得与使用 StratifiedKfold 作为 CV 时获得的结果相似的结果。

总之,如果我指定 random_state,对于不同的值,我得到的结果会略有不同,类似于我使用 StratifiedKfold 获得的结果(一次迭代,或者我自己计算洗牌,如 here)。但是,如果 random_state 为 none 或未指定,我获得的结果将完全改变。

我检查了当 random_state 为 None 时,train 和 test 索引是不同的并且是分层的,正如预期的那样。

我没有使用随机数生成器的经验,但这对我来说没有任何意义

查看代码我意识到当 random_state 为 None 时,函数 check_random_state 被调用。如果种子为无,此函数返回 np.random (link) 使用的 RandomState 单例。

我给你写了有问题的代码。 如果我将注释行更改为下面的行,我会得到不同的结果。

import numpy as np
import sklearn as skl

(...)
#skCVs=skl.cross_validation.StratifiedShuffleSplit(classes,n_iter=iterations*kfoldCV,test_size = 1/float(kfoldCV),random_state=5)
skCVs=skl.cross_validation.StratifiedShuffleSplit(classes,n_iter=iterations*kfoldCV,test_size = 1/float(kfoldCV))

for train,test in skCVs:

   (classification, ...)

我使用的是 0.14 版的 sklearn。

你有什么解释或线索可以帮助理解正在发生的事情吗?

【问题讨论】:

    标签: python random machine-learning scikit-learn cross-validation


    【解决方案1】:

    (Stratified)ShuffleSplit 在拆分之前随机打乱数据。 (伪)随机性由random_state 构造函数参数控制。默认的None 值意味着每个新调用都会产生不同的洗牌。要获得确定性改组,您可以选择传递整数种子。

    【讨论】:

    • 谢谢。我明白你的意思,但是当我指定不同的整数种子或不通过任何整数种子时,我希望得到类似的结果,对吗?问题是我得到了不同手动指定种子的一些结果,但是当我将 random_state 保留为 None 时得到不同的结果。这就像取决于随机数生成器,我的结果会发生变化,这对我来说没有任何意义。
    • 你的“结果变化”是什么意思?对我来说,这听起来像是预期的行为。如果结果不会受到随机改组交叉验证的影响,你为什么要首先进行交叉验证?如果您想要更好地估计平均验证分数(更窄的均值标准误差估计),只需增加迭代次数即可。
    • “结果变化”是指预期的行为。如果我运行 10 倍的 CV,我唯一能做的就是在不改组的情况下增加数据量是使用 15 倍或 20 倍的 CV。这就是为什么我切换到改组版本,以便能够根据需要增加迭代次数。我的问题是,当我使用 StratifiedShuffleSplit 指定 random_state (任何整数)或如果它是 None 运行分类时,我会得到不同的行为。当手动给出种子或从 np.random 的某个随机数生成器中获取种子时,我希望得到相同的结果。
    • 改组的平均验证显着更高?这是 i.i.d 破损的典型症状。假设。当您对数据进行混洗时,您可能会严重过度拟合非 iid 数据。当您具有时间依赖性或当您的测量来自连续样本中分组的不同主题/实验/会话时,就会发生这种情况。您需要一个在组边界上拆分的特定方案,以便来自给定主题的样本都在训练折叠或验证折叠中。
    • 这可能是有道理的。我的数据中可能存在一些时间依赖性(实际上,这很可能),因此由于非 iid 数据,洗牌可能会过度拟合。谢谢!
    【解决方案2】:

    我也不是随机生成器的专家,但据我所知,如果您不定义 random_state,则会调用不同的 RandomState 类型。这是我找到的解释:

    “如果种子为无,那么 RandomState 将尝试从 /dev/urandom(或 Windows 模拟)中读取数据(如果可用)或从时钟中读取数据。”[1]

    "如果 size 是一个整数,则返回一个填充了生成值的一维数组。" [1]

    您可以在此处 [2] 的“check_random_state”中查看调用的两个不同随机生成器的代码。

    [1]http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.RandomState.html

    [2]https://github.com/scikit-learn/scikit-learn/blob/0.14.X/sklearn/utils/validation.py

    这对你有帮助吗?

    【讨论】:

    • 谢谢。如果我指定 RandomState 或不指定,我看到我正在使用不同的随机生成器。问题是我不明白为什么不同的随机数生成器会得到不同的结果。
    • 欢迎您阿吉岑。您会看到,在无种子生成器中,每次都会采用不同的种子,但如果您为生成器设置种子,那么每次都会出现相同的“随机性”,因为它来自同一个种子。也许你应该看看这篇文章:stackoverflow.com/questions/9023660/…
    • 我同意。但是,它应该等效于使用不同的手动指定种子或不传递任何种子多次运行代码。唯一的区别是使用了不同的随机数生成器并且不应该改变结果,但它确实......我不知道我是否正确解释了这个问题。
    猜你喜欢
    • 2021-07-15
    • 2018-03-19
    • 2020-11-23
    • 2017-09-05
    • 2019-12-09
    • 2017-12-22
    • 2021-12-20
    • 1970-01-01
    • 2018-12-31
    相关资源
    最近更新 更多