google-deepmind / graph_nets

Build Graph Nets in Tensorflow
https://arxiv.org/abs/1806.01261
Apache License 2.0
5.34k stars 783 forks source link

no output from processor #152

Closed balexx2 closed 1 year ago

balexx2 commented 1 year ago

hello iam running this but no output from processor, what could be the issue.

alvarosg commented 1 year ago

Hi, could you clarify which code/example you are running to run into this problem?

balexx2 commented 1 year ago

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))]

Shuffle file paths

random.shuffle(file_paths)

Split into train, test, and evaluation sets

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):]

Process graph files and create Data objects

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])

Create DataLoaders for train, test, and evaluation sets

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)

Get the number of node features from a sample data point

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

Hyperparameters

n_edge_features =2 n_hidden = 16 n_output = 1

Create MPNN model

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

Define the loss function and the optimizer

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

Training the model

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)

print(output)

    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}")

Test the model

model.eval()

total_test_loss = 0

with torch.no_grad():

for test_batch in eval_loader:

test_output = model(test_batch)

test_loss = loss_function(test_output, test_batch.y)

total_test_loss += test_loss.item()

avg_test_loss = total_test_loss / len(eval_loader)

print(f"Test Loss: {avg_test_loss:.4f}")

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

balexx2 commented 1 year ago

this is the one graph file data you can use: has adjacency matrix and maximum flow=54 at the bottom 0, 2, 5, 6, 6, 8, 9, 2, 0, 3, 10 2, 0, 11, 14, 3, 4, 0, 10, 0, 6, 9 5, 11, 0, 18, 5, 7, 1, 6, 0, 5, 9 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1 8, 3, 5, 4, 0, 11, 10, 5, 0, 1, 2 8, 4, 7, 4, 11, 0, 16, 10, 0, 6, 9 11, 6, 1, 12, 10, 16, 0, 9, 0, 1, 4 2, 10, 6, 14, 5, 10, 9, 0, 0, 5, 4 2, 2, 10, 20, 6, 4, 20, 12, 0, 30, 2 3, 12, 13, 16, 1, 6, 1, 5, 0, 0, 9 10, 9, 9, 3, 2, 9, 4, 4, 0, 9, 0

54

alvarosg commented 1 year ago

This code does not seems to be using our library since it seems to be using torch while our library is for tensorflow.

balexx2 commented 1 year ago

oooh yes.. i can still implement in tensorflow but some assistance. I need to use encode-process-decode algorithm to learn and predict maximum flow in the network. but i get that error. some guidance is highly welcomed.

alvarosg commented 1 year ago

Thanks, I would recommend in that case to try to get support in a different torch-specific venue.