Scikit learn中的随机状态(伪随机数)

203

我想在Scikit Learn中实现机器学习算法,但我不理解参数random_state的作用是什么?为什么要使用它?

我也不理解何为伪随机数。

8个回答

295

train_test_split将数组或矩阵随机分成训练集和测试集。这意味着,每次运行它而没有指定random_state时,您都会得到不同的结果,这是预期的行为。例如:

运行1:

>>> a, b = np.arange(10).reshape((5, 2)), range(5)
>>> train_test_split(a, b)
[array([[6, 7],
        [8, 9],
        [4, 5]]),
 array([[2, 3],
        [0, 1]]), [3, 4, 2], [1, 0]]

运行 2

>>> train_test_split(a, b)
[array([[8, 9],
        [4, 5],
        [0, 1]]),
 array([[6, 7],
        [2, 3]]), [4, 2, 0], [3, 1]]
它会改变。然而,如果使用random_state=some_number,则可以保证Run 1的输出将等于Run 2的输出,即您的拆分始终相同。实际上随机种子的数字是多少并不重要,无论是42、0、21等数字,每次使用42都会在第一次进行拆分时得到相同的输出结果。这在文档中需要复现结果时很有用,以便每个人在运行示例时始终看到相同的数字。实际上,建议在测试时将random_state设置为固定数字,但在生产环境中如果确实需要随机(而不是固定)拆分,则应将其删除。
关于您的第二个问题,伪随机数生成器是一种生成几乎真正随机数的数字生成器。它们不是真正的随机数的原因超出了本问题的范围,对您来说可能也不重要,您可以查看此处了解更多详细信息。

9
那么我应该设置哪个随机种子?我经常看到使用数字42。 - Elizabeth Susan Joseph
3
@ElizabethSusanJoseph,这并不太重要,我总是在需要可复现性时使用0,否则就使用None。也许像scikit的人喜欢42。 - elyase
72
这很可能解释了为什么数字42经常被使用:http://zh.wikipedia.org/wiki/%E5%93%88%E5%B8%8C%C2%B7%E9%A9%AC%E6%96%AF%E5%85%8B%E7%9A%84%E5%AF%BC%E5%BC%B9%E4%B9%8B%E6%97%85 - denson
4
好的,这里有更多可能性 - elyase
1
@Herbert 这是一个棘手的问题。核心PRNG部分基于numpy,它是一致的(在过去出现问题后,他们引入了许多检查)。如果在sklearn中使用时没有错误,它也会表现出一致性。我会假设这一点(特别是对于像train-test-split和co这样不太复杂的函数)编辑:糟糕,有点晚了 :-) - sascha
显示剩余9条评论

26
如果你的代码中没有指定random_state,那么每次运行代码时都会生成一个新的随机值,训练集和测试集的数值也会随之而变化。
然而,如果指定了一个固定的值,例如random_state=42,则无论执行多少次代码,结果都将是相同的,即训练集和测试集中的数值相同。

14

“随机状态”是什么,为什么要使用它的问题,已经被其他人很好地回答了。我将尝试回答一个问题:“为什么在训练机器学习模型时经常选择随机状态42?为什么不选择12、32或5?是否有科学解释?”

许多学生和从业者使用此数字(42)作为随机状态,是因为许多在线课程的教练使用它。他们经常将随机状态或numpy种子设置为42号,学习者也会毫无思考地遵循相同的做法。

具体来说,42与AI或ML无关。事实上,它是一个通用数字,在机器学习中,实际的随机数是什么并不重要,正如scikit API文档中所述,任何整数都足以完成任务。

42是来自《银河系漫游指南》一书的参考。它代表了“生命宇宙和万物的答案”,意味着一个笑话。它没有其他意义。

