PyTorch实现CNN遇RuntimeError:多进程启动异常求助
问题:PyTorch DataLoader 多进程启动错误(Windows环境)
我在使用PyTorch实现CNN时,添加「训练与验证数据集」相关代码后遇到如下RuntimeError,此前所有步骤均正常运行。运行环境为Windows 11系统、PyCharm编辑器、Python 3.8版本。
错误信息
RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your child processes and you have forgotten to use the proper idiom in the main module: if __name__ == '__main__': freeze_support() ... The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.
我的代码
# Import whatever libraries/modules you need import numpy as np import tensorflow as tf from torchvision.datasets import ImageFolder from torchvision.transforms import ToTensor import matplotlib import matplotlib.pyplot as plt import os import torch import torchvision import tarfile from torchvision.datasets.utils import download_url from torch.utils.data import random_split from torch.utils.data.dataloader import DataLoader from torchvision.utils import make_grid # Dowload the dataset dataset_url = "https://s3.amazonaws.com/fast-ai-imageclas/cifar10.tgz" download_url(dataset_url, '.') # # Extract from archive to data/cifar10, containing training set and test set # with tarfile.open('./cifar10.tgz', 'r:gz') as tar: # tar.extractall(path='./data') # Verify using os.listdir data_dir = './data/cifar10' print(os.listdir(data_dir)) classes = os.listdir(data_dir + "/train") print(classes) # Load Data as PyTorch Tensors dataset = ImageFolder(data_dir+'/train', transform=ToTensor()) #Display image using matplotlib but change the tensor dimensions to (32, 32, 3) matplotlib.rcParams['figure.facecolor'] = '#ffffff' def show_example(img, label): print('Label: ', dataset.classes[label], "("+str(label)+")") plt.imshow(img.permute(1, 2, 0)) plt.show() show_example(*dataset[0]) show_example(*dataset[1099]) # Training random_seed = 42 torch.manual_seed(random_seed); val_size = 5000 train_size = len(dataset) - val_size train_ds, val_ds = random_split(dataset, [train_size, val_size]) len(train_ds), len(val_ds) batch_size=128 train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True) val_dl = DataLoader(val_ds, batch_size*2, num_workers=4, pin_memory=True) # Look at batches of images from the dataset using the make grid method # Gets a random batch each time since the sampler shuffles the indices before creating batches def show_batch(dl): for images, labels in dl: fig, ax = plt.subplots(figsize=(12, 6)) ax.set_xticks([]); ax.set_yticks([]) ax.imshow(make_grid(images, nrow=16).permute(1, 2, 0)) break show_batch(train_dl)
解决方案
Windows系统下Python多进程采用spawn而非Linux的fork机制,子进程会重新执行整个脚本的全局代码,因此必须将触发多进程的逻辑(如DataLoader初始化、数据加载执行)放在if __name__ == '__main__':代码块内,避免子进程重复初始化导致错误。
修改后的代码示例:
# Import whatever libraries/modules you need import numpy as np import tensorflow as tf from torchvision.datasets import ImageFolder from torchvision.transforms import ToTensor import matplotlib import matplotlib.pyplot as plt import os import torch import torchvision import tarfile from torchvision.datasets.utils import download_url from torch.utils.data import random_split from torch.utils.data.dataloader import DataLoader from torchvision.utils import make_grid # Display image using matplotlib but change the tensor dimensions to (32, 32, 3) matplotlib.rcParams['figure.facecolor'] = '#ffffff' def show_example(img, label, classes): print('Label: ', classes[label], "("+str(label)+")") plt.imshow(img.permute(1, 2, 0)) plt.show() def show_batch(dl): for images, labels in dl: fig, ax = plt.subplots(figsize=(12, 6)) ax.set_xticks([]); ax.set_yticks([]) ax.imshow(make_grid(images, nrow=16).permute(1, 2, 0)) break if __name__ == '__main__': # Dowload the dataset dataset_url = "https://s3.amazonaws.com/fast-ai-imageclas/cifar10.tgz" download_url(dataset_url, '.') # # Extract from archive to data/cifar10, containing training set and test set # with tarfile.open('./cifar10.tgz', 'r:gz') as tar: # tar.extractall(path='./data') # Verify using os.listdir data_dir = './data/cifar10' print(os.listdir(data_dir)) classes = os.listdir(data_dir + "/train") print(classes) # Load Data as PyTorch Tensors dataset = ImageFolder(data_dir+'/train', transform=ToTensor()) show_example(*dataset[0], classes) show_example(*dataset[1099], classes) # Training random_seed = 42 torch.manual_seed(random_seed) val_size = 5000 train_size = len(dataset) - val_size train_ds, val_ds = random_split(dataset, [train_size, val_size]) print(len(train_ds), len(val_ds)) batch_size=128 train_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True) val_dl = DataLoader(val_ds, batch_size*2, num_workers=4, pin_memory=True) show_batch(train_dl)
说明:
- 将所有执行逻辑(包括数据下载、加载、DataLoader初始化、图像展示)放入
if __name__ == '__main__':块内 - 调整
show_example函数,将classes作为参数传入,避免子进程中无法访问全局变量的问题 - 保留函数定义、库导入在全局区域,不影响子进程调用
内容的提问来源于stack exchange,提问作者Derz
相关产品推荐
相关产品推荐

