随机性#

在生成、绘制、计算属性或操纵网络时,常常会使用随机数生成器(RNGs)。NetworkX 提供了使用两种标准 RNG 的函数:NumPy 的包 numpy.random 或 Python 内置的包 random。它们都使用相同的算法来生成数字(Mersenne Twister)。它们的接口非常相似(危险地相似),但又有所不同。它们各自提供了一个全局默认实例,其生成器在单次会话中的所有程序中共享。大多数情况下,你可以按照 NetworkX 设置的方式使用 RNG,并获得合理的伪随机结果(统计上随机,但以确定性方式创建的结果)。

有时你希望对数字的生成方式有更多的控制。特别是,你需要设置生成器的 seed 以使你的结果可重复——无论是为了科学出版还是调试。两个 RNG 包都有简单的函数来将种子设置为任意整数,从而确定后续生成的值。由于这个包(以及许多其他包)使用了这两种 RNG,你可能需要同时设置两种 RNG 的 seed。即使我们严格只使用一个 RNG,你也可能会使用另一个使用另一 RNG 的包。设置两个全局 RNG 的状态就像将每个 RNG 的种子设置为任意整数一样简单:

>>> import random
>>> random.seed(246)        # 或任意整数
>>> import numpy
>>> numpy.random.seed(4812)

许多用户会对这种控制水平感到满意。

对于希望获得更多控制的人,我们在使用 RNG 的函数中包含了一个可选参数。这个参数叫做 seed,但不仅决定 RNG 的种子。它还告诉函数使用哪个 RNG 包,以及是使用全局还是本地 RNG。

>>> from networkx import path_graph, random_layout
>>> G = path_graph(9)
>>> pos = random_layout(G, seed=None)  # 使用(任意)全局默认 RNG
>>> pos = random_layout(G, seed=42)  # 仅用于此调用的本地 RNG
>>> pos = random_layout(G, seed=numpy.random)  # 使用 numpy 全局 RNG
>>> random_state = numpy.random.RandomState(42)
>>> pos = random_layout(G, seed=random_state)  # 使用/重用你自己的 RNG

每个使用 RNG 的 NetworkX 函数都是以一个 RNG 包为默认编写的。它默认使用 randomnumpy.random。但有些用户希望在所有代码中仅使用一个 RNG。这个 seed 参数提供了一种机制,使任何函数都能使用 numpy.random RNG,即使该函数是为了 random 编写的。它的工作原理如下。

默认行为(当 seed=None 时)是使用函数首选包的全局 RNG。如果 seed 设置为一个整数值,将创建一个具有指定种子值的本地 RNG,并在此函数的整个持续时间内使用(包括对其他函数的任何调用),然后丢弃。或者,你可以指定 seed=numpy.random 以确保全局 numpy RNG 是否被使用,函数是否预期如此。最后,你可以提供一个 numpy RNG 供函数使用。然后,该 RNG 可用于其他函数,甚至其他包,如 sklearn。这样,你可以在项目中的所有随机数中使用一个 RNG。

虽然可以为为 random 包 API 编写的 NetworkX 函数指定 seedrandom 风格的 RNG,但 numpy RNG 接口有太多很好的功能,我们无法确保所有函数都能使用 random 风格的 RNG。在实践中,你只使用 random RNG(如果没有 numpy)也可以完成大多数事情。但如果有 numpy,你的体验将更加丰富。

总而言之,你可以轻松忽略 seed 参数并使用全局 RNG。你可以通过 seed=numpy.random 指定只使用 numpy 全局 RNG。你可以通过提供一个整数种子值来使用本地 RNG。你还可以提供你自己的 numpy RNG,重用它在所有函数中。如果你希望在计算中使用单个 RNG,使用 numpy RNG 更加容易。