• Pytorch指定数据加载器使用子进程


    torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True,num_workers=4, pin_memory=True)

    num_workers 参数是 DataLoader 类的一个参数,它指定了数据加载器使用的子进程数量。通过增加 num_workers 的数量,可以并行地读取和预处理数据,从而提高数据加载的速度。

    通常情况下,增加 num_workers 的数量可以提高数据加载的效率,因为它可以使数据加载和预处理工作在多个进程中同时进行。然而,当 num_workers 的数量超过一定阈值时,增加更多的进程可能不会再带来更多的性能提升,甚至可能会导致性能下降。

    这是因为增加 num_workers 的数量也会增加进程间通信的开销。当 num_workers 的数量过多时,进程间通信的开销可能会超过并行化所带来的收益,从而导致性能下降。

    此外,还需要考虑到计算机硬件的限制。如果你的计算机 CPU 核心数量有限,增加 num_workers 的数量也可能会导致性能下降,因为每个进程需要占用 CPU 核心资源。

    因此,对于 num_workers 参数的设置,需要根据具体情况进行调整和优化。通常情况下,一个合理的 num_workers 值应该在 2 到 8 之间,具体取决于你的计算机硬件配置和数据集大小等因素。在实际应用中,可以通过尝试不同的 num_workers 值来找到最优的配置。

    综上所述,当 num_workers 的值从 4 增加到 8 时,如果你的计算机硬件配置和数据集大小等因素没有发生变化,那么两者之间的性能差异可能会很小,或者甚至没有显著差异。

    测试代码如下

    1. import torch
    2. import torchvision
    3. import matplotlib.pyplot as plt
    4. import torchvision.models as models
    5. import torch.nn as nn
    6. import torch.optim as optim
    7. import torch.multiprocessing as mp
    8. import time
    9. if __name__ == '__main__':
    10. mp.freeze_support()
    11. train_on_gpu = torch.cuda.is_available()
    12. if not train_on_gpu:
    13. print('CUDA is not available. Training on CPU...')
    14. else:
    15. print('CUDA is available! Training on GPU...')
    16. device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    17. batch_size = 4
    18. # 设置数据预处理的转换
    19. transform = torchvision.transforms.Compose([
    20. torchvision.transforms.Resize((512,512)), # 调整图像大小为 224x224
    21. torchvision.transforms.ToTensor(), # 转换为张量
    22. torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化
    23. ])
    24. dataset = torchvision.datasets.ImageFolder('C:\\Users\\ASUS\\PycharmProjects\\pythonProject1\\cats_and_dogs_train',
    25. transform=transform)
    26. val_ratio = 0.2
    27. val_size = int(len(dataset) * val_ratio)
    28. train_size = len(dataset) - val_size
    29. train_dataset, val_dataset = torch.utils.data.random_split(dataset, [train_size, val_size])
    30. train_dataset = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True,num_workers=4, pin_memory=True)
    31. val_dataset = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=True,num_workers=4, pin_memory=True)
    32. model = models.resnet18()
    33. num_classes = 2
    34. for param in model.parameters():
    35. param.requires_grad = False
    36. model.fc = nn.Sequential(
    37. nn.Dropout(),
    38. nn.Linear(model.fc.in_features, num_classes),
    39. nn.LogSoftmax(dim=1)
    40. )
    41. optimizer = optim.Adam(model.parameters(), lr=0.001)
    42. criterion = nn.CrossEntropyLoss().to(device)
    43. model.to(device)
    44. filename = "recognize_cats_and_dogs.pt"
    45. def save_checkpoint(epoch, model, optimizer, filename):
    46. checkpoint = {
    47. 'epoch': epoch,
    48. 'model_state_dict': model.state_dict(),
    49. 'optimizer_state_dict': optimizer.state_dict(),
    50. 'loss': loss,
    51. }
    52. torch.save(checkpoint, filename)
    53. num_epochs = 3
    54. train_loss = []
    55. for epoch in range(num_epochs):
    56. running_loss = 0
    57. correct = 0
    58. total = 0
    59. epoch_start_time = time.time()
    60. for i, (inputs, labels) in enumerate(train_dataset):
    61. # 将数据放到设备上
    62. inputs, labels = inputs.to(device), labels.to(device)
    63. # 前向计算
    64. outputs = model(inputs)
    65. # 计算损失和梯度
    66. loss = criterion(outputs, labels)
    67. optimizer.zero_grad()
    68. loss.backward()
    69. # 更新模型参数
    70. optimizer.step()
    71. # 记录损失和准确率
    72. running_loss += loss.item()
    73. train_loss.append(loss.item())
    74. _, predicted = torch.max(outputs.data, 1)
    75. correct += (predicted == labels).sum().item()
    76. total += labels.size(0)
    77. accuracy_train = 100 * correct / total
    78. # 在测试集上计算准确率
    79. with torch.no_grad():
    80. running_loss_test = 0
    81. correct_test = 0
    82. total_test = 0
    83. for inputs, labels in val_dataset:
    84. inputs, labels = inputs.to(device), labels.to(device)
    85. outputs = model(inputs)
    86. loss = criterion(outputs, labels)
    87. running_loss_test += loss.item()
    88. _, predicted = torch.max(outputs.data, 1)
    89. correct_test += (predicted == labels).sum().item()
    90. total_test += labels.size(0)
    91. accuracy_test = 100 * correct_test / total_test
    92. # 输出每个 epoch 的损失和准确率
    93. epoch_end_time = time.time()
    94. epoch_time = epoch_end_time - epoch_start_time
    95. print("Epoch [{}/{}], Time: {:.4f}s, Loss: {:.4f}, Train Accuracy: {:.2f}%, Loss: {:.4f}, Test Accuracy: {:.2f}%"
    96. .format(epoch + 1, num_epochs,epoch_time,running_loss / len(val_dataset),
    97. accuracy_train, running_loss_test / len(val_dataset), accuracy_test))
    98. save_checkpoint(epoch, model, optimizer, filename)
    99. plt.plot(train_loss, label='Train Loss')
    100. # 添加图例和标签
    101. plt.legend()
    102. plt.xlabel('Epochs')
    103. plt.ylabel('Loss')
    104. plt.title('Training Loss')
    105. # 显示图形
    106. plt.show()

    不同num_workers的结果如下

  • 相关阅读:
    java各类面试题集合
    Ubuntu 18.04 LTS PWN安装
    【英语口语】01 - 原子介绍
    【从零开始学习 SystemVerilog】8.8、SystemVerilog 约束—— foreach Constraint
    合并区间问题
    Windows 安装 Nginx, 本地访问vue打包项目
    JS-Bom-while(计算闰年)
    在Linux上以all in one模式安装kubernetes & kubesphere
    Windows平台搭建wxWidgets 3.2.3开发环境
    模型部署libtorch
  • 原文地址:https://blog.csdn.net/Victor_Li_/article/details/134040006