batch size 训练时间_pytorch一机多卡训练

bf311dc39fbc263cd09783960d8fe2d4.png

1. 一机多卡(one matchine multi-GPU)

1.1 DataParallel

DataParallel(DP):Parameter Server模式,一张卡位reducer,实现也超级简单,一行代码。 有个不能接受的缺陷是:DataParallel是基于Parameter server的算法,所有的loss都在主卡上计算,负载不均衡的问题比较严重,有时在模型较大的时候(比如bert-large),主卡占满了,其他的卡一半都占不到,及其浪费资源。 示例代码:

# coding=utf-8

import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import Dataset, DataLoader

class RandomDataset(Dataset):
    def __init__(self, size, length):
        self.len = length
        self.data = torch.randn(length, size)

    def __getitem__(self, index):
        return self.data[index]

    def __len__(self):
        return self.len

class Model(nn.Module):
    def __init__(self, input_size, output_size):
        super(Model, self).__init__()
        self.fc = nn.Linear(input_size, output_size)

    def forward(self, input):
        output = self.fc(input)
        return output

input_size = 5
output_size = 2
batch_size = 30
data_size = 30

dataset = RandomDataset(input_size, data_size)
rand_loader = DataLoader(dataset=dataset,
                         batch_size=batch_size, shuffle=True)
model = Model(input_size, output_size)

if torch.cuda.is_available():
    model.cuda()

if torch.cuda.device_count() > 1:
    model = nn.DataParallel(model)  # 关键代码

for data in rand_loader:
    if torch.cuda.is_available():
        input_var = Variable(data.cuda())
    else:
        input_var = Variable(data)
    output = model(input_var)

1.2 DistributedDataParallel

是的,你没有看错,这个函数是为了分布式训练设计的。但是,即使在单机多卡上,官方也建议使用新的DistributedDataParallel,采用all-reduce算法。

(1)初始化后端

torch.cuda.set_device(args.local_rank)
torch.distributed.init_process_group(backend='nccl', init_method='env://')

(2)模型并行化 这里也很简单,使用DistributedDataParallel函数warp一下就可以:

model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank)

(3)数据并行 这里需要注意,如果指定了sampler,则shuffle=False,其中DataLoader的num_worker是每一个卡独立设置。

dataset = RandomDataset(input_size, data_size)
sampler = torch.utils.data.distributed.DistributedSampler(dataset)
rand_loader = DataLoader(dataset=dataset,
                         batch_size=batch_size, shuffle=False, sampler=sampler)

(4)启动脚本

python -m torch.distributed.launch --nproc_per_node=8 train_face_troch.py

完整代码示例:

# coding=utf-8

import torch
import torch.distributed
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import Dataset, DataLoader
import apex
import argparse

class RandomDataset(Dataset):
    def __init__(self, size, length):
        self.len = length
        self.data = torch.randn(length, size)
        self.label = torch.mean(self.data, dim=-1)

    def __getitem__(self, index):
        return self.data[index], self.label[index]

    def __len__(self):
        return self.len

class Model(nn.Module):
    def __init__(self, input_size, output_size):
        super(Model, self).__init__()
        self.fc = nn.Linear(input_size, output_size)

    def forward(self, input):
        output = self.fc(input)
        return output

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--local_rank', default=0, type=int)
    args = parser.parse_args()
    return args

input_size = 5
output_size = 2
batch_size = 30
data_size = 30

args = parse_args()
local_rank = args.local_rank

torch.cuda.set_device(local_rank) # 设定cuda的默认GPU,每个rank不同
torch.distributed.init_process_group(backend='nccl', init_method='env://')

dataset = RandomDataset(input_size, data_size)
sampler = torch.utils.data.distributed.DistributedSampler(dataset)
rand_loader = DataLoader(dataset=dataset,
                         batch_size=batch_size, shuffle=False, sampler=sampler)

model = Model(input_size, output_size)

if torch.cuda.is_available():
    model.cuda()

model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank)

optimizer = torch.optim.Adam(model.parameters())
criterion = torch.nn.CrossEntropyLoss()

