📊 第6章 图解数组计算模块 NumPy
📄 一句话概括

np.random.default_rng 是新版推荐写法,老的 np.random.rand 还能用但不推荐。 种子固定,结果就固定。报数必须交代种子,否则别人复现不了。 normal 的两个参数是均值和标准差,不是均值和方差。

📝 本章和前面几章的关系

造测试数据、随机分组、随机抽样都靠随机数。这一篇把「可复现」这件事讲透。 不做随机模拟也值得看:种子是数据分析的诚信底线。

一、新版写法:default_rng

rng = np.random.default_rng() 造一个随机数生成器。 然后 rng.integers(0, 10, 5) 取五个 0 到 9 的整数。 老的 np.random.rand 还能用,但官方建议统一换到 default_rng。

两者最大的区别是:生成器是一个对象,可以独立持有状态,不会互相干扰。

二、种子:可复现

np.random.default_rng(42).integers(0, 100, 5) 连跑两次,结果一模一样。 种子 42 定了,整条随机序列就定了。 报数必须交代种子。不给种子,别人复现不了你的结果,那个数就是孤证。

这不是洁癖。做随机模拟时,改一个参数结果就变,没有种子根本分不清是参数起作用还是随机波动。

三、三种常用分布

要什么 怎么写 范围
整数 integers(低, 高, 个数) 右端不含
0 到 1 小数 random(个数) 左闭右开
正态分布 normal(均值, 标准差, 个数) 无上下界

integers 的右端不包含,和 arange 一样——写 integers(0, 10) 给的是 0 到 9。 normal 的两个参数是均值和标准差,不是均值和方差。这一点常记错。 标准差 1 意味着约 68% 的数落在 -1 到 1 之间。

四、打乱与抽样

rng.permutation(A) 洗牌,返回新数组,不改原数组。 rng.choice(10, 3, replace=False) 从 10 个里抽 3 个不重复的。 replace=False 是不放回。忘了写默认有放回,可能抽到重复的。

随机分组就是先用 permutation 洗牌,再按顺序切两半。

五、随机数的四个用处

用途 怎么写
造测试数据 integers 或 normal
随机分组(A/B 测试) permutation 洗牌再切
随机抽样 choice(replace=False)
初始化权重 normal 小标准差

造测试数据时一定要给种子,不然每次跑出来都不一样,debug 就没法比。 没有种子的随机测试,等于每次都换一份数据在测。

六、动手 Demo:随机数组与随机种子

先看同一个生成器连取两次不一样,再看固定种子两次完全一样。 最后演示三种分布、洗牌和抽样。

import numpy as np

R = np.random.default_rng(20261102)
print("第一次 %s" % R.integers(0, 10, 5))
print("第二次 %s" % R.integers(0, 10, 5))

print("种子 42:%s" % np.random.default_rng(42).integers(0, 100, 5))
print("再来一次:%s" % np.random.default_rng(42).integers(0, 100, 5))

R = np.random.default_rng(7)
print("整数 %s" % R.integers(0, 100, 5))
print("小数 %s" % np.round(R.random(5), 3))
print("正态 %s" % np.round(R.normal(0, 1, 5), 3))

R = np.random.default_rng(3)
A = np.arange(10)
print("原数组 %s" % A)
print("洗牌后 %s" % R.permutation(A))
print("抽样   %s" % R.choice(10, 3, replace=False))

实跑输出:

--------------------------------------------------------------------
随机数组与随机种子
--------------------------------------------------------------------

  ① 新版写法:default_rng
  --------------------------------------------------------------------
  第一次:[7 6 2 4 7]
  第二次:[8 0 8 0 3]
  同一个生成器连着取,每次都不一样——这是随机的本意。
  ! np.random.default_rng 是新版推荐写法。老的 np.random.rand 还能用,但官方建议换。

  ② 种子:可复现
  --------------------------------------------------------------------
  种子 42 造两次:[ 8 77 65 43 43]
  再来一次:      [ 8 77 65 43 43]
  两次完全一样。种子固定,结果就固定。
  ! 报数必须交代种子。不给种子,别人复现不了你的结果,那个数就是孤证。

  ③ 三种常用分布
  --------------------------------------------------------------------
  整数:integers(0, 100, 5) → [94 62 68 89 57]
  小数:random(5) → [0.225 0.3   0.874 0.005 0.821]
  正态:normal(均值 0, 标准差 1, 5 个) → [-0.492 -0.62   0.49   0.357  0.105]
  integers 的右端不包含,和 arange 一样;random 给 0 到 1 之间的小数。
  ! normal 的两个参数是均值和标准差,不是均值和方差。这一点常记错。

  ④ 打乱与抽样
  --------------------------------------------------------------------
  原数组:[0 1 2 3 4 5 6 7 8 9]
  洗牌后:[9 6 0 2 1 4 7 5 3 8]
  原数组还是:[0 1 2 3 4 5 6 7 8 9]——permutation 返回新数组,不改原数组。
  从 10 个里抽 3 个不重复:[5 4 3]
  ! 抽样的 replace=False 是不放回。忘了写默认是有放回,可能抽到重复的。

  ⑤ 随机数能干什么
  --------------------------------------------------------------------

| 用途 | 怎么写 |
|---|---|
| 造测试数据 | integers 或 normal |
| 随机分组 | permutation 洗牌再切 |
| 随机抽样 | choice(replace=False) |
| 初始化权重 | normal 小标准差 |

  造测试数据时一定要给种子,不然每次跑出来都不一样,debug 就没法比。

default_rng(42) 每次都新建一个生成器,所以两次结果一样;R 是同一个生成器,所以两次不一样。 「同一个生成器连取」和「新建两个同种子生成器」结果完全不同。这是最容易混的一点。

30 秒实验

  1. 把种子 42 改成 43,看五个数变成什么。
  2. 把 choice 的 replace=False 去掉,连跑几次看有没有重复。
  3. 想一想:为什么 A/B 测试要随机分组?不随机会怎样?

常见误区

  1. 不设种子:每次跑结果不同,出了问题无法复现。
  2. 以为 normal 第二个参数是方差:它是标准差,方差要开根号。
  3. 抽样忘了 replace=False:抽到重复的,样本量不够。
  4. 以为 permutation 改原数组:它返回新数组,原数组不动。
自测三问(点开对答案) 1. 为什么报数必须交代种子? —— 没有种子,同一个随机过程每次结果不同,别人无法复现,结论也就无法验证。 2. normal(0, 1) 的两个参数是什么? —— 均值 0、标准差 1。不是均值 0、方差 1。 3. 随机分组怎么做? —— 先用 permutation 把行号洗牌,再按顺序切段,比如前一半是 A 组。

造数组的方式都讲完了。下一篇讲一个隐蔽的坑:asarray 和 array 差在「复不复制」。

相关笔记