随机性是机器学习算法的配置和评估的重要组成部分。
从人工神经网络中权重的随机初始化,到将数据随机分割成训练集和测试集,再到随机梯度下降中训练数据集的随机洗牌,生成随机数和利用随机性都是一项必备技能。
在本教程中,您将学习如何在 Python 中生成和使用随机数。
完成本教程后,您将了解:
- 随机性可以通过伪随机数生成器在程序中得到应用。
- 如何通过 Python 标准库生成随机数并使用随机性。
- 如何通过 NumPy 库生成随机数数组。
通过我新书《机器学习统计学》快速启动您的项目,书中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。

如何在 Python 中生成随机数
照片由 Thomas Lipike 拍摄。保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 伪随机数生成器
- 使用 Python 标准库生成随机数
- 使用 NumPy 生成随机数
1. 伪随机数生成器
我们注入到程序和算法中的随机性来源,是一种称为伪随机数生成器的数学技巧。
随机数生成器是一种从真实随机源生成随机数的系统。通常是物理的,例如盖革计数器或静电噪声,其结果被转换为随机数。机器学习不需要真正的随机性。相反,我们可以使用伪随机性。伪随机性是一系列看起来接近随机但通过确定性过程生成的数字。
数据洗牌和用随机值初始化系数会使用伪随机数生成器。这些小程序通常是一个您可以调用的函数,它会返回一个随机数。再次调用,它们会返回一个新的随机数。通常也有包装函数,允许您将随机性作为整数、浮点数,在特定分布下,在特定范围内等获得。
数字是按序列生成的。序列是确定性的,并用一个初始数字进行种子。如果您不显式调用伪随机数生成器的种子,它可能会使用当前系统时间(秒或毫秒)作为种子。
种子的值无关紧要。选择您喜欢的任何值。重要的是,相同的种子播种过程将产生相同的随机数序列。
让我们用一些例子来具体说明这一点。
2. 使用 Python 标准库生成随机数
Python 标准库提供了一个名为 random 的模块,它提供了一系列用于生成随机数的函数。
Python 使用一种流行且强大的伪随机数生成器,称为 梅森旋转算法。
在本节中,我们将通过标准 Python API 探讨生成和使用随机数和随机性的几种用例。
需要机器学习统计学方面的帮助吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
设置随机数生成器的种子
伪随机数生成器是一个生成近乎随机数字序列的数学函数。
它需要一个参数来启动序列,称为种子。该函数是确定性的,意味着给定相同的种子,它每次都会生成相同的数字序列。种子的选择并不重要。
seed() 函数将设置伪随机数生成器的种子,接受一个整数参数,例如 1 或 7。如果在生成随机数之前未调用 seed() 函数,则默认使用自纪元(1970年)以来的当前系统时间(毫秒)。
下面的示例演示了如何设置伪随机数生成器的种子,生成一些随机数,并显示重新设置种子将导致生成相同的数字序列。
1 2 3 4 5 6 7 8 9 10 11 |
# 播种伪随机数生成器 from random import seed from random import random # 设定随机数生成器种子 seed(1) # 生成一些随机数 print(random(), random(), random()) # 重置种子 seed(1) # 生成一些随机数 print(random(), random(), random()) |
运行此示例会使用种子值 1 设置伪随机数生成器,生成 3 个随机数,重新设置种子,并显示生成了相同的三个随机数。
1 2 |
0.13436424411240122 0.8474337369372327 0.763774618976614 0.13436424411240122 0.8474337369372327 0.763774618976614 |
通过设置种子来控制随机性可能很有用,以确保您的代码每次都产生相同的结果,例如在生产模型中。
对于用于控制混杂变量的随机化实验,每次实验运行时可以使用不同的种子。
随机浮点值
可以使用 random() 函数生成随机浮点值。值将在 0 到 1 之间生成,具体来说是在区间 [0,1) 内。
值是从均匀分布中抽取的,这意味着每个值被抽取的几率均等。
下面的示例生成 10 个随机浮点值。
1 2 3 4 5 6 7 8 9 |
# 生成随机浮点值 from random import seed from random import random # 设定随机数生成器种子 seed(1) # 生成 0-1 之间的随机数 for _ in range(10): value = random() print(value) |
运行此示例会生成并打印每个随机浮点值。
1 2 3 4 5 6 7 8 9 10 |
0.13436424411240122 0.8474337369372327 0.763774618976614 0.2550690257394217 0.49543508709194095 0.4494910647887381 0.651592972722763 0.7887233511355132 0.0938595867742349 0.02834747652200631 |
可以通过将浮点值乘以新范围的大小并加上最小值来将其缩放到所需的范围,如下所示:
1 |
缩放值 = min + (value * (max - min)) |
其中 _min_ 和 _max_ 分别是所需范围的最小值和最大值,而 _value_ 是在 0 和 1 之间生成的随机浮点值。
随机整数值
可以使用 randint() 函数生成随机整数值。
此函数接受两个参数:生成整数值的范围的开始和结束。随机整数将在包含范围开始和结束值的区间 [start, end] 内生成。随机值是从均匀分布中抽取的。
下面的示例生成 10 个介于 0 和 10 之间的随机整数值。
1 2 3 4 5 6 7 8 9 |
# 生成随机整数值 from random import seed from random import randint # 设定随机数生成器种子 seed(1) # 生成一些整数 for _ in range(10): value = randint(0, 10) print(value) |
运行此示例会生成并打印 10 个随机整数值。
1 2 3 4 5 6 7 8 9 10 |
2 9 1 4 1 7 7 7 10 6 |
随机高斯值
可以使用 gauss() 函数从高斯分布中抽取随机浮点值。
此函数接受两个参数,对应于控制分布大小的参数,特别是均值和标准差。
下面的示例生成 10 个从均值为 0.0、标准差为 1.0 的高斯分布中抽取的随机值。
请注意,这些参数不是值的边界,并且值的分布将由分布的钟形曲线控制,在这种情况下,它们在 0.0 以上和以下的几率大致相等。
1 2 3 4 5 6 7 8 9 |
# 生成随机高斯值 from random import seed from random import gauss # 设定随机数生成器种子 seed(1) # 生成一些高斯值 for _ in range(10): value = gauss(0, 1) print(value) |
运行此示例会生成并打印 10 个高斯随机值。
1 2 3 4 5 6 7 8 9 10 |
1.2881847531554629 1.449445608699771 0.06633580893826191 -0.7645436509716318 -1.0921732151041414 0.03133451683171687 -1.022103170010873 -1.4368294451025299 0.19931197648375384 0.13337460465860485 |
注意: 在 random 模块中,有一个名为 normalvariate()
的函数,其功能与 gauss()
相同。前者是线程安全的,而 gauss()
则不是。但是,您很少在多线程环境中运行 Python,而 gauss()
的速度更快。
从列表中随机选择
随机数可用于从列表中随机选择一个项。
例如,如果一个列表有 10 个项,索引在 0 到 9 之间,那么您可以生成一个介于 0 和 9 之间的随机整数,并用它来随机选择列表中的一个项。choice() 函数为您实现了此行为。选择是根据均匀几率进行的。
下面的示例生成一个包含 20 个整数的列表,并给出从列表中随机选择一个项的五个示例。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 从列表中选择一个随机元素 from random import seed from random import choice # 设定随机数生成器种子 seed(1) # 准备一个序列 sequence = [i for i in range(20)] 打印(序列) # 从序列中进行选择 for _ in range(5): selection = choice(sequence) print(selection) |
运行此示例会首先打印整数值列表,然后打印五个随机选择并打印列表中的随机值的示例。
1 2 3 4 5 6 |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 4 18 2 8 3 |
从列表中随机抽取样本
我们可能对重复从列表中随机选择项以创建随机选择的子集感兴趣。
重要的是,一旦从列表中选择了一个项并将其添加到子集中,就不应再次添加。这称为不放回抽样,因为一旦从列表中选择了一个项用于子集,就不会将其添加回原始列表(即,不再可供重新选择)。
sample() 函数提供了此行为,该函数从列表中无放回地选择随机样本。该函数接受列表和要选择的子集大小作为参数。请注意,实际上并不会从原始列表中删除项,只是将它们复制到新列表中。
下面的示例演示了从 20 个整数列表中选择一个包含 5 个项的子集。
1 2 3 4 5 6 7 8 9 10 11 |
# 无放回地选择一个随机样本 from random import seed from random import sample # 设定随机数生成器种子 seed(1) # 准备一个序列 sequence = [i for i in range(20)] 打印(序列) # 选择一个无放回的子集 subset = sample(sequence, 5) print(subset) |
运行此示例会首先打印整数值列表,然后打印选择的随机样本以供比较。
1 2 |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] [4, 18, 2, 8, 3] |
随机打乱列表
随机性可用于打乱项目列表,就像洗一副牌一样。
shuffle() 函数可用于打乱列表。打乱是就地进行的,这意味着提供给 shuffle() 函数的列表会被打乱,而不是制作并返回列表的打乱副本。
下面的示例演示了如何随机打乱整数值列表。
1 2 3 4 5 6 7 8 9 10 11 |
# 随机打乱序列 from random import seed from random import shuffle # 设定随机数生成器种子 seed(1) # 准备一个序列 sequence = [i for i in range(20)] 打印(序列) # 随机打乱序列 shuffle(sequence) 打印(序列) |
运行此示例会首先打印整数列表,然后打印打乱后的相同列表。
1 2 |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] [11, 5, 17, 19, 9, 0, 16, 1, 15, 6, 10, 13, 14, 12, 7, 3, 8, 2, 18, 4] |
3. 使用 NumPy 生成随机数
在机器学习中,您很可能正在使用 scikit-learn 和 Keras 等库。
这些库在底层使用了 NumPy,这是一个使处理数字向量和矩阵非常高效的库。
NumPy 也有自己的伪随机数生成器实现和方便的包装函数。
NumPy 还实现了梅森旋转伪随机数生成器。
让我们来看几个生成随机数和使用随机性处理 NumPy 数组的示例。
设置随机数生成器的种子
NumPy 的伪随机数生成器与 Python 标准库的伪随机数生成器不同。
重要的是,设置 Python 伪随机数生成器的种子不会影响 NumPy 伪随机数生成器。它必须单独设置种子并单独使用。
seed() 函数可用于设置 NumPy 伪随机数生成器的种子,接受一个整数作为种子值。
下面的示例演示了如何设置生成器的种子以及重新设置种子将导致生成相同的随机数序列。
1 2 3 4 5 6 7 8 9 10 11 |
# 播种伪随机数生成器 from numpy.random import seed from numpy.random import rand # 设定随机数生成器种子 seed(1) # 生成一些随机数 print(rand(3)) # 重置种子 seed(1) # 生成一些随机数 print(rand(3)) |
运行此示例会设置伪随机数生成器的种子,打印随机数序列,然后重新设置生成器,显示生成了完全相同的随机数序列。
1 2 |
[4.17022005e-01 7.20324493e-01 1.14374817e-04] [4.17022005e-01 7.20324493e-01 1.14374817e-04] |
随机浮点值数组
可以使用 NumPy 的 rand() 函数生成随机浮点值数组。
如果不提供参数,则会创建一个单个随机值,否则可以指定数组的大小。
下面的示例创建了一个包含 10 个从均匀分布中抽取的随机浮点值的数组。
1 2 3 4 5 6 7 8 |
# 生成随机浮点值 from numpy.random import seed from numpy.random import rand # 设定随机数生成器种子 seed(1) # 生成 0-1 之间的随机数 values = rand(10) 打印(values) |
运行此示例会生成并打印随机浮点值 NumPy 数组。
1 2 3 |
[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01 1.46755891e-01 9.23385948e-02 1.86260211e-01 3.45560727e-01 3.96767474e-01 5.38816734e-01] |
随机整数值数组
可以使用 NumPy 的 randint() 函数生成随机整数数组。
此函数接受三个参数:范围的下限、范围的上限,以及要生成的整数值的数量或数组的大小。随机整数将从均匀分布中抽取,包括下限值但不包括上限值,例如在区间 [lower, upper) 内。
下面的示例演示了如何生成随机整数数组。
1 2 3 4 5 6 7 8 |
# 生成随机整数值 from numpy.random import seed from numpy.random import randint # 设定随机数生成器种子 seed(1) # 生成一些整数 values = randint(0, 10, 20) 打印(values) |
运行此示例会生成并打印一个包含 20 个介于 0 和 10 之间的随机整数值的数组。
1 |
[5 8 9 5 0 0 1 7 6 9 2 4 5 2 4 2 4 7 7 9] |
随机高斯值数组
可以使用 NumPy 的 randn() 函数生成随机高斯值数组。
此函数接受一个参数来指定结果数组的大小。高斯值是从标准高斯分布中抽取的;这是一个均值为 0.0、标准差为 1.0 的分布。
下面的示例显示了如何生成随机高斯值数组。
1 2 3 4 5 6 7 8 |
# 生成随机高斯值 from numpy.random import seed from numpy.random import randn # 设定随机数生成器种子 seed(1) # 生成一些高斯值 values = randn(10) 打印(values) |
运行此示例会生成并打印一个包含 10 个标准高斯分布随机值的数组。
1 2 |
[ 1.62434536 -0.61175641 -0.52817175 -1.07296862 0.86540763 -2.3015387 1.74481176 -0.7612069 0.3190391 -0.24937038] |
标准高斯分布的值可以通过将值乘以标准差并加上所需缩放分布的均值来缩放。例如:
1 |
缩放值 = mean + value * stdev |
其中 _mean_ 和 _stdev_ 是所需缩放高斯分布的均值和标准差,而 _value_ 是从标准高斯分布中随机生成的值。
打乱 NumPy 数组
可以使用 NumPy 的 shuffle() 函数就地随机打乱 NumPy 数组。
下面的示例演示了如何打乱 NumPy 数组。
1 2 3 4 5 6 7 8 9 10 11 |
# 随机打乱序列 from numpy.random import seed from numpy.random import shuffle # 设定随机数生成器种子 seed(1) # 准备一个序列 sequence = [i for i in range(20)] 打印(序列) # 随机打乱序列 shuffle(sequence) 打印(序列) |
运行此示例会首先生成一个包含 20 个整数值的列表,然后打乱并打印打乱后的数组。
1 2 |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] [3, 16, 6, 10, 2, 14, 4, 17, 7, 1, 13, 0, 19, 18, 9, 15, 8, 12, 11, 5] |
NumPy 中生成随机数的新方法
在较新版本的 NumPy 中,您可以按照以下方式进行随机数生成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import numpy as np rng = np.random.Generator(np.random.PCG64()) rng = np.random.default_rng() # 0 到 1 之间的均匀分布 value = rng.random() # 生成 10 个高斯随机数 value = rng.standard_normal(10) # 生成 0 到 10 之间的 20 个随机整数 value = rng.integers(low=0, high=10, size=20) # 就地打乱序列 rng.shuffle(sequence) |
对象 rng
是一个随机数生成器。您可以创建多个这样的生成器,或使用默认生成器。其思想是允许您拥有多个独立的随机数生成器,因此从一个生成器中抽取的随机数不会影响另一个。这会使您的代码更具健壮性(因为您可以缓解并行算法中的竞争条件),并允许您微调伪随机数生成算法。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
总结
在本教程中,您学习了如何在 Python 中生成和使用随机数。
具体来说,你学到了:
- 随机性可以通过伪随机数生成器在程序中得到应用。
- 如何通过 Python 标准库生成随机数并使用随机性。
- 如何通过 NumPy 库生成随机数数组。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
太棒了!非常感谢!这正是我今天需要的,而且我是随机找到它的,或者应该说伪随机找到的!哈哈!
很高兴它有帮助。
感谢您提供的精彩文章……它帮助我理解了生成随机数的不同方法……
谢谢。
这非常有帮助,Jason。
谢谢
很高兴听到这个消息。
非常翔实的博客!
我有一个问题。
传递给 .seed() 的数字有什么意义?
例如,如果我运行以下代码
# 代码 1
np.random.seed(0)
np.random.rand(4)
# 代码 2
np.random.seed(10)
np.random.rand(4)
两者都显示不同的输出。那么,np.random.seed(10) 和 np.random.seed(0) 有什么区别?
它被输入到启动随机数序列的方程中。相同的种子将产生相同的随机序列。
所以它不是随机的……当你运行模块时,它会给你相同的“随机”数字,所以它不是随机的……
是的,它不是“随机”的,它是通过数学函数控制的伪随机。
太棒了!非常感谢 Jason。这对我来说太完美了!
很高兴听到这个消息。
非常感谢Jason。
只是一个相关话题,有没有办法将生成的随机数保存到 csv 文件?
是的,您可以将它们存储在数组中,并将数组保存为CSV格式。
也许这会有帮助。
https://docs.scipy.org.cn/doc/numpy/reference/generated/numpy.savetxt.html
嗨 Jason,我正在尝试创建多个结果(通过不同的种子)并使用 NumPy 伪随机数生成器(np.random.randomState(seed))在同一张图上绘制。
有没有办法只用一个代码来完成,而不是为比如10个不同的种子编写不同的代码?
George
我不太确定您到底想实现什么?
我的意思是,例如,有没有一种方法可以像您在单个代码中解释的那样,创建 n 个不同的随机种子,它们都应该产生不同的结果。
具体来说,如果我想获得 n 个不同的结果/样本,是否可以通过一个代码随机选择 n 个不同的种子,而不是必须编写 n 次不同的种子代码?
如果您需要很多随机数,您只需要一个随机种子,就可以生成一系列许多随机数。
这有帮助吗?
能给我个代码吗?
上面的教程展示了如何生成随机数序列。
您可以使用 while 循环来处理不同的种子值。然后使用 random.randint(a, b)。
我刚做了一下,很有效!
当然。我明白了。
谢谢
不客气。
太棒了。谢谢 Jason。
谢谢,很高兴对您有帮助。
尊敬的Jason博士,
感谢您的教程。
我尝试了练习,并得出关于生成随机整数的结论。
生成一组不重复的随机整数(不放回)请阅读以下部分:
生成一组随机整数,将数字“放回帽子里”(有放回,可能包含重复项),请阅读:
谢谢你,
悉尼的Anthony
太棒了!
杰森博士,
感谢您宝贵的帖子。
我尝试了以下操作,但没有结果——即打印出“None”。
然而,当我这样做时:
from random import sample
subset = sample(x,100); # subset the whole sample to get around the original problem
subset
[97, 68, 3, 37, 29, 39, 52, 57, 5, 98, 33, 79, 65, 94, 16, 87, 28, 20, 72, 12, 46, 34, 78, 76, 59, 2, 48, 71, 18, 92, 26, 51, 54, 6, 41, 81, 74, 21, 11, 50, 22, 56, 44, 4, 69, 0, 14, 64, 66, 89, 7, 32, 27, 58, 62, 67, 61, 23, 36, 84, 24, 45, 25, 9, 38, 99, 19, 70, 95, 85, 80, 1, 13, 47, 86, 83, 82, 35, 15, 60, 8, 40, 75, 17, 31, 77, 30, 93, 10, 55, 49, 42, 53, 43, 73, 90, 63, 88, 96, 91]
为什么“shuffle”命令不起作用?也就是说,为什么应该打乱的数组会产生“None”结果?
谢谢你,
悉尼的Anthony
即使在重置电脑后,我也没能弄清楚为什么使用“shuffle”命令结果是空的。
目标是生成一个 x 和 fx 的数组,其中 fx = x**2。
上面的方法有效,甚至下面的代码也有效。
看起来,当你直接对变量/二维数组使用 shuffle 时,你可以做到,但原始数组会被修改。
出于某种无法解释的原因,您不能这样做:
不知道为什么,请协助。
谢谢你,
Anthony of Sydney NSW
shuffle() 函数会就地操作数组。它不返回任何内容。
https://docs.scipy.org.cn/doc/numpy-1.15.0/reference/generated/numpy.random.shuffle.html
尊敬的Jason博士,
谢谢你
悉尼的Anthony
我认为 shuffle 是就地执行的,您将 xshuffled 赋值为“None”。
尊敬的Jason博士,
阅读了上面的评论和两个评论前的页面内容后,它返回“None”。
谢谢,非常感谢。
悉尼的Anthony
你好,如何将此随机输出合并到一个文本文件中?
以及如何合并字母数字、字母和整数的随机输出?
您可以生成 numpy 数组,将它们连接起来,然后调用 savetxt。
这个可能会有帮助
https://machinelearning.org.cn/how-to-save-a-numpy-array-to-file-for-machine-learning/
非常感谢!!!
不客气。
我不会 Python。教我。
当然,从这里开始
https://machinelearning.org.cn/faq/single-faq/how-do-i-get-started-with-python-programming
你好,我是 Python 新手,我想给我的随机数列表命名并添加它们。
我该怎么做?
假设我有两个包含十个随机数的列表,想将这两个列表相加得到第三个。
也许可以将列表转换为 numpy 数组并使用 add() 函数。
再次感谢,易于理解和实现!对于像我这样的初学者来说,这是正确的方法!
谢谢,很高兴听到这个!
我需要生成 100 个介于 1 和 3 之间的随机(浮点)数。我该怎么做?
上面的教程将向您展示具体方法!
如何将 1-100 的随机数绘制成直方图?它只给出了绘制的图,而不是所有值。
好问题。
首先生成您的数字并将其存储在列表或数组中。
然后使用 matplotlib 的 hist() 函数并将您的数字列表或数组传递给它。
https://matplotlib.net.cn/3.1.1/api/_as_gen/matplotlib.pyplot.hist.html
谢谢!
不客气。
非常好的教程。我来这里寻找一些我期望在最后找到的东西,但没有找到。
如何从标准正态分布生成整数?
类似于 randint,但用于正态分布而非均匀分布。
换句话说,类似于 randn 但返回一个整数。
某种程度上它会是“randnint”。
有这样的函数吗?
谢谢!
好问题,也许可以生成高斯实值,然后将它们缩放到您想要的范围,或者乘以 10、100、1000 等,然后四舍五入结果。
我怀疑有更好的方法,检查文献以找到高效算法可能是一个好主意。
谢谢你
不客气。
非常感谢 Jason 博士!
它对我帮助很大,对其他人也肯定有帮助。
精彩分享
谢谢,很高兴听到这个。
除了数字之外,我如何随机生成信息?我想生成随机的美式橄榄球队。有什么想法吗?
您可以有一个体育队伍列表,从 1 到 n,然后生成一个 1 到 n 的数字来从列表中选择一个随机项。
你好 Jason,我如何从机器数字(52 39 70 77 73)生成随机数?
是的,您可以生成随机整数,请参阅上面的示例。