RuntimeError: mat1 and mat2 shapes cannot be multiplied (2810x16 and 2x16)

import torch
import torch.nn.functional as F
from torch_geometric.data import Data
import os
import random
import torch.optim as optim
from torch_geometric.data import Data, DataLoader

class Encoder(torch.nn.Module):
def init(self, n_node_features, n_hidden):
super(Encoder, self).init()
self.lin_node = torch.nn.Linear(n_node_features, n_hidden)

def forward(self, x, edge_index, edge_attr):
    x = F.relu(self.lin_node(x))
    print("Encoder output:", x.shape)
    return x

class Processor(torch.nn.Module):
def init(self, n_edge_features, n_hidden):
super(Processor, self).init()
self.lin_edge = torch.nn.Linear(n_edge_features, n_hidden)
self.gru = torch.nn.GRUCell(n_hidden, n_hidden)

def forward(self, x, edge_index, edge_attr):
    edge_attr = edge_attr.repeat(1, 16)
    print("Processor input x:", x.shape)
    print("Processor input edge_index:", edge_index.shape)
    print("Processor input edge_attr:", edge_attr.shape)
    
    edge_attr = F.relu(self.lin_edge(edge_attr))
    print("Processor edge_attr after lin_edge:", edge_attr.shape)
    
    row, col = edge_index
    aggr = self.gru(edge_attr, x[col])
    print("Processor aggr:", aggr.shape)
    
    x = aggr[row].sum(dim=1)
    print("Processor output:", x.shape)
    return x

class Decoder(torch.nn.Module):
def init(self, n_hidden, n_output):
super(Decoder, self).init()
self.lin_out = torch.nn.Linear(n_hidden, n_output)

def forward(self, x, edge_index, edge_attr):
    x = F.relu(self.lin_out(x))
    x = x.mean(dim=0)
    print("Decoder output:", x.shape)
    return x

class MPNN(torch.nn.Module):
def init(self, n_node_features, n_edge_features, n_hidden, n_output):
super(MPNN, self).init()
self.encoder = Encoder(n_node_features, n_hidden)
self.processor = Processor(n_edge_features, n_hidden)
self.decoder = Decoder(n_hidden, n_output)

def forward(self, data):
    x, edge_index, edge_attr = data.x, data.edge_index, data.edge_attr
    x = self.encoder(x, edge_index, edge_attr) #output of encoder
    x = self.processor(x, edge_index, edge_attr)
    x = self.decoder(x, edge_index, edge_attr)
    print("MPNN output:", x.shape)
    return x

def read_labeled_data_file(file_path):
with open(file_path, ‘r’) as f:
content = f.readlines()

adj_matrix = []
for line in content:
    line = line.strip()
    if line:  # Skip empty lines
        row = list(map(int, line.split(',')))
        adj_matrix.append(row)

max_flow = adj_matrix[-1][-1]
adj_matrix = adj_matrix[:-1]  # Remove last row containing max flow

return adj_matrix, max_flow

def adjacency_matrix_to_edge_index(adj_matrix):
edge_index = []
edge_features = []

for i in range(len(adj_matrix)):
    for j in range(len(adj_matrix[i])):
        if adj_matrix[i][j] > 0:
            edge_index.append([i, j])
            edge_features.append([adj_matrix[i][j]])

return torch.tensor(edge_index, dtype=torch.long).t().contiguous(), torch.tensor(edge_features, dtype=torch.float32)

def create_mpnn_data(adj_matrix, max_flow):
node_features = torch.eye(len(adj_matrix), dtype=torch.float32)
edge_index, edge_features = adjacency_matrix_to_edge_index(adj_matrix)

data = Data(x=node_features, edge_index=edge_index, edge_attr=edge_features, y=torch.tensor([max_flow], dtype=torch.float32))
return data

def read_and_process_files(file_paths):
data_list = []
for file_path in file_paths:
adj_matrix, max_flow = read_labeled_data_file(file_path)
data = create_mpnn_data(adj_matrix, max_flow)
data_list.append(data)
return data_list

data_dir = ‘C:/Users/Admin/Desktop/working_codes/data/’
file_paths = [os.path.join(data_dir, f) for f in os.listdir(data_dir) if os.path.isfile(os.path.join(data_dir, f))]

random.shuffle(file_paths)
train_ratio, test_ratio = 0.7, 0.2
n_files = len(file_paths)

train_files = file_paths[:int(train_ratio * n_files)]
test_files = file_paths[int(train_ratio * n_files):int((train_ratio + test_ratio) * n_files)]
eval_files = file_paths[int((train_ratio + test_ratio) * n_files):]

train_data = read_and_process_files(train_files)
test_data = read_and_process_files(test_files)
eval_data = read_and_process_files(eval_files)
print(train_data[0])

train_loader = DataLoader(train_data, batch_size=32, shuffle=True)
test_loader = DataLoader(test_data, batch_size=32, shuffle=False)
eval_loader = DataLoader(eval_data, batch_size=32, shuffle=False)

sample_data = train_data[0]
n_node_features = sample_data.x.shape[1]

n_edge_features =2
n_hidden = 16
n_output = 1

model = MPNN(n_node_features, n_edge_features, n_hidden, n_output)

loss_function = torch.nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 10
validation_interval = 10

for epoch in range(num_epochs):
model.train()
total_loss = 0
for batch in train_loader:
optimizer.zero_grad()
output = model(batch)
loss = loss_function(output, batch.y)
loss.backward()
optimizer.step()
total_loss += loss.item()

avg_loss = total_loss / len(train_loader)
print(f"Epoch: {epoch + 1}, Loss: {avg_loss:.4f}")

if (epoch + 1) % validation_interval == 0:
    model.eval()
    total_val_loss = 0
    with torch.no_grad():
        for val_batch in test_loader:
            val_output = model(val_batch)
            val_loss = loss_function(val_output, val_batch.y)
            total_val_loss += val_loss.item()
    avg_val_loss = total_val_loss / len(test_loader)
    print(f"Validation Loss: {avg_val_loss:.4f}")

This is the error on the console:
File ~\anaconda3\envs\t_3_10\lib\site-packages\torch\nn\modules\linear.py:114 in forward
return F.linear(input, self.weight, self.bias)
RuntimeError: mat1 and mat2 shapes cannot be multiplied (2810x16 and 2x16)

The code is quite hard to read and cannot be copied for debugging as you haven’t properly formatted it.
However, the error points to a shape mismatch in a linear layer so check which nn.Linear expects an input with 2 features and either change it to 16 or make sure the incoming activation has only 2 features.