Skip to content
Back to skills

Torch Geometric

ASecurity

Graph Neural Networks (PyG). Classificação de nós/grafos, predição de links, GCN, GAT, GraphSAGE, grafos heterogêneos, predição de propriedades moleculares, para deep learning geométrico.

  • 11 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added September 8, 2026
datapythongobashnodegitapi

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 7 files and shows the line behind each finding

Scanned September 8, 2026

npx -y skills add artubss/SKILLS-CLAUDE-CODE --skill torch_geometric --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Torch Geometric?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Torch Geometric
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/artubss-torch-geometric/badge)](https://www.skillsdirectory.com/skills/artubss-torch-geometric)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: torch-geometric
description: "Graph Neural Networks (PyG). Classificação de nós/grafos, predição de links, GCN, GAT, GraphSAGE, grafos heterogêneos, predição de propriedades moleculares, para deep learning geométrico."
---

# PyTorch Geometric (PyG)

## Visão Geral

PyTorch Geometric é uma biblioteca construída sobre PyTorch para desenvolvimento e treinamento de Graph Neural Networks (GNNs). Use esta skill para deep learning em grafos e estruturas irregulares, incluindo processamento em mini-batch, treinamento multi-GPU e aplicações de deep learning geométrico.

## Quando Usar Esta Skill

Esta skill deve ser usada ao trabalhar com:
- **Machine learning baseado em grafos**: Classificação de nós, classificação de grafos, predição de links
- **Predição de propriedades moleculares**: Descoberta de fármacos, predição de propriedades químicas
- **Análise de redes sociais**: Detecção de comunidades, predição de influência
- **Redes de citação**: Classificação de papers, sistemas de recomendação
- **Dados geométricos 3D**: Point clouds, malhas, estruturas moleculares
- **Grafos heterogêneos**: Nós e arestas de múltiplos tipos (ex: knowledge graphs)
- **Aprendizado em grafos em larga escala**: Amostragem de vizinhos, treinamento distribuído

## Início Rápido

### Instalação

```bash
uv pip install torch_geometric
```

Para dependências adicionais (operações esparsas, clustering):
```bash
uv pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https://data.pyg.org/whl/torch-${TORCH}+${CUDA}.html
```

### Criação Básica de Grafos

```python
import torch
from torch_geometric.data import Data

# Create a simple graph with 3 nodes
edge_index = torch.tensor([[0, 1, 1, 2],  # source nodes
                           [1, 0, 2, 1]], dtype=torch.long)  # target nodes
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)  # node features

data = Data(x=x, edge_index=edge_index)
print(f"Nodes: {data.num_nodes}, Edges: {data.num_edges}")
```

### Carregamento de Dataset de Benchmark

```python
from torch_geometric.datasets import Planetoid

# Load Cora citation network
dataset = Planetoid(root='/tmp/Cora', name='Cora')
data = dataset[0]  # Get the first (and only) graph

print(f"Dataset: {dataset}")
print(f"Nodes: {data.num_nodes}, Edges: {data.num_edges}")
print(f"Features: {data.num_node_features}, Classes: {dataset.num_classes}")
```

## Conceitos Principais

### Estrutura de Dados

PyG representa grafos usando a classe `torch_geometric.data.Data` com estes atributos principais:

- **`data.x`**: Matriz de features de nós `[num_nodes, num_node_features]`
- **`data.edge_index`**: Conectividade do grafo em formato COO `[2, num_edges]`
- **`data.edge_attr`**: Matriz de features de arestas `[num_edges, num_edge_features]` (opcional)
- **`data.y`**: Labels alvo para nós ou grafos
- **`data.pos`**: Posições espaciais dos nós `[num_nodes, num_dimensions]` (opcional)
- **Atributos customizados**: Você pode adicionar qualquer atributo (ex: `data.train_mask`, `data.batch`)

**Importante**: Esses atributos não são obrigatórios—estenda objetos Data com atributos customizados conforme necessário.

### Formato de Edge Index

Arestas são armazenadas em formato COO (coordinate) como um tensor `[2, num_edges]`:
- Primeira linha: índices dos nós de origem
- Segunda linha: índices dos nós de destino

```python
# Edge list: (0→1), (1→0), (1→2), (2→1)
edge_index = torch.tensor([[0, 1, 1, 2],
                           [1, 0, 2, 1]], dtype=torch.long)
```

### Processamento em Mini-Batch

PyG lida com batching criando matrizes de adjacência block-diagonais, concatenando múltiplos grafos em um grande grafo desconectado:

- Matrizes de adjacência são empilhadas diagonalmente
- Features de nós são concatenadas ao longo da dimensão do nó
- Um vetor `batch` mapeia cada nó ao seu grafo de origem
- Sem necessidade de padding—computacionalmente eficiente

```python
from torch_geometric.loader import DataLoader

loader = DataLoader(dataset, batch_size=32, shuffle=True)
for batch in loader:
    print(f"Batch size: {batch.num_graphs}")
    print(f"Total nodes: {batch.num_nodes}")
    # batch.batch maps nodes to graphs
```

## Construindo Graph Neural Networks

### Paradigma de Message Passing

GNNs em PyG seguem um esquema de agregação de vizinhança:
1. Transformar features de nós
2. Propagar mensagens ao longo das arestas
3. Agregar mensagens dos vizinhos
4. Atualizar representações de nós

### Usando Camadas Pré-Construídas

PyG fornece 40+ camadas convolucionais. As mais comuns incluem:

**GCNConv** (Graph Convolutional Network):
```python
from torch_geometric.nn import GCNConv
import torch.nn.functional as F

class GCN(torch.nn.Module):
    def __init__(self, num_features, num_classes):
        super().__init__()
        self.conv1 = GCNConv(num_features, 16)
        self.conv2 = GCNConv(16, num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)
        return F.log_softmax(x, dim=1)
```

**GATConv** (Graph Attention Network):
```python
from torch_geometric.nn import GATConv

class GAT(torch.nn.Module):
    def __init__(self, num_features, num_classes):
        super().__init__()
        self.conv1 = GATConv(num_features, 8, heads=8, dropout=0.6)
        self.conv2 = GATConv(8 * 8, num_classes, heads=1, concat=False, dropout=0.6)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = F.dropout(x, p=0.6, training=self.training)
        x = F.elu(self.conv1(x, edge_index))
        x = F.dropout(x, p=0.6, training=self.training)
        x = self.conv2(x, edge_index)
        return F.log_softmax(x, dim=1)
```

**GraphSAGE**:
```python
from torch_geometric.nn import SAGEConv

class GraphSAGE(torch.nn.Module):
    def __init__(self, num_features, num_classes):
        super().__init__()
        self.conv1 = SAGEConv(num_features, 64)
        self.conv2 = SAGEConv(64, num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)
        return F.log_softmax(x, dim=1)
```

### Camadas de Message Passing Customizadas

Para camadas customizadas, herde de `MessagePassing`:

```python
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops, degree

class CustomConv(MessagePassing):
    def __init__(self, in_channels, out_channels):
        super().__init__(aggr='add')  # "add", "mean", or "max"
        self.lin = torch.nn.Linear(in_channels, out_channels)

    def forward(self, x, edge_index):
        # Add self-loops to adjacency matrix
        edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))

        # Transform node features
        x = self.lin(x)

        # Compute normalization
        row, col = edge_index
        deg = degree(col, x.size(0), dtype=x.dtype)
        deg_inv_sqrt = deg.pow(-0.5)
        norm = deg_inv_sqrt[row] * deg_inv_sqrt[col]

        # Propagate messages
        return self.propagate(edge_index, x=x, norm=norm)

    def message(self, x_j, norm):
        # x_j: features of source nodes
        return norm.view(-1, 1) * x_j
```

Métodos principais:
- **`forward()`**: Ponto de entrada principal
- **`message()`**: Constrói mensagens dos nós de origem para os de destino
- **`aggregate()`**: Agrega mensagens (geralmente não sobrescreva—defina o parâmetro `aggr`)
- **`update()`**: Atualiza embeddings de nós após agregação

**Convenção de nomenclatura**: Adicionar `_i` ou `_j` aos nomes de tensores mapeia automaticamente para nós de destino ou de origem.

## Trabalhando com Datasets

### Carregando Datasets Incorporados

PyG fornece datasets de benchmark extensivos:

```python
# Citation networks (node classification)
from torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/tmp/Cora', name='Cora')  # or 'CiteSeer', 'PubMed'

# Graph classification
from torch_geometric.datasets import TUDataset
dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')

# Molecular datasets
from torch_geometric.datasets import QM9
dataset = QM9(root='/tmp/QM9')

# Large-scale datasets
from torch_geometric.datasets import Reddit
dataset = Reddit(root='/tmp/Reddit')
```

Verifique `references/datasets_reference.md` para uma lista abrangente.

### Criando Datasets Customizados

Para datasets que cabem em memória, herde de `InMemoryDataset`:

```python
from torch_geometric.data import InMemoryDataset, Data
import torch

class MyOwnDataset(InMemoryDataset):
    def __init__(self, root, transform=None, pre_transform=None):
        super().__init__(root, transform, pre_transform)
        self.load(self.processed_paths[0])

    @property
    def raw_file_names(self):
        return ['my_data.csv']  # Files needed in raw_dir

    @property
    def processed_file_names(self):
        return ['data.pt']  # Files in processed_dir

    def download(self):
        # Download raw data to self.raw_dir
        pass

    def process(self):
        # Read data, create Data objects
        data_list = []

        # Example: Create a simple graph
        edge_index = torch.tensor([[0, 1], [1, 0]], dtype=torch.long)
        x = torch.randn(2, 16)
        y = torch.tensor([0], dtype=torch.long)

        data = Data(x=x, edge_index=edge_index, y=y)
        data_list.append(data)

        # Apply pre_filter and pre_transform
        if self.pre_filter is not None:
            data_list = [d for d in data_list if self.pre_filter(d)]

        if self.pre_transform is not None:
            data_list = [self.pre_transform(d) for d in data_list]

        # Save processed data
        self.save(data_list, self.processed_paths[0])
```

Para datasets grandes que não cabem em memória, herde de `Dataset` e implemente `len()` e `get(idx)`.

### Carregando Grafos de CSV

```python
import pandas as pd
import torch
from torch_geometric.data import HeteroData

# Load nodes
nodes_df = pd.read_csv('nodes.csv')
x = torch.tensor(nodes_df[['feat1', 'feat2']].values, dtype=torch.float)

# Load edges
edges_df = pd.read_csv('edges.csv')
edge_index = torch.tensor([edges_df['source'].values,
                           edges_df['target'].values], dtype=torch.long)

data = Data(x=x, edge_index=edge_index)
```

## Workflows de Treinamento

### Classificação de Nós (Grafo Único)

```python
import torch
import torch.nn.functional as F
from torch_geometric.datasets import Planetoid

# Load dataset
dataset = Planetoid(root='/tmp/Cora', name='Cora')
data = dataset[0]

# Create model
model = GCN(dataset.num_features, dataset.num_classes)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

# Training
model.train()
for epoch in range(200):
    optimizer.zero_grad()
    out = model(data)
    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
    loss.backward()
    optimizer.step()

    if epoch % 10 == 0:
        print(f'Epoch {epoch}, Loss: {loss.item():.4f}')

# Evaluation
model.eval()
pred = model(data).argmax(dim=1)
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
acc = int(correct) / int(data.test_mask.sum())
print(f'Test Accuracy: {acc:.4f}')
```

### Classificação de Grafos (Múltiplos Grafos)

```python
from torch_geometric.datasets import TUDataset
from torch_geometric.loader import DataLoader
from torch_geometric.nn import global_mean_pool

class GraphClassifier(torch.nn.Module):
    def __init__(self, num_features, num_classes):
        super().__init__()
        self.conv1 = GCNConv(num_features, 64)
        self.conv2 = GCNConv(64, 64)
        self.lin = torch.nn.Linear(64, num_classes)

    def forward(self, data):
        x, edge_index, batch = data.x, data.edge_index, data.batch

        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = self.conv2(x, edge_index)
        x = F.relu(x)

        # Global pooling (aggregate node features to graph-level)
        x = global_mean_pool(x, batch)

        x = self.lin(x)
        return F.log_softmax(x, dim=1)

# Load dataset
dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')
loader = DataLoader(dataset, batch_size=32, shuffle=True)

model = GraphClassifier(dataset.num_features, dataset.num_classes)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

# Training
model.train()
for epoch in range(100):
    total_loss = 0
    for batch in loader:
        optimizer.zero_grad()
        out = model(batch)
        loss = F.nll_loss(out, batch.y)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()

    if epoch % 10 == 0:
        print(f'Epoch {epoch}, Loss: {total_loss / len(loader):.4f}')
```

### Grafos em Larga Escala com Amostragem de Vizinhos

Para grafos grandes, use `NeighborLoader` para amostrar subgrafos:

```python
from torch_geometric.loader import NeighborLoader

# Create a neighbor sampler
train_loader = NeighborLoader(
    data,
    num_neighbors=[25, 10],  # Sample 25 neighbors for 1st hop, 10 for 2nd hop
    batch_size=128,
    input_nodes=data.train_mask,
)

# Training
model.train()
for batch in train_loader:
    optimizer.zero_grad()
    out = model(batch)
    # Only compute loss on seed nodes (first batch_size nodes)
    loss = F.nll_loss(out[:batch.batch_size], batch.y[:batch.batch_size])
    loss.backward()
    optimizer.step()
```

**Importante**:
- Subgrafos de saída são direcionados
- Índices de nós são renomeados (0 a batch.num_nodes - 1)
- Use apenas predições de nós seed para computar a perda
- Amostragem além de 2-3 saltos geralmente não é viável

## Funcionalidades Avançadas

### Grafos Heterogêneos

Para grafos com múltiplos tipos de nós e arestas, use `HeteroData`:

```python
from torch_geometric.data import HeteroData

data = HeteroData()

# Add node features for different types
data['paper'].x = torch.randn(100, 128)  # 100 papers with 128 features
data['author'].x = torch.randn(200, 64)  # 200 authors with 64 features

# Add edges for different types (source_type, edge_type, target_type)
data['author', 'writes', 'paper'].edge_index = torch.randint(0, 200, (2, 500))
data['paper', 'cites', 'paper'].edge_index = torch.randint(0, 100, (2, 300))

print(data)
```

Converta modelos homogêneos para heterogêneos:

```python
from torch_geometric.nn import to_hetero

# Define homogeneous model
model = GNN(...)

# Convert to heterogeneous
model = to_hetero(model, data.metadata(), aggr='sum')

# Use as normal
out = model(data.x_dict, data.edge_index_dict)
```

Ou use `HeteroConv` para operações customizadas específicas do tipo de aresta:

```python
from torch_geometric.nn import HeteroConv, GCNConv, SAGEConv

class HeteroGNN(torch.nn.Module):
    def __init__(self, metadata):
        super().__init__()
        self.conv1 = HeteroConv({
            ('paper', 'cites', 'paper'): GCNConv(-1, 64),
            ('author', 'writes', 'paper'): SAGEConv((-1, -1), 64),
        }, aggr='sum')

        self.conv2 = HeteroConv({
            ('paper', 'cites', 'paper'): GCNConv(64, 32),
            ('author', 'writes', 'paper'): SAGEConv((64, 64), 32),
        }, aggr='sum')

    def forward(self, x_dict, edge_index_dict):
        x_dict = self.conv1(x_dict, edge_index_dict)
        x_dict = {key: F.relu(x) for key, x in x_dict.items()}
        x_dict = self.conv2(x_dict, edge_index_dict)
        return x_dict
```

### Transforms

Aplique transforms para modificar estrutura ou features do grafo:

```python
from torch_geometric.transforms import NormalizeFeatures, AddSelfLoops, Compose

# Single transform
transform = NormalizeFeatures()
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=transform)

# Compose multiple transforms
transform = Compose([
    AddSelfLoops(),
    NormalizeFeatures(),
])
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=transform)
```

Transforms comuns:
- **Estrutura**: `ToUndirected`, `AddSelfLoops`, `RemoveSelfLoops`, `KNNGraph`, `RadiusGraph`
- **Features**: `NormalizeFeatures`, `NormalizeScale`, `Center`
- **Amostragem**: `RandomNodeSplit`, `RandomLinkSplit`
- **Positional Encoding**: `AddLaplacianEigenvectorPE`, `AddRandomWalkPE`

Veja `references/transforms_reference.md` para a lista completa.

### Explicabilidade de Modelo

PyG fornece ferramentas de explicabilidade para entender predições do modelo:

```python
from torch_geometric.explain import Explainer, GNNExplainer

# Create explainer
explainer = Explainer(
    model=model,
    algorithm=GNNExplainer(epochs=200),
    explanation_type='model',  # or 'phenomenon'
    node_mask_type='attributes',
    edge_mask_type='object',
    model_config=dict(
        mode='multiclass_classification',
        task_level='node',
        return_type='log_probs',
    ),
)

# Generate explanation for a specific node
node_idx = 10
explanation = explainer(data.x, data.edge_index, index=node_idx)

# Visualize
print(f'Node {node_idx} explanation:')
print(f'Important edges: {explanation.edge_mask.topk(5).indices}')
print(f'Important features: {explanation.node_mask[node_idx].topk(5).indices}')
```

### Operações de Pooling

Para representações hierárquicas de grafos:

```python
from torch_geometric.nn import TopKPooling, global_mean_pool

class HierarchicalGNN(torch.nn.Module):
    def __init__(self, num_features, num_classes):
        super().__init__()
        self.conv1 = GCNConv(num_features, 64)
        self.pool1 = TopKPooling(64, ratio=0.8)
        self.conv2 = GCNConv(64, 64)
        self.pool2 = TopKPooling(64, ratio=0.8)
        self.lin = torch.nn.Linear(64, num_classes)

    def forward(self, data):
        x, edge_index, batch = data.x, data.edge_index, data.batch

        x = F.relu(self.conv1(x, edge_index))
        x, edge_index, _, batch, _, _ = self.pool1(x, edge_index, None, batch)

        x = F.relu(self.conv2(x, edge_index))
        x, edge_index, _, batch, _, _ = self.pool2(x, edge_index, None, batch)

        x = global_mean_pool(x, batch)
        x = self.lin(x)
        return F.log_softmax(x, dim=1)
```

## Padrões Comuns e Melhores Práticas

### Verificar Propriedades do Grafo

```python
# Undirected check
from torch_geometric.utils import is_undirected
print(f"Is undirected: {is_undirected(data.edge_index)}")

# Connected components
from torch_geometric.utils import connected_components
print(f"Connected components: {connected_components(data.edge_index)}")

# Contains self-loops
from torch_geometric.utils import contains_self_loops
print(f"Has self-loops: {contains_self_loops(data.edge_index)}")
```

### Treinamento em GPU

```python
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
data = data.to(device)

# For DataLoader
for batch in loader:
    batch = batch.to(device)
    # Train...
```

### Salvar e Carregar Modelos

```python
# Save
torch.save(model.state_dict(), 'model.pth')

# Load
model = GCN(num_features, num_classes)
model.load_state_dict(torch.load('model.pth'))
model.eval()
```

### Capacidades de Camadas

Ao escolher camadas, considere essas capacidades:
- **SparseTensor**: Suporta operações eficientes com matrizes esparsas
- **edge_weight**: Lida com pesos de arestas unidimensionais
- **edge_attr**: Processa features de arestas multidimensionais
- **Bipartite**: Funciona com grafos bipartidos (dimensões diferentes de origem/destino)
- **Lazy**: Habilita inicialização sem especificar dimensões de entrada

Veja o cheatsheet de GNN em `references/layer_capabilities.md`.

## Recursos

### Referências Incluídas

Esta skill inclui documentação de referência detalhada:

- **`references/layers_reference.md`**: Listagem completa de todos os 40+ layers de GNN com descrições e capacidades
- **`references/datasets_reference.md`**: Catálogo abrangente de datasets organizado por categoria
- **`references/transforms_reference.md`**: Todos os transforms disponíveis e seus casos de uso
- **`references/api_patterns.md`**: Padrões comuns de API e exemplos de código

### Scripts

Scripts de utilidade são fornecidos em `scripts/`:

- **`scripts/visualize_graph.py`**: Visualiza estrutura do grafo usando networkx e matplotlib
- **`scripts/create_gnn_template.py`**: Gera código boilerplate para arquiteturas GNN comuns
- **`scripts/benchmark_model.py`**: Benchmarks de desempenho do modelo em datasets padrão

Execute scripts diretamente ou leia-os para padrões de implementação.

### Recursos Oficiais

- **Documentação**: https://pytorch-geometric.readthedocs.io/
- **GitHub**: https://github.com/pyg-team/pytorch_geometric
- **Tutorials**: https://pytorch-geometric.readthedocs.io/en/latest/get_started/introduction.html
- **Examples**: https://github.com/pyg-team/pytorch_geometric/tree/master/examples

Files in this skill

  • SKILL.md20.6 KB
  • references/datasets_reference.md15.6 KB
  • references/layers_reference.md16.7 KB
  • references/transforms_reference.md17.5 KB
  • scripts/benchmark_model.py9.8 KB
  • scripts/create_gnn_template.py15 KB
  • scripts/visualize_graph.py10 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in data →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.