# if torch.cuda.device_count() > 1:
#    model = nn.DataParallel(model)

for data, label in rand_loader:
    data = data.cuda()
    label = label.cuda()

    output = model(data)
    loss = criterion(output, label)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

1.3 DistributedDataParallel + apex

大规模数据训练时,混合精度训练时必须的,这速度谁用谁知道。 参考: https://github.com/NVIDIA/apex/tree/master/examples/simple/distributed

这里主要需要改两个地方,一个是amp.initialize这个函数,一个是backward。

# coding=utf-8

import torch
import torch.distributed
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import Dataset, DataLoader
import apex
import argparse

class RandomDataset(Dataset):
    def __init__(self, size, length):
        self.len = length
        self.data = torch.randn(length, size)
        self.label = torch.mean(self.data, dim=-1)

    def __getitem__(self, index):
        return self.data[index], self.label[index]

    def __len__(self):
        return self.len

class Model(nn.Module):
    def __init__(self, input_size, output_size):
        super(Model, self).__init__()
        self.fc = nn.Linear(input_size, output_size)

    def forward(self, input):
        output = self.fc(input)
        return output

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--local_rank', default=0, type=int)
    args = parser.parse_args()
    return args

input_size = 5
output_size = 2
batch_size = 30
data_size = 30

args = parse_args()
local_rank = args.local_rank
# 初始化
torch.cuda.set_device(local_rank)
torch.distributed.init_process_group(backend='nccl', init_method='env://')

dataset = RandomDataset(input_size, data_size)
sampler = torch.utils.data.distributed.DistributedSampler(dataset)
rand_loader = DataLoader(dataset=dataset,
                         batch_size=batch_size, shuffle=False, sampler=sampler)

model = Model(input_size, output_size)
model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank)

optimizer = torch.optim.Adam(model.parameters())

model, optimizer = amp.initialize(model, optimizer, opt_level='O1')  # 这里是字母O

criterion = torch.nn.CrossEntropyLoss()

if torch.cuda.is_available():
    model.cuda()

# if torch.cuda.device_count() > 1:
#     model = nn.DataParallel(model)

for data, label in rand_loader:
    data = data.cuda()
    label = label.cuda()

    output = model(data)
    loss = criterion(output, label)

    optimizer.zero_grad()
    #loss.backward()
    with amp.scale_loss(loss, optimizer) as scaled_loss:
        scaled_loss.backward()
    optimizer.step()

1.4 其他的问题

  1. torch.load会根据之前保存的参数的GPU信息加载到对应的GPU上,但是在DistributedDataParallel 模式下需要加载到不同的GPU中。所以在torch.load的参数可以做如下设定
torch.load(params_path, map_location=lambda storge, loc: storge.cuda(self.local_rank))

2. 多机多卡(multi-matchine multi-GPU)

