Hi, I’m trying to implement a neural network example to understand how it works and I get the following error:
C:\GCN\venv\lib\site-packages\torch_geometric\nn\conv\hetero_conv.py:76: UserWarning: There exist node types ({‘t’, ‘g’, ‘c’}) whose representations do not get updated during message passing as they do not occur as destination type in any edge type. This may lead to unexpected behavior.
warnings.warn(
Traceback (most recent call last):
File “C:\GCN\main.py”, line 77, in
out = model(data)
File “C:\GCN\venv\lib\site-packages\torch\nn\modules\module.py”, line 1736, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
File “C:\GCN\venv\lib\site-packages\torch\nn\modules\module.py”, line 1747, in _call_impl
return forward_call(*args, **kwargs)
File “C:\GCN\main.py”, line 29, in forward
out = self.conv1(data.x_dict, data.edge_index_dict)
File “C:\GCN\venv\lib\site-packages\torch\nn\modules\module.py”, line 1736, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
File “C:\GCN\venv\lib\site-packages\torch\nn\modules\module.py”, line 1747, in _call_impl
return forward_call(*args, **kwargs)
File “C:\GCN\venv\lib\site-packages\torch_geometric\nn\conv\hetero_conv.py”, line 119, in forward
src, rel, dst = edge_type
ValueError: too many values to unpack (expected 3)
The code is as follows:
import torch
import torch.nn as nn
import torch.optim as optim
import torch_geometric
from torch_geometric.nn import HeteroConv, GCNConv
from torch_geometric.data import HeteroData
import numpy as np
Definir la red neuronal heterogénea
class HeteroGNN(nn.Module):
def init(self, input_features, output_features):
super(HeteroGNN, self).init()
# Red convolucional para diferentes tipos de nodos, desactivar self-loops
self.conv1 = HeteroConv({
‘generator’: GCNConv(input_features, 64, add_self_loops=False),
‘consumer’: GCNConv(input_features, 64, add_self_loops=False),
‘transformer’: GCNConv(input_features, 64, add_self_loops=False)
}, aggr=‘mean’)
self.conv2 = HeteroConv({
'generator': GCNConv(64, 32, add_self_loops=False),
'consumer': GCNConv(64, 32, add_self_loops=False),
'transformer': GCNConv(64, 32, add_self_loops=False)
}, aggr='mean')
self.fc = nn.Linear(32, output_features) # Predicción de la tensión de cada nodo
def forward(self, data):
out = self.conv1(data.x_dict, data.edge_index_dict)
out = self.conv2(out, data.edge_index_dict)
out = {key: self.fc(val) for key, val in out.items()}
return out
Datos de ejemplo
nodos = 4 # Ejemplo: 4 nodos
caracteristicas_generador = np.random.rand(1, 2) # P, Q para generadores
caracteristicas_consumidor = np.random.rand(2, 2) # P, Q para consumidores
caracteristicas_transformador = np.random.rand(1, 2) # V para transformadores
Definir las conexiones entre los nodos
edge_index_generator_to_consumer = torch.tensor([[0, 0], [1, 2]], dtype=torch.long) # Conexiones de generador a consumidores
edge_index_consumer_to_transformer = torch.tensor([[1, 2], [3, 3]], dtype=torch.long) # Conexiones de consumidores a transformadores
Tensiones reales de cada nodo (estas son las etiquetas de salida)
tensiones_reales = torch.tensor([1.05, 1.02, 1.08, 1.01], dtype=torch.float).view(-1, 1)
Convertir a un formato compatible con PyTorch Geometric HeteroData
data = HeteroData()
Añadir características de los nodos a HeteroData
data[‘generator’].x = torch.tensor(caracteristicas_generador, dtype=torch.float)
data[‘consumer’].x = torch.tensor(caracteristicas_consumidor, dtype=torch.float)
data[‘transformer’].x = torch.tensor(caracteristicas_transformador, dtype=torch.float)
Definir las conexiones entre los nodos (tipos de relaciones entre nodos)
data.edge_index_dict = {
(‘generator’, ‘to’, ‘consumer’): edge_index_generator_to_consumer,
(‘consumer’, ‘to’, ‘transformer’): edge_index_consumer_to_transformer
}
print(“Datos de entrada:\n”, data)
Crear la red neuronal
input_features = 2 # Porque cada nodo tiene 2 características (P y Q para generadores/consumidores, V para transformadores)
output_features = 1 # Predecir la tensión de cada nodo
model = HeteroGNN(input_features, output_features)
Configurar el optimizador y la función de pérdida
optimizer = optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.MSELoss()
Entrenamiento
epochs = 1000
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
out = model(data)
loss = sum(loss_fn(out[key], tensiones_reales) for key in out) / len(out)
loss.backward()
optimizer.step()
if (epoch + 1) % 100 == 0:
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
Evaluación
model.eval()
with torch.no_grad():
prediccion_tensiones = model(data)
print("Tensiones predichas: ", prediccion_tensiones)
print("Tensiones reales: ", tensiones_reales)
Thank you very much for your help and time