NumPy 中文教程

第一部分:基础认知与环境准备
第 1 章 全面认识 NumPy
第 2 章 开发环境搭建与验证
第二部分:核心对象 ——ndarray 数组
第 3 章 ndarray 数组基础
第 4 章 数组的形状与维度操作
第四部分:高级应用与数据处理
第 8 章 数组的排序、查找与去重
第 9 章 缺失值与异常值处理
第 10 章 随机数生成与抽样
第 11 章 文件读写与数据交互
第五部分:实战场景与落地应用
第 12 章 数值计算实战
第 13 章 数据分析实战
第六部分:优化进阶与问题解决
第 14 章 NumPy 性能优化
第 15 章 NumPy 进阶扩展
第 16 章 常见问题与解决方案

10.1 随机数生成器

NumPy随机数生成器全面教程:种子设置、可复现性与新旧API兼容指南

NumPy 中文教程

本教程详细介绍NumPy随机数生成器,涵盖随机种子设置、可复现性重要性、新版Generator API使用及旧版np.random接口兼容性,适合新手学习NumPy随机数操作。

推荐工具
PyCharm专业版开发必备

功能强大的Python IDE,提供智能代码补全、代码分析、调试和测试工具,提高Python开发效率。特别适合处理列表等数据结构的开发工作。

了解更多

NumPy随机数生成器教程:从基础到高级

引言

随机数生成在科学计算、数据分析和机器学习中至关重要。NumPy提供了强大的工具来生成随机数,确保实验的可复现性和灵活性。本教程将带你深入理解NumPy的随机数生成器,包括如何设置种子、使用新版Generator API,以及处理新旧版本的兼容性。

1. 随机数生成器基础

NumPy使用伪随机数生成器(PRNG)生成随机数,这些数字看似随机,但实际上是由算法生成的确定性序列。这意味着,通过设置相同的初始状态(种子),可以复现相同的随机序列。

关键概念:

  • 伪随机数:基于种子生成,具有可预测性。
  • 随机数分布:NumPy支持多种分布,如均匀分布、正态分布等。

代码示例:

import numpy as np

# 生成一个随机数(旧版接口)
random_number = np.random.rand()  # 返回0到1之间的均匀分布随机数
print(f"随机数: {random_number}")

2. 随机数种子与可复现性

什么是随机种子?

随机种子(seed)是一个整数,用于初始化随机数生成器的状态。设置相同的种子后,每次运行代码生成的随机数序列将完全相同,这对于调试和实验至关重要。

使用 np.random.seed() 设置种子:

# 设置种子为42
np.random.seed(42)
random_num1 = np.random.rand()
print(f"第一次生成的随机数: {random_num1}")

# 再次设置相同种子,生成相同的随机数
np.random.seed(42)
random_num2 = np.random.rand()
print(f"第二次生成的随机数: {random_num2}")
assert random_num1 == random_num2, "随机数应该相同"  # 不会报错,因为种子相同

可复现性的重要性

  • 科学实验: 确保结果可以复现,验证算法或模型的稳定性。
  • 机器学习: 训练模型时使用固定种子,方便调参和对比。
  • 调试: 帮助定位由随机性引起的错误。

最佳实践: 在代码开头设置种子,尤其是在团队协作或发布代码时。

3. 新版随机数生成器:Generator

从NumPy 1.17版本开始,引入了新的随机数生成器API,称为 Generator。它使用更现代的算法(如PCG64),提供更好的性能和统计特性。旧版的 np.random 函数是基于全局状态,而 Generator 是实例化对象,更灵活和安全。

创建Generator实例

使用 np.random.default_rng() 创建默认的Generator。

# 创建Generator实例
rng = np.random.default_rng(seed=42)  # 可以在创建时指定种子

# 使用Generator生成随机数
random_uniform = rng.random()  # 生成0到1之间的均匀分布随机数
random_normal = rng.standard_normal()  # 生成标准正态分布随机数
print(f"均匀分布随机数: {random_uniform}")
print(f"正态分布随机数: {random_normal}")

Generator的优势

  • 局部状态: 每个Generator实例独立,避免全局状态污染。
  • 更多方法: 提供丰富的随机数生成方法,如 integerschoice 等。
  • 性能改进: 使用更高效的算法。

代码示例:

# 使用Generator生成整数数组
random_ints = rng.integers(0, 10, size=5)  # 生成5个0到9之间的随机整数
print(f"随机整数数组: {random_ints}")

# 生成随机选择
random_choice = rng.choice(['a', 'b', 'c'], size=3)
print(f"随机选择: {random_choice}")

4. 旧版接口(np.random)与新版兼容

旧版接口概述

在NumPy 1.16及更早版本中,随机数生成主要通过 np.random 模块的全局函数实现,如 np.random.rand()np.random.randn() 等。这些函数基于全局状态,可能导致不可预期的行为。

示例:

# 旧版接口的用法
np.random.seed(123)
old_random = np.random.rand(3, 3)  # 生成3x3的随机数组
print(f"旧版接口生成的数组:\n{old_random}")

新旧版本兼容性

从NumPy 1.17开始,np.random 模块仍然保留,但推荐使用新的 Generator API。np.random 中的许多函数现在通过 Generator 实例调用,以提高一致性和可维护性。

如何迁移:

  • 新代码应优先使用 np.random.default_rng() 创建Generator。
  • 旧代码可以继续使用 np.random,但建议逐步迁移,特别是在需要可复现性和性能的场景。

兼容性示例:

# 旧版代码
np.random.seed(42)
old_array = np.random.randn(5)

# 迁移到新版代码
rng = np.random.default_rng(seed=42)
new_array = rng.standard_normal(5)

# 验证结果相同(假设种子相同,算法不同可能导致微小差异)
print(f"旧版数组: {old_array}")
print(f"新版数组: {new_array}")
# 注意:由于算法升级,数值可能不完全相同,但概念上可复现性一致。

注意事项

  • 种子设置: 在Generator中,种子通过 rng = np.random.default_rng(seed=value) 设置,而不是 np.random.seed()
  • 函数对应: 旧版函数如 np.random.rand() 对应 rng.random(),但参数可能略有不同。
  • 向后兼容: NumPy维护 np.random 以支持旧代码,但未来版本可能弃用某些函数。

5. 总结与最佳实践

  • 使用新版Generator: 对于新项目,推荐使用 np.random.default_rng() 创建Generator实例,以获得更好的性能和灵活性。
  • 设置种子: 始终在代码开头设置随机种子,以确保可复现性,无论使用旧版还是新版接口。
  • 逐步迁移: 如果维护旧代码,计划迁移到新版API,以减少依赖过时函数。
  • 文档参考: 查阅NumPy官方文档(如 numpy.random 模块)获取最新信息。

最终建议代码:

import numpy as np

# 最佳实践:使用新版Generator并设置种子
seed_value = 42  # 选择一个固定种子
rng = np.random.default_rng(seed=seed_value)

# 生成随机数据
random_data = rng.random((2, 3))  # 生成2x3的均匀分布数组
random_ints = rng.integers(1, 100, size=5)  # 生成5个1到99的随机整数

print(f"随机数组:\n{random_data}")
print(f"随机整数: {random_ints}")

# 这样确保代码在不同运行中生成相同的随机序列,便于调试和复现。

通过本教程,你应该对NumPy的随机数生成器有了全面理解,并能自信地在项目中应用种子设置和新旧API。祝你学习愉快!

开发工具推荐
Python开发者工具包

包含虚拟环境管理、代码格式化、依赖管理、测试框架等Python开发全流程工具,提高开发效率。特别适合处理复杂数据结构和算法。

获取工具包