AttributeError: 'function' object has no attribute 'size'

Hi everyone,

I am training an RNN and have come across the following error

    247             input = cast(Tensor, input)
    248             batch_sizes = None
--> 249             max_batch_size = input.size(0) if self.batch_first else input.size(1)
    250             sorted_indices = None
    251             unsorted_indices = None
AttributeError: 'function' object has no attribute 'size'

I understand what the error means, but what I do not understand is why it is happening or where it is occurring. I’d appreciate any feedback if available!

At the risk of not providing enough information this is my training and validation function:

# Training functioN
def train(model, device, train_loader, valid_loader, epochs, learning_rate):

  criterion = nn.CrossEntropyLoss()
  optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
  
  train_loss, validation_loss = [], []
  train_acc, validation_acc = [], []

  for epoch in range(epochs):
    #train
    model.train()
    running_loss = 0.
    correct, total = 0, 0
    steps = 0

    for idx, batch in enumerate(train_loader):
      text = batch["Sample"].to(device)
      target = batch['Class'].to(device)
      print(type(text), text.shape)
      target = torch.autograd.Variable(target).long()
      target = text.to(device), target.to(device)

      # add micro for coding training loop
      optimizer.zero_grad()
      output = model(text)

      loss = criterion(output, target)
      loss.backward()
      optimizer.step()
      steps += 1
      running_loss += loss.item()

      # get accuracy
      _, predicted = torch.max(output, 1)
      total += target.size(0)
      correct += (predicted == target).sum().item()

    train_loss.append(running_loss/len(train_loader))
    train_acc.append(correct/total)

    print(f'Epoch: {epoch + 1}, '
          f'Training Loss: {running_loss/len(train_loader):.4f}, '
          f'Training Accuracy: {100*correct/total: .2f}%')

    # evaluate on validation data
    model.eval()
    running_loss = 0.
    correct, total = 0, 0

    with torch.no_grad():
      for idx, batch in enumerate(valid_loader):
        text = batch["Sample"].to(device)
        print(type(text), text.shape)
        target = batch['Class'].to(device)
        target = torch.autograd.Variable(target).long()
        text, target = text.to(device), target.to(device)

        optimizer.zero_grad()
        output = model(text)

        loss = criterion(output, target)
        running_loss += loss.item()

        # get accuracy
        _, predicted = torch.max(output, 1)
        total += target.size(0)
        correct += (predicted == target).sum().item()

    validation_loss.append(running_loss/len(valid_loader))
    validation_acc.append(correct/total)

    print (f'Validation Loss: {running_loss/len(valid_loader):.4f}, '
           f'Validation Accuracy: {100*correct/total: .2f}%')

  return train_loss, train_acc, validation_loss, validation_acc

Model

class VanillaRNN(nn.Module):

 def __init__(self, output_size, input_size, RNN_size, fc_size,
              device):
   super(VanillaRNN, self).__init__()
   self.RNN_size = RNN_size
   self.fc_size = fc_size
   
# Define the RNN layer
   self.rnn = nn.RNN(input_size, 100, 2)
   # Define the fully connected layer
   self.fc1 = nn.Linear(100, 11)
   self.device = device

 def forward(self, inputs):
   h_0 = torch.zeros(2, input_size, self.RNN_size).to(self.device)
   output, h_n = self.rnn(input, h_0)
   h_n = h_n.permute(1, 0, 2)
   h_n = h_n.contiguous().reshape(h_n.size()[0], self.RNN_size*self.fc_size)
   logits = self.fc(h_n)
   return logits

## Uncomment to test VanillaRNN class

sampleRNN = VanillaRNN(11, 300, 100, 50, DEVICE)

print(sampleRNN)

And this is where I call the training function

# Model hyperparamters
learning_rate = 1e-3
RNN_size = 100
output_size = 11
input_size = 300

epochs = 10
embed_length = 300
fc_size  = 50

# Initialize model, training and testing
set_seed(SEED)
vanilla_rnn_model = VanillaRNN(output_size, input_size, RNN_size, fc_size, DEVICE)
vanilla_rnn_model.to(DEVICE)
vanilla_rnn_start_time = time.time()
vanilla_train_loss, vanilla_train_acc, vanilla_validation_loss, vanilla_validation_acc = train(vanilla_rnn_model,  DEVICE, train_loader, valid_loader, learning_rate = learning_rate)

Change this line in forward

   output, h_n = self.rnn(input, h_0)

to

   output, h_n = self.rnn(inputs, h_0)

This is great, and thank you very much. Typos face palm I am now getting an error stating

IndexError                                Traceback (most recent call last)
<ipython-input-43-b5a747e0c45e> in <module>()
     19                                                                                                valid_loader,
     20                                                                                                epochs = epochs,
---> 21                                                                                                learning_rate = learning_rate)
     22 print("--- Time taken to train = %s seconds ---" % (time.time() - vanilla_rnn_start_time))
     23 #test_accuracy = test(vanilla_rnn_model, DEVICE, test_iter)

4 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/modules/rnn.py in forward(self, input, hx)
    247             input = cast(Tensor, input)
    248             batch_sizes = None
--> 249             max_batch_size = input.size(0) if self.batch_first else input.size(1)
    250             sorted_indices = None
    251             unsorted_indices = None

IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

Based on this post I think it is coming from the way i am creating either my output or predicted objects. I tried changing predictived variable from:

_, predicted = torch.max(output, 1)

to both

predicted = torch.round(output.squeeze())
#AND
_, predicted = torch.round(output.squeeze())

But get the same error. Any thoughts? Thanks for your continued support!!