Custom Function - object has no attribute 'dim'

Hello,
So I’ve been trying to create a custom function and test things out, but I can’t seem to know how to make the data or function work. I’m a little confused. Here is the code:

from collections import OrderedDict
import numpy as np
import torch
from torch import nn
from torch import optim
import torch.nn.functional as F
from torchvision import datasets, transforms
import math


class Custom(nn.Module):
    def __init__(self, weights = 1, dim = 1):
        super().__init__()
        self.weights = weights

    def forward(self, input):
        a = 2
        x = input
        y = a + math.log(x)
        return y


transform = transforms.Compose([transforms.ToTensor(),
  transforms.Normalize((0.5,), (0.5,))
])

trainset = datasets.MNIST('MNIST_data/', download=True, train=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)

input_size = 784
hidden_sizes = [128, 64]
output_size = 10

class Network(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 10)
        
    def forward(self, x):
        x = Custom(x)
        x = self.fc1(x)
        x = Custom(x)
        x = self.fc2(x)
        x = Custom(x)
        x = self.fc3(x)
        
        
        return x

model = Network()

criterion = nn.CrossEntropyLoss() 
optimizer = optim.SGD(model.parameters(), lr=0.003)


#some tutorial
epochs = 3
print_every = 40
steps = 0
for e in range(epochs):
    running_loss = 0
    for images, labels in iter(trainloader):
        steps += 1
        images.resize_(images.size()[0], 784)
        optimizer.zero_grad()
        output = model.forward(images)
        loss = criterion(output, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        
        if steps % print_every == 0:
            print("Epoch: {}/{}... ".format(e+1, epochs),
                    "Loss: {:.4f}".format(running_loss/print_every))
            
            running_loss = 0
torch.save(model.state_dict(),'MNIST_' + str(epochs) + 'ep.pth')
print("I saved the model: " + 'MNIST_' + str(epochs) + 'ep.pth')

The error I get is

Traceback (most recent call last):
  File "MNIST.py", line 68, in <module>
    output = model.forward(images)
  File "MNIST.py", line 43, in forward
    x = self.fc1(x)
  File "/home/caius/anaconda3/envs/Tutorials/lib/python3.8/site-packages/torch/nn/modules/module.py", line 532, in __call__
    result = self.forward(*input, **kwargs)
  File "/home/caius/anaconda3/envs/Tutorials/lib/python3.8/site-packages/torch/nn/modules/linear.py", line 87, in forward
    return F.linear(input, self.weight, self.bias)
  File "/home/caius/anaconda3/envs/Tutorials/lib/python3.8/site-packages/torch/nn/functional.py", line 1368, in linear
    if input.dim() == 2 and bias is not None:
  File "/home/caius/anaconda3/envs/Tutorials/lib/python3.8/site-packages/torch/nn/modules/module.py", line 575, in __getattr__
    raise AttributeError("'{}' object has no attribute '{}'".format(
AttributeError: 'Custom' object has no attribute 'dim'

I don’t know how am I supposed to declare a custom function or to alter the input data so as to make it work.
Thanks and have a wonderful day! :slight_smile:

I think you forgot to add self.dim = dim in Custom.__init__.

Thanks for your reply. I’ve tried similar changes.
Now it seems to show
TypeError: 'int' object is not callable

You would have to create instances of your Custom module before calling it (same as with other modules, e.g. nn.Linear).

Currently you are trying to pass the activation directly to the module instantiation:

x = Custom(x)

Instead define instances of Custom in the __init__ method of Network and call them in forward:

class Network(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 10)
        self.custom = Custom(weights=1)
        
    def forward(self, x):
        x = self.custom(x)
        x = self.fc1(x)
        x = self.custom(x)
        x = self.fc2(x)
        x = self.custom(x)
        x = self.fc3(x)    
        return x

Note that this code will reuse the self.custom module.
Since you don’t have any trainable parameters inside this module, this should be fine.

1 Like