【问题标题】:RuntimeError: shape '[128, -1]' is invalid for input of size 378 pytorchRuntimeError: shape '[128, -1]' 对于大小为 378 pytorch 的输入无效
【发布时间】:2022-01-15 05:22:36
【问题描述】:

我正在为具有 21 个特征且批量大小为 128 的数据运行尖峰神经网络。经过多次训练迭代后出现以下错误(此错误不会立即出现!):

RuntimeError: shape '[128, -1]' is invalid for input of size 378 pytorch

当我去打印之前张量的形状时,我得到以下信息:

Train
torch.Size([128, 21])
Test
torch.Size([128, 21])

这是我的网络:

class SpikingNeuralNetwork(nn.Module):
    """
        Parameters in SpikingNeuralNetwork class:
        
        1. number_inputs: Number of inputs to the SNN.
        2. number_hidden: Number of hidden layers.
        3. number_outputs: Number of output classes.
        4. beta: Decay rate. 
    """
    def __init__(self, number_inputs, number_hidden, number_outputs, beta):
        super().__init__()
        self.number_inputs = number_inputs
        self.number_hidden = number_hidden
        self.number_outputs = number_outputs
        self.beta = beta

        # Initialize layers
        self.fc1 = nn.Linear(self.number_inputs, self.number_hidden) # Applies linear transformation to all input points
        self.lif1 = snn.Leaky(beta = self.beta) # Integrates weighted input over time, emitting a spike if threshold condition is met
        self.fc2 = nn.Linear(self.number_hidden, self.number_outputs) # Applies linear transformation to output spikes of lif1
        self.lif2 = snn.Leaky(beta = self.beta) # Another spiking neuron, integrating the weighted spikes over time

    """
        Forward propagation of SNN. The code below function will only be called once the input argument x 
        is explicitly passed into net.

        @param x: input passed into the network
        @return layer of output after applying final spiking neuron
    """
    def forward(self, x):
        num_steps = 25

        # Initialize hidden states at t = 0
        mem1 = self.lif1.init_leaky()
        mem2 = self.lif2.init_leaky()

        # Record the final layer
        spk2_rec = []
        mem2_rec = []

        for step in range(num_steps):
            cur1 = self.fc1(x)
            spk1, mem1 = self.lif1(cur1, mem1)
            cur2 = self.fc2(spk1)
            spk2, mem2 = self.lif2(cur2, mem2)
            spk2_rec.append(spk2)
            mem2_rec.append(mem2)

        return torch.stack(spk2_rec, dim = 0), torch.stack(mem2_rec, dim = 0)

这是我的训练循环:

def training_loop(net, train_loader, test_loader, dtype, device, optimizer):
    num_epochs = 1
    loss_history = []
    test_loss_history = []
    counter = 0

    # Temporal dynamics
    num_steps = 25

    # Outer training loop
    for epoch in range(num_epochs):
        iter_counter = 0
        train_batch = iter(train_loader)

        # Minibatch training loop
        for data, targets in train_batch:
            data = data.to(device)
            targets = targets.to(device)

            # Forward pass
            net.train()
            print("Train")
            print(data.size())
            spk_rec, mem_rec = net(data.view(batch_size, -1))

            # Initialize the loss and sum over time
            loss_val = torch.zeros((1), dtype = dtype, device = device)
            for step in range(num_steps):
                loss_val += loss_function(mem_rec[step], targets.long().flatten().to(device))

            # Gradient calculation and weight update
            optimizer.zero_grad()
            loss_val.backward()
            optimizer.step()

            # Store loss history for future plotting
            loss_history.append(loss_val.item())

            # Test set
            with torch.no_grad():
                net.eval()
                test_data, test_targets = next(iter(test_loader))
                test_data = test_data.to(device)
                test_targets = test_targets.to(device)

                # Test set forward pass
                print("Test")
                print(test_data.size())
                test_spk, test_mem = net(test_data.view(batch_size, -1))

                # Test set loss
                test_loss = torch.zeros((1), dtype = dtype, device = device)
                for step in range(num_steps):
                    test_loss += loss_function(test_mem[step], test_targets.long().flatten().to(device))
                test_loss_history.append(test_loss.item())

                # Print train/test loss and accuracy
                if counter % 50 == 0:
                    train_printer(epoch, iter_counter, counter, loss_history, data, targets, test_data, test_targets)
                counter = counter + 1
                iter_counter = iter_counter + 1
    
    return loss_history, test_loss_history

错误发生在spk_rec, mem_rec = net(data.view(batch_size, -1))

代码是从 https://snntorch.readthedocs.io/en/latest/tutorials/tutorial_5.html 采用的,它最初用于 MNIST 数据集。但是,我没有使用图像数据集。我正在使用具有 21 个特征并仅预测一个目标(具有 100 个类)的数据集。我尝试根据我看到的其他一些论坛答案将data.view(batch_size, -1)test_data.view(batch_size, -1) 更改为data.view(batch_size, 21)test_data.view(batch_size, 21),并且我的程序现在正在通过培训循环运行。有没有人对我如何在没有错误的情况下完成培训有任何建议?

编辑:我现在从spk_rec, mem_rec = net(data.view(batch_size, -1)) 收到错误RuntimeError: shape '[128, 21]' is invalid for input of size 378

这是我的数据加载器:

    train_loader = DataLoader(dataset = train, batch_size = batch_size, shuffle = True)
    test_loader = DataLoader(dataset = test, batch_size = batch_size, shuffle = True)

我的批量大小是 128。

