Pytorch Geometric: «from_networkx» не работает с моим «group_node_attrs»

Я пытаюсь преобразовать график NetwrokX в формат pyg, чтобы передать его в GCN.

      from_networkx(G) works without problems

from_networkx(G, group_node_attrs=x) # doesn't work, and I get the following error:

Здесь документация о том, как работает функция from_networkx: https://pytorch-geometric.readthedocs.io/en/latest/_modules/torch_geometric/utils/convert.html

Трассировка (последний последний вызов): Файл "/home/iris/PycharmProjects/GNN/input_preprocessing.py", строка 161, в pyg_graph1 = from_networkx(G1, group_node_attrs=x_1_str) Файл "/home/iris/venv/GNN/lib/python3.10/site-packages/torch_geometric/utils/convert.py", строка 262, в from_networkx x = data[key] File "/home/iris/venv/GNN/lib/python3.10/site-packages/ torch_geometric/data/data.py", строка 444, в getitem return self._store[key] File "/home/iris/venv/GNN/lib/python3.10/site-packages/torch_geometric/data/storage.py" , строка 85, в getitem return self._mapping[key] TypeError: unhashable type: 'list'

Вот пример (исходный x на самом деле длиннее, каждый список состоит из 768 dim, но здесь короче для общего представления):

      import networkx as nx
from torch_geometric.utils.convert import from_networkx
from torch_geometric.data import Data
from torch_geometric.loader import DataLoader

nodes= ['1', '5', '28']
edges= [('1', '5'), ('5', '28')]

G = nx.DiGraph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)

x=[['0.7844669818878174', '-0.40328940749168396', '-0.9366764426231384'],['0.14061762392520905', '-1.1449155807495117', '-0.1811756044626236'],['-1.8840126991271973', '-1.2096494436264038', '1.0780194997787476']]

pyg_graph = from_networkx(G, group_node_attrs=x)

Формат моего списка функций неверен, но я не знаю, в какой форме он должен работать.

Я попытался изменить формат элементов elements вложенного списка функций с str на int, но это не проблема.

Заранее большое спасибо!

1 ответ

Здесь есть ряд проблем (цитата из документации , # <--- вставки мои):

       def from_networkx(
    G: Any,
    group_node_attrs: Optional[Union[List[str], all]] = None,
    group_edge_attrs: Optional[Union[List[str], all]] = None,
) -> 'torch_geometric.data.Data':
    r"""Converts a :obj:`networkx.Graph` or :obj:`networkx.DiGraph` to a
    :class:`torch_geometric.data.Data` instance.

    Args:
        G (networkx.Graph or networkx.DiGraph): A networkx graph.
        group_node_attrs (List[str] or all, optional): The node attributes to # <---- (point 1)
            be concatenated and added to  :obj:`data.x`. (default: :obj:`None`) # <----
        group_edge_attrs (List[str] or all, optional): The edge attributes to
            be concatenated and added to :obj:`data.edge_attr`.
            (default: :obj:`None`)

    .. note::

        All :attr:`group_node_attrs` and :attr:`group_edge_attrs` values must
        be numeric. # <-- point 2

[...]

  1. Вы пытаетесь добавить атрибуты узла в граф pyg при его создании. Функция from_networkx ожидает, что атрибуты узла уже присутствуют в исходном графе networkx, который она объединяет в один массив и добавляет к атрибутам узла. Атрибуты узла, которые присутствуют в вашем nx-графе, но которые вы явно не группируете, по-прежнему добавляются в граф PyG, но как набор массивов с именами атрибутов, которые они имеют в nx-графе.
  2. тип данных в ваших атрибутах - str, это должен быть какой-то числовой тип, иначе библиотека не знает, что с ним делать.

Чтобы исправить эти ошибки, я взял ваш код и дополнил его.

      import networkx as nx
from torch_geometric.utils.convert import from_networkx
from torch_geometric.data import Data
from torch_geometric.loader import DataLoader


edges= [('1', '5'), ('5', '28')]


nodes= ['1', '5', '28']
x=[['0.7844669818878174', '-0.40328940749168396', '-0.9366764426231384'],['0.14061762392520905', '-1.1449155807495117', '-0.1811756044626236'],['-1.8840126991271973', '-1.2096494436264038', '1.0780194997787476']]

# make a dedicated node list, which assigns nodes to their attributes
# and ensures proper data types.
node_list = []
for node, features in zip(nodes, x):
    node_list.append((node, {str(a):float(b) for a, b in enumerate(features)}))

G = nx.DiGraph()
G.add_nodes_from(node_list) # now the attributes are part of the original nx-graph
G.add_edges_from(edges)

pyg_graph = from_networkx(G, group_node_attrs=['0', '1', '2'])

print(pyg_graph.x)

выход:

      tensor([[ 0.7845, -0.4033, -0.9367],
        [ 0.1406, -1.1449, -0.1812],
        [-1.8840, -1.2096,  1.0780]])
Другие вопросы по тегам