为什么要设置随机种子

alt

什么是随机种子

在我们阅读别人代码的时候,经常会在代码中看到这样一段。

seed=42
ramdom.seed(seed)
np.random.seed(seed)
torch.manual.seed(seed)
torch.cuda.manual.seed(seed)

很多人会好奇这几行代码的作用。实际上,在深度学习任务中,很多情况下需要进行随机初始化参数、随机打乱数据集、随机选择样本等操作,这些操作的随机性可能会导致不同的运行结果,而这几行代码的作用是为了确保在进行上述随机性操作时,每次运行得到的结果都是可重复的,我们称之为随机种子。也就是说,设置了相同的随机种子后,每次运行程序得到的随即结果都是一样的,这样就保证了实验的可重复性,方便调试与验证模型。

随机种子的简单示例

下面我们将以numpy与pytorch的随机种子为例,来看一下随机种子的作用。

numpy

numpy中设置随机种子使用的是np.random.seed(seed),其中seed是一个取值范围在-2^32到2^32-1之间的任意整数。下面是一个随机种子的简单示例。

# 设置随机种子为7
np.random.seed(7)
# 生成一个长度为3的随机数组
print(np.random.rand(3))
# 生成一个长度为3的随机数组
print(np.random.rand(3))
# 重新设置随机种子为7,以确保再次生成相同的随机序列
np.random.seed(7)
# 生成一个长度为5的随机数组
print(np.random.rand(5))
# 生成一个长度为1的随机数组
print(np.random.rand(1))
# 重新设置随机种子为1
np.random.seed(1)
# 生成一个长度为3的随机数组,此时的种子不同,所以得到的结果也会不同
print(np.random.rand(3))
# 生成一个长度为3的随机数组,此时的种子不同,所以得到的结果也会不同
print(np.random.rand(3))
>>>[0.07630829 0.77991879 0.43840923]
>>>[0.72346518 0.97798951 0.53849587]
>>>[0.07630829 0.77991879 0.43840923 0.72346518 0.97798951]
>>>[0.53849587]
>>>[4.17022005e-01 7.20324493e-01 1.14374817e-04]
>>>[0.30233257 0.14675589 0.09233859]

在示例中,我们首先定义里随机种子为7,然后输出了两遍长度为3的随机数组,此时这两个随机数组的值是不一样的,这里很多人会好奇,不是说每次运行的结果都是一样的吗,原因我们在后面详细描述。第一次一共输出了6个随机值。而后我们重新定义了随机种子,此时再分别输出了长度为5与长度为1的随机数组,这里我们发现,虽然每次输出的随机数组长度与第一次不同,但整体输出的结果与第一次输出的结果相同,并且输出顺序保持一致。最后我们定义了随机种子为1,此时我们继续输出两个长度为3的随机数组,但对比前面的结果发现,输出结果已经发生了改变,因为随机种子已经发生了变化。

pytorch

在我们日常使用pytorch进行深度学习任务时,通常使用torch.manual_seed(seed)与torch.cuda.manual_seed(seed)来分别设置CPU与GPU中的随机种子。

import torch
# 创建一个简单的神经网络模型
model = torch.nn.Sequential(
    torch.nn.Linear(1010),
    torch.nn.ReLU(),
    torch.nn.Linear(102)
)
# 设置随机种子
seed = 42
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
# 定义输入数据
input_data1 = torch.randn(110)
input_data2 = torch.randn(110)
# 第一次输出结果
output1 = model(input_data1)
output2 = model(input_data2)
# 重新定义随机种子
seed = 43
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
# 定义输入数据
input_data3 = torch.randn(110)
# 第二次运行模型
output3 = model(input_data3)
# 恢复第一次随机种子
seed = 42
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
# 定义输入数据
input_data4 = torch.randn(110)
input_data5 = torch.randn(110)
# 第三次运行模型
output4 = model(input_data4)
output5 = model(input_data5)
# 输出两次运行的结果进行对比
print("Output 1:")
print(output1)
print("Output 2:")
print(output2)
print("Output 3:")
print(output3)
print("Output 4:")
print(output4)
print("Output 5:")
print(output5)
Output 1:
tensor([[-0.0672,  0.1808]], grad_fn=<AddmmBackward0>)
Output 2:
tensor([[-0.0665,  0.5292]], grad_fn=<AddmmBackward0>)
Output 3:
tensor([[0.16380.2211]], grad_fn=<AddmmBackward0>)
Output 4:
tensor([[-0.0672,  0.1808]], grad_fn=<AddmmBackward0>)
Output 5:
tensor([[-0.0665,  0.5292]], grad_fn=<AddmmBackward0>)