参考资料:

  1. 维基百科:《银河系漫游指南》
  2. Stack Exchange:为什么在表示随机时首选数字42
  • 为什么使用数字42
  • Quora:为什么在指示随机性时更喜欢使用数字42
  • YouTube:简单易懂的视频,解释train-test-split中使用随机状态的原因
  • 数字42的意义!


    5

    如果您在代码中没有提到random_state,那么每次执行代码时都会生成一个新的随机值,训练和测试数据集每次都会有不同的值。

    然而,如果您每次使用特定的值作为random_state(例如random_state = 1或任何其他值),结果将是相同的,即训练和测试数据集中的数值相同。请参考以下代码:

    import pandas as pd 
    from sklearn.model_selection import train_test_split
    test_series = pd.Series(range(100))
    size30split = train_test_split(test_series,random_state = 1,test_size = .3)
    size25split = train_test_split(test_series,random_state = 1,test_size = .25)
    common = [element for element in size25split[0] if element in size30split[0]]
    print(len(common))
    

    无论您运行代码多少次,输出都将为70。
    70
    

    尝试移除random_state并运行代码。
    import pandas as pd 
    from sklearn.model_selection import train_test_split
    test_series = pd.Series(range(100))
    size30split = train_test_split(test_series,test_size = .3)
    size25split = train_test_split(test_series,test_size = .25)
    common = [element for element in size25split[0] if element in size30split[0]]
    print(len(common))
    

    现在每次执行代码时,输出结果都会不同。


    3
    如果没有提供randomstate,系统将使用内部生成的randomstate。因此,当您多次运行程序时,可能会看到不同的训练/测试数据点,并且行为将是不可预测的。如果您的模型出现问题,由于不知道运行程序时生成的随机数,您将无法重新创建它。
    如果您看到Tree Classifiers - DT或RF,则尝试使用最佳计划构建一个try。虽然大多数情况下这个计划可能是相同的,但可能存在树不同的情况,因此预测结果也会不同。当您尝试调试模型时,可能无法为构建Tree的同一实例进行重新创建。因此,在构建DecisionTreeClassifier或RandomForestClassifier时,我们使用random_state来避免所有这些麻烦。
    PS:您可以深入了解DecisionTree中如何构建树,以更好地理解此问题。
    randomstate基本上用于每次运行时重复您的问题。如果在traintestsplit中不使用randomstate,则每次进行拆分时,您可能会得到不同的训练和测试数据点集,并且在出现问题时无法帮助您进行调试。
    从文档中得知:
    如果是int,则randomstate是随机数生成器使用的种子;如果是RandomState实例,则randomstate是随机数生成器;如果是None,则随机数生成器是np.random使用的RandomState实例。

    很好的解释。我只想补充一点,我们传递随机状态的原因是,如果我们尝试优化超参数,我们不希望由于基于随机数的不同初始化而导致得分波动,这可能会掩盖或隐藏实际优化的效果,因此我们无法确定得分变化的哪一部分是由于参数变化引起的,哪一部分是由于RNG的不同起始状态引起的。 - jottbe

    3

    random_state数字以随机方式拆分测试和训练数据集。除了本文所解释的内容之外,重要的是要记住random_state值可能对模型的质量产生重大影响(我指的是准确性)。例如,如果您使用某个数据集训练回归模型而没有指定random_state值,则有可能每次在测试数据上训练模型时都会得到不同的准确度结果。

    因此,找到最佳的random_state值以提供最准确的模型非常重要。然后,该数字将用于再次生成模型,例如另一个研究实验。

    为了做到这一点,可以通过为random_state参数分配随机数字来拆分和训练模型:

    for j in range(1000):
    
                X_train, X_test, y_train, y_test = train_test_split(X, y , random_state =j,     test_size=0.35)
                lr = LarsCV().fit(X_train, y_train)
    
                tr_score.append(lr.score(X_train, y_train))
                ts_score.append(lr.score(X_test, y_test))
    
            J = ts_score.index(np.max(ts_score))
    
            X_train, X_test, y_train, y_test = train_test_split(X, y , random_state =J, test_size=0.35)
            M = LarsCV().fit(X_train, y_train)
            y_pred = M.predict(X_test)`
    
    

    0
    考虑这样一种情况:我们有一个数据集,包含10个数字,范围从1到10,我们想将其分成一个训练数据集和一个测试数据集,其中测试数据集的大小为整个数据集的20%。
    训练数据集将有8个数据样本,测试数据集将有2个数据样本。我们确保随机过程每次输出相同的结果,以使代码可重复。如果我们不对数据集进行洗牌,它将每次产生不同的数据集,而且每次用不同的数据来训练模型是不好的。
    对于所有随机数据集,每个都被分配一个“random_state”值。这意味着一个“random_state”值有一个固定的数据集,因此每次我们使用“random_state”值1运行代码时,它将产生相同的拆分数据集。
    下面的图片展示了“random_state”的全部内容:

    i

    另请参阅:什么是random_state?


    -1
    sklearn.model_selection.train_test_split(*arrays, **options)[source]
    

    将数组或矩阵随机分成训练集和测试集

    Parameters: ... 
        random_state : int, RandomState instance or None, optional (default=None)
    

    如果是int类型,random_state就是随机数生成器使用的种子;如果是RandomState实例,random_state就是随机数生成器;如果是None,则随机数生成器是np.random使用的RandomState实例。 来源:http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

    关于随机状态,它在sklearn中的许多随机算法中用于确定传递给伪随机数生成器的随机种子。因此,它不控制算法行为的任何方面。因此,在验证集中表现良好的随机状态值与在新的未见过的测试集中表现良好的随机状态值不相对应。事实上,根据算法的不同,仅通过改变训练样本的顺序就可能看到完全不同的结果。 来源:https://stats.stackexchange.com/questions/263999/is-random-state-a-parameter-to-tune


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接