3.3 arange、linspace与随机数填充


文档摘要

3.3 arange、linspace与随机数填充 本节摘要:arange 由步长定个数、linspace 由个数定步长,浮点场景必须用后者避免累计误差。随机数用 defaultrng 创建的 Generator,seed 固定即可复现。本节还对比三种序列生成的端点行为与 dtype 默认,并演示正态、整数等常用分布的填充。 承接与定位 前两节解决了"造什么类型",这一节解决"数值从哪来"的后两类:规律序列与随机数。它们是坐标轴、采样点、模拟实验的原材料,第 7、8 章的线代与性能实验都将大量使用本节的接口。 arange 与 linspace 的分工 两个函数都在造等差序列,控制量不同: 浮点步长为什么禁用 arange?看事故: 整数序列用 arange,浮点序列一律 linspace。

3.3 arange、linspace与随机数填充

本节摘要:arange 由步长定个数、linspace 由个数定步长,浮点场景必须用后者避免累计误差。随机数用 default_rng 创建的 Generator,seed 固定即可复现。本节还对比三种序列生成的端点行为与 dtype 默认,并演示正态、整数等常用分布的填充。

承接与定位

前两节解决了"造什么类型",这一节解决"数值从哪来"的后两类:规律序列与随机数。它们是坐标轴、采样点、模拟实验的原材料,第 7、8 章的线代与性能实验都将大量使用本节的接口。

arange 与 linspace 的分工

两个函数都在造等差序列,控制量不同:

import numpy as np # arange(起, 止, 步长):止不含;个数由步长间接决定 a = np.arange(0, 10, 2) print(a, a.dtype) # [0 2 4 6 8] int64 # linspace(起, 止, 个数):止默认包含;步长由个数推出 b = np.linspace(0, 1, 5) print(b) # [0. 0.25 0.5 0.75 1. ],float64 # 不想要端点时用 endpoint=False c = np.linspace(0, 1, 5, endpoint=False) print(c) # [0. 0.2 0.4 0.6 0.8] # 想知道实际步长时拿 retstep=True d, step = np.linspace(0, 1, 5, retstep=True) print(step) # 0.25

浮点步长为什么禁用 arange?看事故:

import numpy as np bad = np.arange(0, 1, 0.1) print(len(bad)) # 10?还是 11? # 实际输出 10,但把终点改成 1.0000001 或换平台就可能变 11 # 因为 0.1 的二进制表示略大于 0.1,累计 10 步后仍小于 1 print(bad[-1]) # 0.9(约),但序列里没有任何精确的边界保证 good = np.linspace(0, 1, 11) print(len(good), good[-1]) # 11 1.0,端点精确保证

整数序列用 arange,浮点序列一律 linspace。这条规矩能消掉一整类"差一个采样点"的 bug。

序列生成方式对比

序列生成方式对比

随机数:新式 Generator 用法

老教程里的 np.random.rand、np.random.seed 是全局函数族,状态全局共享,多线程与可复现性都不理想。现代写法是先造 Generator 实例:

import numpy as np rng = np.random.default_rng(seed=42) # 固定种子 u = rng.random((2, 3)) # 0到1均匀分布 print(u.round(3)) # [[0.774 0.44 0.858] # [0.697 0.094 0.198]] n = rng.normal(loc=0.0, scale=1.0, size=5) # 标准正态 print(n.round(3)) # [-0.855 -1.104 0.322 -0.602 -0.109] idx = rng.integers(0, 10, size=4) # 0到9随机整数 print(idx) # [0 7 2 4] # 可复现性:同种子同序列 rng2 = np.random.default_rng(seed=42) print(np.array_equal(rng2.random((2, 3)), u)) # True

常用分布速记:uniform(low, high, size) 区间均匀;normal(mean, std, size) 正态;choice(数组, size, replace=False) 无放回抽样(洗牌、划分数据集);permutation(n) 生成随机排列。种子策略上,实验代码固定 seed 保证可复现,生产代码用默认熵源即可,两者别混。

案例:模拟一百万次掷骰子

完整过程演练。背景:验证"大量独立随机事件频率趋近期望"(大数定律),同时练习随机整数与聚合。

操作:

import numpy as np rng = np.random.default_rng(seed=7) rolls = rng.integers(1, 7, size=1_000_000) # 1到6,含1含6?看输出 # 注意:integers 的区间是 [low, high),掷骰子要写 7 或用 endpoint rolls = rng.integers(1, 7, size=1_000_000, endpoint=True) counts = np.bincount(rolls)[1:] # 统计1到6各出现次数 print(counts) # 输出示例:[166725 166417 166922 166372 166610 166954] freq = counts / counts.sum() print(freq.round(4)) # [0.1667 0.1664 0.1669 0.1664 0.1666 0.167 ]

结果:各面频率都在 0.1666 附近,离期望 0.1667 最多偏差万分之几。解读:一百万元素的一次生成与统计在毫秒级完成,这正是 3.1 节占位数组与这里随机填充的组合价值——先用 zeros 思路想"容器要多大",再用 Generator 一次性灌满,绝不写 Python 循环。变式:把 size 换成 (1000, 1000) 得到二维模拟,每行是一轮实验,用 axis=1 聚合可同时观察"轮与轮"的波动(聚合细节在第 7 章)。

⚠️ 常见坑:rng.integers(1, 7) 取不到 7,与 Python 的 range 一致是"含头不含尾";但 dice、月份这类"两端都要"的场景记得 endpoint=True,否则边界值永远缺席。

本节要点回顾

  • 分工口诀:整数序列 arange,浮点采样 linspace;linspace 端点默认包含且精确
  • 浮点步长禁用 arange:二进制误差使元素个数在平台间漂移
  • 新式随机:default_rng 建 Generator,random、normal、integers、choice、permutation 各司其职
  • 复现纪律:实验固定 seed;生产用默认熵源,不要全局 seed
  • 组合思路:占位思维定形状,随机接口灌数据,聚合接口验结果

第 4 章开始取用这些数组:索引与切片的每种写法,都对应一条明确的内存行为——视图还是拷贝,一试便知。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U