Materials as Graphs


Introduction


Graph Neural Networks


GNN + MS



Step 1: Setting Up the Environment

!pip install torch
!pip install torch-geometric

Step 2: Data Preparation

Methane (CH4)

import torch
from torch_geometric.data import Data

# Methane (CH4) molecule
nodes_ch4 = torch.tensor([[6.0], [1.0], [1.0], [1.0], [1.0]], dtype=torch.float)  # Carbon and Hydrogen atoms
edges_ch4 = torch.tensor([[0, 0, 0, 0], [1, 2, 3, 4]], dtype=torch.long)  # Bonds between C and H
edge_attr_ch4 = torch.tensor([[1], [1], [1], [1]], dtype=torch.float)  # Single bonds
data_ch4 = Data(x=nodes_ch4, edge_index=edges_ch4, edge_attr=edge_attr_ch4, y=torch.tensor([16.0]))  # Example property

Carbon Dioxide (CO2)

# Carbon Dioxide (CO2) molecule
nodes_co2 = torch.tensor([[6.0], [8.0], [8.0]], dtype=torch.float)  # Carbon and Oxygen atoms
edges_co2 = torch.tensor([[0, 0], [1, 2]], dtype=torch.long)  # Bonds between C and O
edge_attr_co2 = torch.tensor([[2], [2]], dtype=torch.float)  # Double bonds
data_co2 = Data(x=nodes_co2, edge_index=edges_co2, edge_attr=edge_attr_co2, y=torch.tensor([44.0]))  # Example property

Benzene (C6H6)

# Benzene (C6H6) molecule
nodes_benzene = torch.tensor([[6.0], [6.0], [6.0], [6.0], [6.0], [6.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0]], dtype=torch.float)  # Carbon and Hydrogen atoms
edges_benzene = torch.tensor([
    [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 1, 2, 3, 4, 5],  # Bonds between C and H, and C-C
    [1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 0, 11, 1, 2, 3, 4, 5, 0]
], dtype=torch.long)  # Bond indices
edge_attr_benzene = torch.tensor([[1], [1], [2], [1], [1], [2], [1], [2], [1], [2], [1], [1], [2], [1], [2], [1], [2], [1]], dtype=torch.float)  # Bond types
data_benzene = Data(x=nodes_benzene, edge_index=edges_benzene, edge_attr=edge_attr_benzene, y=torch.tensor([78.0]))  # Example property

Step 3: Defining the GNN Model

import torch.nn.functional as F
from torch_geometric.nn import GCNConv

class GCN(torch.nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(input_dim, hidden_dim)
        self.conv2 = GCNConv(hidden_dim, hidden_dim)
        self.fc = torch.nn.Linear(hidden_dim, output_dim)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = self.conv2(x, edge_index)
        x = torch.mean(x, dim=0)  # Global mean pooling
        x = self.fc(x)
        return x

# Model instantiation
model = GCN(input_dim=1, hidden_dim=16, output_dim=1)

Step 4: Training the Model

import torch.optim as optim

# Training settings
learning_rate = 0.01
epochs = 100

# Optimizer
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# Training loop
model.train()
for epoch in range(epochs):
    optimizer.zero_grad()
    out = model(data_ch4)  # Change to data_co2 or data_benzene for other molecules
    target = data_ch4.y
    loss = F.mse_loss(out, target)
    loss.backward()
    optimizer.step()
    if epoch % 10 == 0:
        print(f'Epoch {epoch}, Loss: {loss.item()}')

Step 5: Evaluating the Model

# Evaluation
model.eval()
with torch.no_grad():
    prediction = model(data_ch4)  # Change to data_co2 or data_benzene for other molecules
    print(f'Prediction: {prediction.item()}, Target: {data_ch4.y.item()}')

Adding New Properties to the GNN

Methane (CH4)

# Methane (CH4) molecule with atomic mass and electronegativity
# Node features: [atom_type, atomic_mass, electronegativity]
nodes_ch4 = torch.tensor([
    [6.0, 12.01, 2.55],  # Carbon atom: C
    [1.0, 1.008, 2.20],  # Hydrogen atoms: H
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20]
], dtype=torch.float)
edges_ch4 = torch.tensor([[0, 0, 0, 0], [1, 2, 3, 4]], dtype=torch.long)  # Bonds between C and H
edge_attr_ch4 = torch.tensor([[1], [1], [1], [1]], dtype=torch.float)  # Single bonds
data_ch4 = Data(x=nodes_ch4, edge_index=edges_ch4, edge_attr=edge_attr_ch4, y=torch.tensor([16.0]))  # Example property

Carbon Dioxide (CO2)

# Carbon Dioxide (CO2) molecule with atomic mass and electronegativity
# Node features: [atom_type, atomic_mass, electronegativity]
nodes_co2 = torch.tensor([
    [6.0, 12.01, 2.55],  # Carbon atom: C
    [8.0, 16.00, 3.44],  # Oxygen atoms: O
    [8.0, 16.00, 3.44]
], dtype=torch.float)
edges_co2 = torch.tensor([[0, 0], [1, 2]], dtype=torch.long)  # Bonds between C and O
edge_attr_co2 = torch.tensor([[2], [2]], dtype=torch.float)  # Double bonds

data_co2 = Data(x=nodes_co2, edge_index=edges_co2, edge_attr=edge_attr_co2, y=torch.tensor([44.0]))  # Example property

Benzene (C6H6)

# Benzene (C6H6) molecule with atomic mass and electronegativity
# Node features: [atom_type, atomic_mass, electronegativity]
nodes_benzene = torch.tensor([
    [6.0, 12.01, 2.55],  # Carbon atoms: C
    [6.0, 12.01, 2.55],
    [6.0, 12.01, 2.55],
    [6.0, 12.01, 2.55],
    [6.0, 12.01, 2.55],
    [6.0, 12.01, 2.55],
    [1.0, 1.008, 2.20],  # Hydrogen atoms: H
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20],
    [1.0, 1.008, 2.20]
], dtype=torch.float)
edges_benzene = torch.tensor([
    [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 1, 2, 3, 4, 5],  # Bonds between C and H, and C-C
    [1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 0, 11, 1, 2, 3, 4, 5, 0]
], dtype=torch.long)  # Bond indices
edge_attr_benzene = torch.tensor([[1], [1], [2], [1], [1], [2], [1], [2], [1], [2], [1], [1], [2], [1], [2], [1], [2], [1]], dtype=torch.float)  # Bond types

data_benzene = Data(x=nodes_benzene, edge_index=edges_benzene, edge_attr=edge_attr_benzene, y=torch.tensor([78.0]))  # Example property

Conclusion


canpolat Avatar

Posted by