comming soon
### 回答1: segmentation_models_pytorch 是一个基于 PyTorch 的图像分割库,可以用来训练语义分割模型。下面是使用 segmentation_models_pytorch 实现单模型训练的基本步骤: 1. 安装 segmentation_models_pytorch 和其依赖项: ``` pip install segmentation-models-pytorch ``` 2. 加载数据集并进行预处理。可以使用 torchvision 或者其他图像处理库加载数据集,并对数据进行预处理,如裁剪、缩放、归一化等操作。 3. 定义模型。使用 segmentation_models_pytorch 中提供的模型类(如 UNet、FPN、PSPNet 等)来定义模型。 ```python import segmentation_models_pytorch as smp model = smp.Unet( encoder_name="resnet34", # 使用 ResNet34 作为编码器 encoder_weights="imagenet", # 加载预训练权重 in_channels=3, # 输入通道数 classes=2, # 分类数 ) ``` 4. 定义损失函数和优化器。可以选择使用交叉熵损失函数和 Adam 优化器。 ```python import torch.nn as nn import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) ``` 5. 训练模型。使用 DataLoader 加载数据集,并对模型进行训练。 ```python from torch.utils.data import DataLoader train_loader = DataLoader(dataset, batch_size=4, shuffle=True) for epoch in range(num_epochs): running_loss = 0.0 for i, data in enumerate(train_loader, 0): inputs, labels = data optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}") ``` 6. 保存模型。训练完毕后,可以使用 torch.save() 方法将模型保存到本地。 ```python torch.save(model.state_dict(), "model.pth") ``` ### 回答2: segmentation_models_pytorch是一个基于PyTorch实现的语义分割模型库。使用segmentation_models_pytorch实现单模型训练可以通过以下步骤完成。 首先,安装segmentation_models_pytorch库。可以通过pip install segmentation_models_pytorch命令来安装。 导入所需的库和模型。常用的库包括torch,torchvision和segmentation_models_pytorch。可以使用以下命令导入库: ```python import torch import torchvision.transforms as transforms import segmentation_models_pytorch as smp ``` 加载和预处理训练数据。可以使用torchvision中的transforms来定义一系列的数据预处理操作,例如裁剪、缩放和标准化等。之后,使用torch.utils.data.DataLoader来加载和批量处理数据。 定义模型架构。可以选择使用segmentation_models_pytorch中预定义的模型架构,例如UNet、PSPNet和DeepLab等。根据任务需求选择合适的模型,并初始化相关参数。 定义优化器和损失函数。常见的优化器有Adam和SGD等,损失函数常选择交叉熵损失函数。可以使用torch.optim中的函数来定义优化器,使用torch.nn中的损失函数来定义损失函数。 进行模型训练。使用torch.utils.data.DataLoader加载训练数据集,并迭代训练数据集中的每个批次。将批次数据输入模型中进行前向传播,获取模型的输出。计算损失,并进行反向传播更新模型的参数。重复以上步骤直到达到预定的训练轮数或达到设定的训练目标。 保存和加载训练好的模型。可以使用torch.save函数将训练好的模型保存到指定的文件路径,使用torch.load函数加载保存的模型文件。 以上是使用segmentation_models_pytorch实现单模型训练的基本步骤。根据具体任务和数据的不同,可能还需要进行一些细节操作,例如数据增强、学习率调整和模型评估等。 ### 回答3: segmentation_models_pytorch是一个基于PyTorch的分割模型训练库,可以应用于图像分割任务。下面我将介绍如何使用segmentation_models_pytorch实现单模型训练。 首先,我们需要安装segmentation_models_pytorch库。可以使用pip命令进行安装: ``` pip install segmentation-models-pytorch ``` 在训练之前,我们需要准备好训练数据和标签。通常情况下,训练数据是一些图像,标签则是对应每个像素点的分类或分割结果。 接下来,我们需要导入所需的库: ``` import segmentation_models_pytorch as smp import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, Dataset ``` 然后,我们需要创建一个自定义的数据集类,该类继承自torch.utils.data.Dataset类,并实现__len__和__getitem__方法,用于加载和处理数据。 接着,我们可以选择一个合适的分割模型,比如Unet、FPN等。这些模型可以通过调用smp库中的函数进行初始化,比如: ``` model = smp.Unet( encoder_name="resnet34", encoder_weights="imagenet", classes=1, activation='sigmoid' ) ``` 在这里,我们选择了一个使用ResNet-34作为编码器、预训练权重为ImageNet数据集、分类数为1(二分类问题)的Unet模型。 然后,我们可以定义损失函数和优化器: ``` criterion = nn.BCELoss() optimizer = optim.Adam(model.parameters(), lr=0.001) ``` 接着,我们可以进行训练循环,依次迭代数据进行训练和优化: ``` for epoch in range(num_epochs): for batch in dataloader: inputs, labels = batch optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() ``` 最后,我们可以保存模型并在需要预测时加载模型进行测试: ``` torch.save(model.state_dict(), "segmentation_model.pt") model.load_state_dict(torch.load("segmentation_model.pt")) ``` 以上就是使用segmentation_models_pytorch实现单模型训练的过程。根据具体任务需求,你也可以调整模型、损失函数、优化器等参数来进行更灵活的训练
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值