[python]内置库random和numpy.random(区别和联系)

4 阅读5分钟

Python 的 random 模块和 numpy.random 模块都用于生成伪随机数,但它们的设计目标、性能、功能和适用场景有显著区别:

核心区别总结:

特性random (内置)numpy.random
目标通用编程、简单随机化任务科学计算、数值模拟、大数据处理
性能单个标量生成极快的向量化生成(批量操作数组)
输出单个标量值NumPy 数组 (ndarray)
分布范围常用基础分布非常广泛的基础和高级分布
随机状态模块级全局状态更灵活(可封装在 Generator 对象中)
种子设置random.seed()推荐:rng = np.random.Generator(np.random.PCG64(seed))
向量化操作不支持核心优势 (一次生成大量数)
依赖Python 标准库需要安装 NumPy
线程安全是(但全局状态需小心)是(尤其使用Generator对象时)

详细区别解析:

  1. 设计目标与定位:

    • random 是 Python 标准库的一部分,旨在提供基本的伪随机数生成功能,满足通用编程中对随机性的需求(如游戏、简单抽样、洗牌等)。它简单易用,无需额外安装。
    • numpy.random 是 NumPy 科学计算库的子模块。它专为高性能数值计算设计,核心优势在于能够高效地生成大量随机数(数组形式),并支持更广泛的概率分布。它是数据科学、机器学习、统计模拟等领域的首选。
  2. 性能与向量化:

    • random 一次只能生成一个随机数(标量)。如果你需要生成一百万个随机数,你需要调用一百万次函数(例如 random.random())。这在循环中效率很低。
    • numpy.random 核心功能是生成整个 NumPy 数组的随机数。你可以通过指定 size 参数一次性生成任意形状的随机数数组(例如 np.random.rand(1000000))。这种向量化操作利用了 NumPy 底层优化的 C/Fortran 代码,速度比循环调用 random 快几个数量级,尤其是在处理大数据量时。
  3. 输出格式:

    • random 函数直接返回单个 Python 标量(整数、浮点数)。
    • numpy.random 函数返回 NumPy 数组 (ndarray)。这是科学计算中处理数据的标准格式,可以直接用于各种向量化运算。
  4. 随机数生成器与状态管理:

    • random 使用一个模块级别的全局随机状态random.seed() 设置整个模块的种子。任何调用 random 模块函数的代码都会影响和受这个全局状态影响。这在多线程或需要独立随机流的环境中需要小心。
    • numpy.random (现代用法):
      • 旧版(np.random.rand()等)也存在模块级全局状态问题。
      • 推荐使用新版 API: numpy.random.Generator
      • 你可以创建独立的 Generator 对象:rng = np.random.default_rng(seed=your_seed)
      • 这个 rng 对象封装了自己的随机状态。你可以创建多个独立的 Generator 实例,它们互不影响,非常适合需要可重现性和隔离性的场景(如并行计算)。所有随机数生成都通过这个对象的方法调用(如 rng.random(size=100), rng.normal(loc=0, scale=1, size=50))。
  5. 随机数质量与算法:

    • random 默认使用 Mersenne Twister (MT19937) 算法,质量较好,周期长,是广泛使用的标准算法。
    • numpy.random
      • 旧版函数也使用 MT19937。
      • Generator 默认使用 PCG64 生成器,它在统计质量、速度、空间效率、可预测性方面通常被认为是 MT19937 的改进。
      • 提供了其他可选算法(如 Philox, SFC64),可通过 np.random.Generator(np.random.OtherBitGenerator(seed)) 创建。
  6. 概率分布支持:

    • random 提供常用的基础分布:均匀分布 (random, uniform)、整数均匀分布 (randint, randrange)、正态分布 (gauss, normalvariate)、对数正态、指数分布、Gamma 分布、Beta 分布、三角分布、离散分布 (choice, choices, sample, shuffle) 等。
    • numpy.random 支持 random 中的所有基础分布,并且额外提供了更多、更专业的统计分布,例如:
      • 多元正态分布 (multivariate_normal)
      • 更丰富的离散分布(如二项、泊松、负二项、几何、超几何)
      • 卡方分布 (chisquare)
      • 非中心卡方/F/t 分布
      • 威布尔分布 (weibull)
      • 冈贝尔分布 (gumbel)
      • 瑞利分布 (rayleigh)
      • 冯·米塞斯分布 (圆形正态) (vonmises)
      • 帕累托分布 (pareto)
      • 幂分布 (power)
      • 拉普拉斯分布 (laplace)
      • 逻辑分布 (logistic)
      • 更灵活的排列操作 (permutation, shuffle 也支持轴参数)
  7. 种子设置:

    • random random.seed(a=None, version=2)
    • numpy.random (旧版): np.random.seed(seed=None) (不推荐,影响全局状态)
    • numpy.random.Generator (推荐): rng = np.random.default_rng(seed=your_seed)rng = np.random.Generator(np.random.PCG64(seed))your_seed 可以是 None (系统随机源)、整数、数组或 SeedSequence 对象。

何时使用哪个?

  • 使用 Python 内置 random 当:

    • 你的任务非常简单(例如,游戏里掷骰子、随机选一个列表元素、洗牌)。
    • 你只需要生成少量随机数。
    • 你不想引入任何外部依赖(NumPy)。
    • 脚本很小,性能不是关键。
    • 不需要复杂的统计分布。
  • 使用 numpy.random (特别是 Generator) 当:

    • 你需要生成大量随机数(成千上万或更多)。
    • 性能至关重要(科学计算、模拟)。
    • 你需要随机数以 NumPy 数组的形式输出,以便直接进行向量化计算。
    • 你需要 更广泛的概率分布
    • 你需要 独立、可重现的随机流(使用独立的 Generator 对象),尤其是在并行计算或多组件系统中。
    • 你已经在使用 NumPy 进行数值计算。

结论:

random 是轻量级的通用工具,适合简单场景。numpy.random(尤其是 Generator API)是为高性能科学计算量身定制的,其核心优势在于快速生成随机数数组更丰富的分布以及更健壮灵活的随机状态管理。如果你的工作涉及数据科学、数值模拟或任何需要高效处理大量随机数的任务,numpy.random.Generator 是绝对的首选。对于琐碎的脚本或避免依赖 NumPy 的情况,内置 random 就足够了。