【问题讨论】:

  • 你能显示数据加载器吗?通常,如果 dataloder 正确,则该转换会自动完成:它加载形状为 21 的示例,并自动变为批处理,21
  • @NicolaLandro 我添加了它们!
  • 尝试自己运行它以尝试解决您的问题我也很幸运:net params 和 snn.snn.Leaky(我写了一个回复,如果我能修复它,我可以执行并尝试找到错误,请在答案中查看)

标签: deep-learning pytorch runtime-error dimensions pytorch-dataloader


【解决方案1】:

尝试自己运行它以尝试解决您的问题我也很幸运:net params 和 snn.snn.Leaky

import torch
from torch import nn
from torch.utils.data import DataLoader


class SpikingNeuralNetwork(nn.Module):
    """
        Parameters in SpikingNeuralNetwork class:

        1. number_inputs: Number of inputs to the SNN.
        2. number_hidden: Number of hidden layers.
        3. number_outputs: Number of output classes.
        4. beta: Decay rate.
    """

    def __init__(self, number_inputs, number_hidden, number_outputs, beta):
        super().__init__()
        self.number_inputs = number_inputs
        self.number_hidden = number_hidden
        self.number_outputs = number_outputs
        self.beta = beta

        # Initialize layers
        self.fc1 = nn.Linear(self.number_inputs,
                             self.number_hidden)  # Applies linear transformation to all input points
        self.lif1 = snn.Leaky(
            beta=self.beta)  # Integrates weighted input over time, emitting a spike if threshold condition is met
        self.fc2 = nn.Linear(self.number_hidden,
                             self.number_outputs)  # Applies linear transformation to output spikes of lif1
        self.lif2 = snn.Leaky(beta=self.beta)  # Another spiking neuron, integrating the weighted spikes over time

    """
        Forward propagation of SNN. The code below function will only be called once the input argument x 
        is explicitly passed into net.

        @param x: input passed into the network
        @return layer of output after applying final spiking neuron
    """

    def forward(self, x):
        num_steps = 25

        # Initialize hidden states at t = 0
        mem1 = self.lif1.init_leaky()
        mem2 = self.lif2.init_leaky()

        # Record the final layer
        spk2_rec = []
        mem2_rec = []

        for step in range(num_steps):
            cur1 = self.fc1(x)
            spk1, mem1 = self.lif1(cur1, mem1)
            cur2 = self.fc2(spk1)
            spk2, mem2 = self.lif2(cur2, mem2)
            spk2_rec.append(spk2)
            mem2_rec.append(mem2)

        return torch.stack(spk2_rec, dim=0), torch.stack(mem2_rec, dim=0)


batch_size = 2
train = torch.rand(128, 21)
test = torch.rand(128, 21)
train_loader = DataLoader(dataset=train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test, batch_size=batch_size, shuffle=True)

net = SpikingNeuralNetwork(number_inputs=1)
loss_function = nn.CrossEntropyLoss()
optimizer = nn.optim.Adam(net.parameters(), lr=0.1)


def training_loop(net, train_loader, test_loader, dtype, device, optimizer):
    num_epochs = 1
    loss_history = []
    test_loss_history = []
    counter = 0

    # Temporal dynamics
    num_steps = 25

    # Outer training loop
    for epoch in range(num_epochs):
        iter_counter = 0
        train_batch = iter(train_loader)

        # Minibatch training loop
        for data, targets in train_batch:
            data = data.to(device)
            targets = targets.to(device)

            # Forward pass
            net.train()
            print("Train")
            print(data.size())
            spk_rec, mem_rec = net(data.view(batch_size, -1))

            # Initialize the loss and sum over time
            loss_val = torch.zeros((1), dtype=dtype, device=device)
            for step in range(num_steps):
                loss_val += loss_function(mem_rec[step], targets.long().flatten().to(device))

            # Gradient calculation and weight update
            optimizer.zero_grad()
            loss_val.backward()
            optimizer.step()

            # Store loss history for future plotting
            loss_history.append(loss_val.item())

            # Test set
            with torch.no_grad():
                net.eval()
                test_data, test_targets = next(iter(test_loader))
                test_data = test_data.to(device)
                test_targets = test_targets.to(device)

                # Test set forward pass
                print("Test")
                print(test_data.size())
                test_spk, test_mem = net(test_data.view(batch_size, -1))

                # Test set loss
                test_loss = torch.zeros((1), dtype=dtype, device=device)
                for step in range(num_steps):
                    test_loss += loss_function(test_mem[step], test_targets.long().flatten().to(device))
                test_loss_history.append(test_loss.item())

                # Print train/test loss and accuracy
                if counter % 50 == 0:
                    train_printer(epoch, iter_counter, counter, loss_history, data, targets, test_data, test_targets)
                counter = counter + 1
                iter_counter = iter_counter + 1

    return loss_history, test_loss_history

【讨论】:

    【解决方案2】:

    您的代码在 MNIST 数据集上运行良好,因此我认为可能是 DataLoader 的调用方式存在问题。我的猜测是整个数据集不能被您的batch_size 整除。如果这是真的,那么您有两个选择:

    1. 试试spk_rec, mem_rec = net(data.flatten(1)),而不是spk_rec, mem_rec = net(data.view(batch_size, -1)),它会保留数据的第一个维度。

    2. 或者,您可能需要在 DataLoader 函数中设置 drop_last=True

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-03
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2019-07-31
      • 2021-12-16
      • 2022-06-28
      • 2020-06-11
      相关资源
      最近更新 更多