простой начальный блок в pytorch, требующий гораздо больше времени для обучения на GPU? - PullRequest
1 голос
/ 04 августа 2020

Я тренирую очень простой начальный блок, за которым следует maxpool и полностью подключенный уровень на графическом процессоре NVIDIA GeForce RTX 2070, и его итерация занимает очень много времени. Только что выполнено 10 итераций за более чем 24 часа.

Вот код для определения начальной модели

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        input_channels = 3
        conv_block = BasicConv2d(input_channels, 64, kernel_size=1)
        self.branch3x3stack = nn.Sequential(
            BasicConv2d(input_channels, 64, kernel_size=1),
            BasicConv2d(64, 96, kernel_size=3, padding=1),
            BasicConv2d(96, 96, kernel_size=3, padding=1),
        )

        self.branch3x3 = nn.Sequential(
            BasicConv2d(input_channels, 64, kernel_size=1),
            BasicConv2d(64, 96, kernel_size=3, padding=1),
        )

        self.branch1x1 = BasicConv2d(input_channels, 96, kernel_size=1)

        self.branchpool = nn.Sequential(
            nn.AvgPool2d(kernel_size=3, stride=1, padding=1),
            BasicConv2d(input_channels, 96, kernel_size=1),
        )
        self.maxpool = nn.MaxPool2d(kernel_size=8, stride=8)
        self.fc_seqn = nn.Sequential(nn.Linear(301056, 1))

    def forward(self, x):
        x = [
            self.branch3x3stack(x),
            self.branch3x3(x),
            self.branch1x1(x),
            self.branchpool(x),
        ]
        x = torch.cat(x, 1)
        x = self.maxpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc_seqn(x)
        return x  # torch.cat(x, 1)

и код обучения, который я использовал

def training_code(self, model):
    model = copy.deepcopy(model)
    model = model.to(self.device)
    criterion = nn.MSELoss()
    optimizer = optim.Adam(model.parameters(), lr=self.learning_rate)
    for epoch in range(self.epochs):
        print("\n epoch :", epoch)
        running_loss = 0.0
        start_epoch = time.time()
        for i, (inputs, labels) in enumerate(self.train_data_loader):
            inputs = inputs.to(self.device)
            labels = labels.to(self.device)
            optimizer.zero_grad()
            outputs = (model(inputs)).squeeze()
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
            if i % log_step == log_step - 1:
                avg_loss = running_loss / float(log_step)
                print("[epoch:%d, batch:%5d] loss: %.3f" % (epoch + 1, i + 1, avg_loss))
                running_loss = 0.0
        if epoch % save_model_step == 0:
            self.path_saved_model = path_saved_model + "_" + str(epoch)
            self.save_model(model)
    print("\nFinished Training\n")
    self.save_model(model)

Вот сводка сверточной нейронной сети. Может ли кто-нибудь помочь мне, пожалуйста, как ускорить обучение?

summary of convolution neural network

Here is the summary of the convolution neural network after reducing the number of inputs to the fully-connected (FC) layer. But still the training time is very high similar as before. Can suggestion on how to speed up the training will be helpful.

сводка модифицированного cnn

1 Ответ

0 голосов
/ 04 августа 2020

Архитектура

Ваш nn.Linear имеет огромные входные данные, которые поступают только на один нейрон для регрессии.

Вы должны использовать torch.nn.AdaptiveAvgPool2d вот так:

class Net(nn.Module):
    def __init__(self):
        ... # your stuff before
        self.pool = nn.AdaptiveAvgPool2D(output_size=1)
        self.fc_seqn = nn.Sequential(nn.Linear(96 * 4, 1))

    def forward(self, x):
        x = [
            self.branch3x3stack(x),
            self.branch3x3(x),
            self.branch1x1(x),
            self.branchpool(x),
        ]
        x = torch.cat(x, 1)
        x = torch.squeeze(self.pool(x))
        if len(x.shape) == 1:
            x = torch.unsqueeze(x, dim=0)
        x = self.fc_seqn(x)
        return x

Это также должно помочь в решении вашей задачи, поскольку оно не будет настолько параметризованным.

Данные

В зависимости от размера вашего изображения вы можете захотеть обрезать его (или произвольно обрезать), используя torchvision.transforms, чтобы уменьшить размер.

Если вы можете, вы также можете go с torch.nn.DistributedDataParallel, чтобы распараллеливать на многих графических процессорах, но я полагаю, это не то, что вам нужно.

Вы также можете cache некоторые данные после загрузки изображения (см. проект torchdata (__disclaimer: I ' m автор)).

Также torch.utils.data.DataLoader с аргументом num_workers, установленным на большее число, чем 1, должно ускорить загрузку изображения (я обычно go с номером ядер, которые есть на моей машине, хотя вам потребуются некоторые эксперименты с этим).

Смешанная точность

Вы должны получить большую пользу от этого это шаг, поскольку ваша карта graphi c поддерживает технологию тензорных ядер .

В PyTorch 1.6.0 это довольно просто с пакетом torch.cuda.amp. По сути, вам просто нужно использовать один диспетчер контекста и масштабатор градиента ( здесь и здесь соответственно).

Это позволяет вам использовать больший размер пакета (поскольку архитектура имеет некоторый вес преобразован в float16 вместо float32).

...