Reputation: 81
I am using EfficientNet to extract features and trying to add a fully connected layer to pre-trained model to reduce the dimension of the out-features from efficientnet to 512. I encountered the following error when the features pass through the layer or the function that I defined.
"Typeerror: 1 positional argument but 2 were given"
Here are the code that I tried:
# define a function to reduce the dimension to 512
# def block_dim_red():
# block_dim_red = Sequential(OrderedDict([
# ('fc', Linear(1280, 512)),
# ]))
# return block_dim_red
def fc():
fc = Linear(in_features = 1280, out_feaures = 512)
return fc
The following codes show how I defined the Class BaseModel(object).
Thank you very much in advance.
class BaseModel(object):
def __init__(self):
self.image_size = 224
self.dimision = 1280
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.load_model()
def load_model(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model = EfficientNet.from_pretrained('efficientnet-b0').to(self.device)
self.model = self.model.eval()
self.PIXEL_MEANS = torch.tensor((0.485, 0.456, 0.406)).to(self.device)
self.PIXEL_STDS = torch.tensor((0.229, 0.224, 0.225)).to(self.device)
self.num = torch.tensor(255.0).to(self.device)
def preprocess_input(self, image):
image = cv2.resize(image, (self.image_size, self.image_size))
# gpu version
image_tensor = torch.from_numpy(image.copy()).to(self.device).float()
image_tensor /= self.num
image_tensor -= self.PIXEL_MEANS
image_tensor /= self.PIXEL_STDS
image_tensor = image_tensor.permute(2, 0, 1)
return image_tensor
# define a function to reduce the dimension to 512
# def block_dim_red():
# block_dim_red = Sequential(OrderedDict([
# ('fc', Linear(1280, 512)),
# ]))
# return block_dim_red
def fc():
fc = Linear(in_features = 1280, out_feaures = 512)
return fc
def forward(self, x):
x = self.preprocess_input(x).unsqueeze(0)
# extraccted feature shape torch.Size([1, 1280, 7, 7])
x = self.model.extract_features(x)
x = F.max_pool2d(x, kernel_size=(7, 7))
x = x.view(x.size(0),-1)
x = torch.reshape(x,(-1,1))
x = self.fc(x) # fully connecte layer to reduce dimension
return self.torch2list(x)
def torch2list(self, torch_data):
return torch_data.cpu().detach().numpy().tolist()
def load_model(): return BaseModel()
Upvotes: 1
Views: 3389
Reputation: 740
There was a self.fc()
problem in your def forward
function
def __init__(self):
self.image_size = 224
self.dimision = 1280
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.load_model()
def load_model(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model = EfficientNet.from_pretrained('efficientnet-b0').to(self.device)
self.model = self.model.eval()
self.PIXEL_MEANS = torch.tensor((0.485, 0.456, 0.406)).to(self.device)
self.PIXEL_STDS = torch.tensor((0.229, 0.224, 0.225)).to(self.device)
self.num = torch.tensor(255.0).to(self.device)
def preprocess_input(self, image):
image = cv2.resize(image, (self.image_size, self.image_size))
# gpu version
image_tensor = torch.from_numpy(image.copy()).to(self.device).float()
image_tensor /= self.num
image_tensor -= self.PIXEL_MEANS
image_tensor /= self.PIXEL_STDS
image_tensor = image_tensor.permute(2, 0, 1)
return image_tensor
# define a function to reduce the dimension to 512
# def block_dim_red():
# block_dim_red = Sequential(OrderedDict([
# ('fc', Linear(1280, 512)),
# ]))
# return block_dim_red
def fc():
fc = Linear(in_features = 1280, out_feaures = 512)
return fc
def forward(self, x):
x = self.preprocess_input(x).unsqueeze(0)
# extraccted feature shape torch.Size([1, 1280, 7, 7])
x = self.model.extract_features(x)
x = F.max_pool2d(x, kernel_size=(7, 7))
x = x.view(x.size(0),-1)
x = torch.reshape(x,(-1,1))
self.fc()(x)
return self.torch2list(x)
def torch2list(self, torch_data):
return torch_data.cpu().detach().numpy().tolist()
def load_model():
return BaseModel()
Upvotes: 0
Reputation: 169
Try replacing x = self.fc(x)
with self.fc()(x)
since self.fc()
is a function that expects no arguments and returns the Linear layer which in turn expects the argument.
Although a better way would be to add self.fc = Linear(in_features = 1280, out_feaures = 512)
inside the __init__
and use x=self.fc(x)
as you have done.
Upvotes: 1