从结果可以看出,当随机种子一致时,模型输出的结果是一致的,当随机种子发生改变,模型结果也相应的发生改变。在深度学习任务中,如果加入随机种子,就能最大限度地保障了模型的可复现性,方便调试与验证模型。

其它固定操作

在深度学习任务时,通常我们还通过设置cudnn算法的确定性与benchmark模式,确保在使用GPU进行计算时,每次计算结果都是一致的,并且提高计算效率。在PyTorch中,cudnn是NVIDIA提供的一个用于深度学习加速的库,它实现了一系列高效的深度学习算法。在PyTorch中,还可以通过设置torch.backends.cudnn.deterministic和 torch.backends.cudnn.benchmark两个参数来控制cudnn库的行为。

确定性(Deterministic)模式: 当 torch.backends.cudnn.deterministic 设置为True时,PyTorch会强制让cudnn使用确定性算法,这意味着对于相同的输入,每次计算的输出都是确定的,即结果可重复。这对于调试和验证模型是非常有用的,因为可以确保每次运行得到相同的结果。

Benchmark模式: 当 torch.backends.cudnn.benchmark 设置为True时,PyTorch会尝试寻找最适合当前配置的cudnn卷积算法,以提高计算效率。它会在第一次运行时进行一些预处理,并记录每个卷积算法的运行时间。随后的运行将根据先前的运行结果选择最快的算法。这可以提高训练速度,特别是在大型模型和大批量数据上,但如果卷积层是一直变化的,将会导致程序不停的做优化,反而会耗费更多的时间。

随机种子的原理

前面我们发现当定义了随机种子后,如果不重新定义随机种子,那么当前随机种子下每次进行随机数获取的值是不一样的。这是为什么呢?这里就涉及到了随机数的原理。

实际上,我们生成的随机数都是伪随机数。随机不是靠人为或机能创造的,人们不可能靠算法真正做到随机。实际上的随机数,是依靠一种确定性的算法来计算出的一种在0-1上均匀分布的随机数序列算法,它并不是真正的随机。随机种子就是用来控制算法生成的伪随机数序列的。当设置相同的随机种子时,算法生成的随机数序列是相同的。 因此在相同的种子下,随机数生成的结果是可重复的。这种机制使得我们能够在需要随机性的场景中获得可控的、可重复的结果,从而方便调试、验证和比较实验结果。

当我们设置随机种子后,算法会生成一段随机数序列,在我们重新设置任意随机种子之前,每次取值,都会在随机数序列中顺序取值,比如先取三个随机数,再去三个随机数,那么实际上就是在随机数序列中顺序获取6个随机数。这就是为什么,上面我们设置随机种子后,连续两次取三个随机数,但结果不同的原因。当我们重新设置种子后,随机数序列会重新生成,如果随机种子一样,那么生成的序列会一样,此时我们再获取随机数,就会和之前的随机数保持一致了。

小结

在深度学习任务中,设置随机种子可以最大限度的保障我们结果的可复现性,方便我们调试与验证。感兴趣的可以进一步学习,并且对随机种子的作用进行测试。

往期精彩

SENet实现遥感影像场景分类
SENet实现遥感影像场景分类
BiseNet实现遥感影像地物
BiseNet实现遥感影像地物
FC-Densenet实现遥感影像道路分类
FC-Densenet实现遥感影像道路分类
pytorch实现遥感影像建筑物提取
pytorch实现遥感影像建筑物提取

本文由 mdnice 多平台发布

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DataAssassin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值