import numpy as np
import torch
import random
def same_seeds(seed):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True
这段代码的作用是确保实验的可重复性(reproducibility),即每次运行代码时都能得到相同的结果。这在机器学习研究中非常重要,因为可重复性是科学研究的基本要求之一。具体来说,这段代码设置了多个随机种子,以确保随机操作的结果是确定性的。
代码解释
- 设置随机种子:
-
random.seed(seed)
:设置 Python 的标准库random
模块的随机种子。np.random.seed(seed)
:设置 NumPy 的随机种子。torch.manual_seed(seed)
:设置 PyTorch 的随机种子。
- CUDA 支持:
-
if torch.cuda.is_available():
:检查是否有可用的 CUDA 设备。torch.cuda.manual_seed(seed)
:设置 CUDA 的随机种子。torch.cuda.manual_seed_all(seed)
:设置所有 CUDA 设备的随机种子,以确保多 GPU 环境下的可重复性。
- 禁用 cuDNN 的 benchmark 模式:
-
torch.backends.cudnn.benchmark = False
:禁用 cuDNN 的 benchmark 模式。cuDNN 的 benchmark 模式会自动寻找最合适的卷积算法,但这会导致结果的非确定性。torch.backends.cudnn.deterministic = True
:设置 cuDNN 为确定性模式,以确保卷积操作的结果是确定性的。
详细解释
- 设置随机种子:
-
- Python 标准库
random
模块:设置 Python 标准库random
模块的随机种子,确保所有基于random
模块的操作具有确定性。 - NumPy:设置 NumPy 的随机种子,确保所有基于 NumPy 的随机操作具有确定性。
- PyTorch:设置 PyTorch 的随机种子,确保所有基于 PyTorch 的随机操作具有确定性。
- Python 标准库
- CUDA 支持:
-
- 单个 CUDA 设备:如果只有一个 CUDA 设备,只需设置
torch.cuda.manual_seed(seed)
。 - 多个 CUDA 设备:如果有多个 CUDA 设备,需要为所有设备设置相同的随机种子,使用
torch.cuda.manual_seed_all(seed)
。
- 单个 CUDA 设备:如果只有一个 CUDA 设备,只需设置
- 禁用 cuDNN 的 benchmark 模式:
-
- 禁用 benchmark 模式:cuDNN 的 benchmark 模式会根据输入数据动态选择最佳算法,这会导致结果的非确定性。通过设置
torch.backends.cudnn.benchmark = False
,确保每次使用的卷积算法相同。 - 设置确定性模式:通过设置
torch.backends.cudnn.deterministic = True
,确保卷积操作的结果是确定性的。
- 禁用 benchmark 模式:cuDNN 的 benchmark 模式会根据输入数据动态选择最佳算法,这会导致结果的非确定性。通过设置
示例代码
下面是一个完整的示例,展示了如何使用这段代码来确保实验的可重复性:
import random
import numpy as np
import torch
def set_random_seeds(seed):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True
# 设置随机种子
set_random_seeds(42)
# 示例:创建随机张量
x = torch.rand(3, 3)
y = np.random.rand(3, 3)
# 打印随机张量
print("Tensor x:\n", x)
print("Numpy array y:\n", y)
总结
这段代码通过设置多个随机种子,并禁用 cuDNN 的 benchmark 模式,确保了实验的可重复性。这对于科学研究非常重要,因为可重复性是验证实验结果的关键因素之一。
在机器学习和深度学习的训练过程中,随机数(或随机数生成器)的使用非常普遍,尤其是在涉及数据增强、初始化权重、数据采样、随机梯度下降(SGD)等场景中。以下是训练过程中会用到随机数的一些常见场合:
1. 数据增强(Data Augmentation)
数据增强是通过对现有数据集中的数据进行变换来生成新的训练样本的过程。这些变换包括旋转、平移、缩放、裁剪、翻转等。为了确保每次生成的数据不同,通常会使用随机数生成器。
举例
import torch
import torchvision.transforms as transforms
# 设置随机种子
torch.manual_seed(42)
# 数据增强
transform = transforms.Compose([
transforms.RandomHorizontalFlip(p=0.5),
transforms.ToTensor()
])
# 加载数据集
train_dataset = torchvision.datasets.CIFAR10(
root='./data', train=True, download=True, transform=transform
)
# 迭代训练数据
for data, target in train_dataset:
pass # 训练模型
2. 初始化权重(Weight Initialization)
神经网络的权重通常需要随机初始化,以打破对称性并促进更好的收敛。
举例
import torch
import torch.nn as nn
# 设置随机种子
torch.manual_seed(42)
# 创建一个简单的模型
class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc = nn.Linear(10, 20)
def forward(self, x):
return self.fc(x)
# 创建模型实例
model = SimpleNet()
# 查看初始化的权重
print(model.fc.weight.data)
3. 随机梯度下降(Stochastic Gradient Descent, SGD)
在每次迭代时,随机选择一个或一批样本进行梯度更新。选择样本的过程需要使用随机数生成器。
举例
import torch
import torch.optim as optim
# 设置随机种子
torch.manual_seed(42)
# 创建一个简单的模型
model = nn.Linear(10, 20)
# 创建优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 加载数据集
train_loader = torch.utils.data.DataLoader(
dataset,
batch_size=32,
shuffle=True # 每个 epoch 开始时重新洗牌
)
# 训练模型
for epoch in range(num_epochs):
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
4. Dropout
Dropout 是一种正则化技术,通过随机丢弃(即设置为零)一部分神经元的输出来防止过拟合。Dropout 的随机性也需要使用随机数生成器。
举例
import torch
import torch.nn as nn
# 设置随机种子
torch.manual_seed(42)
# 创建一个简单的模型
class DropoutNet(nn.Module):
def __init__(self):
super(DropoutNet, self).__init__()
self.fc = nn.Linear(10, 20)
self.dropout = nn.Dropout(p=0.5)
def forward(self, x):
x = self.fc(x)
x = self.dropout(x)
return x
# 创建模型实例
model = DropoutNet()
# 输入数据
input_data = torch.randn(5, 10)
# 通过模型前向传播
output = model(input_data)
# 打印输出
print(output)
5. 数据采样(Data Sampling)
在某些情况下,可能需要从数据集中随机抽取样本进行评估或其他目的。
举例
import torch
# 设置随机种子
torch.manual_seed(42)
# 创建一个简单的数据集
dataset = torch.randn(100, 10)
# 随机抽取 10 个样本
indices = torch.randperm(len(dataset))[:10]
sampled_data = dataset[indices]
# 打印抽样数据
print(sampled_data)