I have a problem when running the saved model of a CNN. When I train the model and the input tensor size of the first linear layer is set to the shape for the training data after it is flattened and went through the convolution layers, everything works. However, when I do the same with the test data after I saved and reload the model, an error shows up.
The error:
RuntimeError Traceback (most recent call last)Cell In[20], line 84 with torch.no_grad():5 for images in X_test.unsqueeze(0):6 images = images.to(device)7----> 8 output = model(images)9 _, predictions = torch.max(output, 1)1011 all_prediction.extend(predictions.cpu().numpy())
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1778, in Module._wrapped_call_impl(self, *args, **kwargs)1776 return self._compiled_call_impl(*args, **kwargs) # type: ignore[misc]1777 else: → 1778 return self._call_impl(*args, **kwargs)
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1789, in Module._call_impl(self, *args, **kwargs)1784 # If we don’t have any hooks, we want to skip the rest of the logic in1785 # this function, and just call forward.1786 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks1787 or _global_backward_pre_hooks or _global_backward_hooks1788 or _global_forward_hooks or _global_forward_pre_hooks): → 1789 return forward_call(*args, **kwargs)1791 result = None1792 called_always_called_hooks = set()
Cell In[11], line 30, in GroceryObjectDetectorv2.forward(self, x)26 def forward(self, x):27 x = x.to(device)28 x = self.conv_layer(x)29 print(f"After conv layer: {x.shape}") # Debug—> 30 x = self.dense_layer(x)31 return x
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1778, in Module._wrapped_call_impl(self, *args, **kwargs)1776 return self._compiled_call_impl(*args, **kwargs) # type: ignore[misc]1777 else: → 1778 return self._call_impl(*args, **kwargs)
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1789, in Module._call_impl(self, *args, **kwargs)1784 # If we don’t have any hooks, we want to skip the rest of the logic in1785 # this function, and just call forward.1786 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks1787 or _global_backward_pre_hooks or _global_backward_hooks1788 or _global_forward_hooks or _global_forward_pre_hooks): → 1789 return forward_call(*args, **kwargs)1791 result = None1792 called_always_called_hooks = set()
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\container.py:253, in Sequential.forward(self, input)249 “”"250 Runs the forward pass.251 “”"252 for module in self: → 253 input = module(input)254 return input
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1778, in Module._wrapped_call_impl(self, *args, **kwargs)1776 return self._compiled_call_impl(*args, **kwargs) # type: ignore[misc]1777 else: → 1778 return self._call_impl(*args, **kwargs)
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\module.py:1789, in Module._call_impl(self, *args, **kwargs)1784 # If we don’t have any hooks, we want to skip the rest of the logic in1785 # this function, and just call forward.1786 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks1787 or _global_backward_pre_hooks or _global_backward_hooks1788 or _global_forward_hooks or _global_forward_pre_hooks): → 1789 return forward_call(*args, **kwargs)1791 result = None1792 called_always_called_hooks = set()
File ~\Desktop\groceryClassifyer\torchGPU\Lib\site-packages\torch\nn\modules\linear.py:134, in Linear.forward(self, input)130 def forward(self, input: Tensor) → Tensor:131 “”"132 Runs the forward pass.133 “”" → 134 return F.linear(input, self.weight, self.bias)
RuntimeError: mat1 and mat2 shapes cannot be multiplied (128x784 and 100352x128)
I do not know how to fix this as I had tried to put a parameter in the class so I can adjust the dense layer’s input tensor of the denser layer but it broke the model.
This is the model(without the parameter that changes the input tensor’s value in dense layer):
class GroceryObjectDetectorv2(nn.Module):def init(self):super().init()self.conv_layer = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(2, 2),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2),
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.dense_layer = nn.Sequential(
nn.Flatten(),
nn.Linear(796, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 43)# number of classes
)
def forward(self, x):
x = self.conv_layer(x)
print(f"After conv layer: {x.shape}") # Debug
x = self.dense_layer(x)
return x
This is my code to run the model with train data:
def accuracy_fn(y_true, y_pred):
“”"Calculates accuracy between truth labels and predictions.
Args:
y_true (torch.Tensor): Truth labels for predictions.
y_pred (torch.Tensor): Predictions to be compared to predictions.
Returns:
[torch.float]: Accuracy value between y_true and y_pred, e.g. 78.45
"""
correct = torch.eq(y_true, y_pred).sum().item()
acc = (correct / len(y_pred)) * 100
return acc
epochs = 100
train_losses = []
train_accs = []
val_losses = []
val_accs = []
for epoch in range(epochs):
model.train()
# running_loss keeps track of the loss in each batch
train_running_loss = 0.0
train_running_acc = 0.0
for X_batch, y_batch in train_loader:
X_batch = X_batch.to(device)
y_batch = y_batch.to(device)
optimizer.zero_grad()
#insert a batch to the model
train_y_pred = model(X_batch).to(device)
#calculate the loss of the batch
loss = loss_fn(train_y_pred, y_batch)
#calculate accuracy of the batch
train_y_pred_class = torch.argmax(train_y_pred, dim=1)
train_acc = accuracy_fn(y_batch, train_y_pred_class)
loss.backward()
optimizer.step()
train_running_loss += loss.item()
train_running_acc += train_acc
average_train_loss = train_running_loss / len(train_loader)
train_losses.append(average_train_loss)
average_train_acc = train_running_acc / len(train_loader)
train_accs.append(average_train_acc)
model.eval()
# running_loss keeps track of the loss in each batch
val_running_loss = 0.0
val_running_acc = 0.0
with torch.no_grad():
for X_val, y_val in val_loader:
#insert a batch to the model
val_y_pred = model(X_val).to(device)
#calculate the loss of the batch
val_loss = loss_fn(val_y_pred, y_val)
#calculate accuracy of the batch
val_y_pred_class = torch.argmax(val_y_pred, dim=1)
val_acc = accuracy_fn(y_batch, val_y_pred_class)
val_running_loss += val_loss.item()
val_running_acc += val_acc
average_val_loss = val_running_loss / len(val_loader)
val_losses.append(average_val_loss)
average_acc = val_running_acc / len(val_loader)
val_accs.append(average_acc)
print(f"Epoch: {epoch + 1} Train: Acc: {train_running_acc / len(train_loader):.2f}% Loss: {train_running_loss / len(train_loader):.4f} | Validation: Acc: {val_running_acc / len(val_loader):.2f}% Loss: {val_running_loss / len(val_loader)
This is the code when I fit the model with test data:
model.to(device)
model.eval()folder = r"C:/Users/FiercePC/Desktop/groceryClassifyer/"
images = labels =
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor()])
for i in range(len(test_df)):path = test_df[“path”].iloc[i]label = test_df[“label”].iloc[i] # change “label” if your column has a different name
img = Image.open(folder + "data/img/" + path).convert("RGB")
img = transform(img)
images.append(img)
labels.append(label)
test_image_tensor = torch.stack(images)test_label_tensor = torch.tensor(labels, dtype=torch.long)
test_loader = DataLoader(test_image_tensor, batch_size=32, shuffle=False)
X_test = next(iter(test_image_tensor)).to(device)y_test = test_label_tensor.to(device)
all_prediction = model.eval()
with torch.no_grad():for images in X_test.unsqueeze(0):images = images.to(device)
output = model(images)
_, predictions = torch.max(output, 1)
all_prediction.extend(predictions.cpu().numpy())
print(all_prediction)