[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XFS1WDCS6CQPCEDPWY1Y76":3,"skill-same:01M6XFS1WDCS6CQPCEDPWY1Y76":103},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":55,"commitSha":56,"skillDirectory":57,"forksCount":14,"repositoryHtmlUrl":58,"repositoryHomepageUrl":6,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":60,"install":61,"resources":74},"01M6XFS1WDCS6CQPCEDPWY1Y76","torch-geometric",null,"Graph Neural Networks (PyG). Node\u002Fgraph classification, link prediction, GCN, GAT, GraphSAGE, heterogeneous graphs, molecular property prediction, for geometric deep learning.","fadrienne\u002FMyGitHub","fadrienne","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F197874571?v=4","01M6X64V8VWCRSMFZ4EPS2BWXG","Francesca Adrienne","01M6X64VD5MW4F9PHDWQKS7ZAF",0,"MIT","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"torch geometric","deep","Molecules","prediction","graph neural networks","for","link","synthetic","gat","molecular","graphs","deep learning","Neural","node","coding","learning","classification","networks","graph","neural networks","2026-11-10 10:12:30",false,"---\nname: torch-geometric\ndescription: Graph Neural Networks (PyG). Node\u002Fgraph classification, link prediction, GCN, GAT, GraphSAGE, heterogeneous graphs, molecular property prediction, for geometric deep learning.\ncategory: coding\nlicense: MIT license\nmetadata:\n    skill-author: Synthetic Sciences\nversion: 1.0.0\nauthor: Synthetic Sciences\ntags: [Graph Neural Networks, Deep Learning, Molecules, Networks]\ndependencies: [\"torch-geometric>=2.5.0\", \"torch>=2.0.0\"]\n---\n\n# PyTorch Geometric (PyG)\n\n## Overview\n\nPyTorch Geometric is a library built on PyTorch for developing and training Graph Neural Networks (GNNs). Apply this skill for deep learning on graphs and irregular structures, including mini-batch processing, multi-GPU training, and geometric deep learning applications.\n\n## When to Use This Skill\n\nThis skill should be used when working with:\n- **Graph-based machine learning**: Node classification, graph classification, link prediction\n- **Molecular property prediction**: Drug discovery, chemical property prediction\n- **Social network analysis**: Community detection, influence prediction\n- **Citation networks**: Paper classification, recommendation systems\n- **3D geometric data**: Point clouds, meshes, molecular structures\n- **Heterogeneous graphs**: Multi-type nodes and edges (e.g., knowledge graphs)\n- **Large-scale graph learning**: Neighbor sampling, distributed training\n\n## Quick Start\n\n### Installation\n\n```bash\nuv pip install torch_geometric\n```\n\nFor additional dependencies (sparse operations, clustering):\n```bash\nuv pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https:\u002F\u002Fdata.pyg.org\u002Fwhl\u002Ftorch-${TORCH}+${CUDA}.html\n```\n\n### Basic Graph Creation\n\n```python\nimport torch\nfrom torch_geometric.data import Data\n\n# Create a simple graph with 3 nodes\nedge_index = torch.tensor([[0, 1, 1, 2],  # source nodes\n                           [1, 0, 2, 1]], dtype=torch.long)  # target nodes\nx = torch.tensor([[-1], [0], [1]], dtype=torch.float)  # node features\n\ndata = Data(x=x, edge_index=edge_index)\nprint(f\"Nodes: {data.num_nodes}, Edges: {data.num_edges}\")\n```\n\n### Loading a Benchmark Dataset\n\n```python\nfrom torch_geometric.datasets import Planetoid\n\n# Load Cora citation network\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')\ndata = dataset[0]  # Get the first (and only) graph\n\nprint(f\"Dataset: {dataset}\")\nprint(f\"Nodes: {data.num_nodes}, Edges: {data.num_edges}\")\nprint(f\"Features: {data.num_node_features}, Classes: {dataset.num_classes}\")\n```\n\n## Core Concepts\n\n### Data Structure\n\nPyG represents graphs using the `torch_geometric.data.Data` class with these key attributes:\n\n- **`data.x`**: Node feature matrix `[num_nodes, num_node_features]`\n- **`data.edge_index`**: Graph connectivity in COO format `[2, num_edges]`\n- **`data.edge_attr`**: Edge feature matrix `[num_edges, num_edge_features]` (optional)\n- **`data.y`**: Target labels for nodes or graphs\n- **`data.pos`**: Node spatial positions `[num_nodes, num_dimensions]` (optional)\n- **Custom attributes**: Can add any attribute (e.g., `data.train_mask`, `data.batch`)\n\n**Important**: These attributes are not mandatory—extend Data objects with custom attributes as needed.\n\n### Edge Index Format\n\nEdges are stored in COO (coordinate) format as a `[2, num_edges]` tensor:\n- First row: source node indices\n- Second row: target node indices\n\n```python\n# Edge list: (0→1), (1→0), (1→2), (2→1)\nedge_index = torch.tensor([[0, 1, 1, 2],\n                           [1, 0, 2, 1]], dtype=torch.long)\n```\n\n### Mini-Batch Processing\n\nPyG handles batching by creating block-diagonal adjacency matrices, concatenating multiple graphs into one large disconnected graph:\n\n- Adjacency matrices are stacked diagonally\n- Node features are concatenated along the node dimension\n- A `batch` vector maps each node to its source graph\n- No padding needed—computationally efficient\n\n```python\nfrom torch_geometric.loader import DataLoader\n\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\nfor batch in loader:\n    print(f\"Batch size: {batch.num_graphs}\")\n    print(f\"Total nodes: {batch.num_nodes}\")\n    # batch.batch maps nodes to graphs\n```\n\n## Building Graph Neural Networks\n\n### Message Passing Paradigm\n\nGNNs in PyG follow a neighborhood aggregation scheme:\n1. Transform node features\n2. Propagate messages along edges\n3. Aggregate messages from neighbors\n4. Update node representations\n\n### Using Pre-Built Layers\n\nPyG provides 40+ convolutional layers. Common ones include:\n\n**GCNConv** (Graph Convolutional Network):\n```python\nfrom torch_geometric.nn import GCNConv\nimport torch.nn.functional as F\n\nclass GCN(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 16)\n        self.conv2 = GCNConv(16, num_classes)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = F.dropout(x, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n**GATConv** (Graph Attention Network):\n```python\nfrom torch_geometric.nn import GATConv\n\nclass GAT(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GATConv(num_features, 8, heads=8, dropout=0.6)\n        self.conv2 = GATConv(8 * 8, num_classes, heads=1, concat=False, dropout=0.6)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = F.dropout(x, p=0.6, training=self.training)\n        x = F.elu(self.conv1(x, edge_index))\n        x = F.dropout(x, p=0.6, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n**GraphSAGE**:\n```python\nfrom torch_geometric.nn import SAGEConv\n\nclass GraphSAGE(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = SAGEConv(num_features, 64)\n        self.conv2 = SAGEConv(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = F.dropout(x, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n### Custom Message Passing Layers\n\nFor custom layers, inherit from `MessagePassing`:\n\n```python\nfrom torch_geometric.nn import MessagePassing\nfrom torch_geometric.utils import add_self_loops, degree\n\nclass CustomConv(MessagePassing):\n    def __init__(self, in_channels, out_channels):\n        super().__init__(aggr='add')  # \"add\", \"mean\", or \"max\"\n        self.lin = torch.nn.Linear(in_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        # Add self-loops to adjacency matrix\n        edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))\n\n        # Transform node features\n        x = self.lin(x)\n\n        # Compute normalization\n        row, col = edge_index\n        deg = degree(col, x.size(0), dtype=x.dtype)\n        deg_inv_sqrt = deg.pow(-0.5)\n        norm = deg_inv_sqrt[row] * deg_inv_sqrt[col]\n\n        # Propagate messages\n        return self.propagate(edge_index, x=x, norm=norm)\n\n    def message(self, x_j, norm):\n        # x_j: features of source nodes\n        return norm.view(-1, 1) * x_j\n```\n\nKey methods:\n- **`forward()`**: Main entry point\n- **`message()`**: Constructs messages from source to target nodes\n- **`aggregate()`**: Aggregates messages (usually don't override—set `aggr` parameter)\n- **`update()`**: Updates node embeddings after aggregation\n\n**Variable naming convention**: Appending `_i` or `_j` to tensor names automatically maps them to target or source nodes.\n\n## Working with Datasets\n\n### Loading Built-in Datasets\n\nPyG provides extensive benchmark datasets:\n\n```python\n# Citation networks (node classification)\nfrom torch_geometric.datasets import Planetoid\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')  # or 'CiteSeer', 'PubMed'\n\n# Graph classification\nfrom torch_geometric.datasets import TUDataset\ndataset = TUDataset(root='\u002Ftmp\u002FENZYMES', name='ENZYMES')\n\n# Molecular datasets\nfrom torch_geometric.datasets import QM9\ndataset = QM9(root='\u002Ftmp\u002FQM9')\n\n# Large-scale datasets\nfrom torch_geometric.datasets import Reddit\ndataset = Reddit(root='\u002Ftmp\u002FReddit')\n```\n\nCheck `references\u002Fdatasets_reference.md` for a comprehensive list.\n\n### Creating Custom Datasets\n\nFor datasets that fit in memory, inherit from `InMemoryDataset`:\n\n```python\nfrom torch_geometric.data import InMemoryDataset, Data\nimport torch\n\nclass MyOwnDataset(InMemoryDataset):\n    def __init__(self, root, transform=None, pre_transform=None):\n        super().__init__(root, transform, pre_transform)\n        self.load(self.processed_paths[0])\n\n    @property\n    def raw_file_names(self):\n        return ['my_data.csv']  # Files needed in raw_dir\n\n    @property\n    def processed_file_names(self):\n        return ['data.pt']  # Files in processed_dir\n\n    def download(self):\n        # Download raw data to self.raw_dir\n        pass\n\n    def process(self):\n        # Read data, create Data objects\n        data_list = []\n\n        # Example: Create a simple graph\n        edge_index = torch.tensor([[0, 1], [1, 0]], dtype=torch.long)\n        x = torch.randn(2, 16)\n        y = torch.tensor([0], dtype=torch.long)\n\n        data = Data(x=x, edge_index=edge_index, y=y)\n        data_list.append(data)\n\n        # Apply pre_filter and pre_transform\n        if self.pre_filter is not None:\n            data_list = [d for d in data_list if self.pre_filter(d)]\n\n        if self.pre_transform is not None:\n            data_list = [self.pre_transform(d) for d in data_list]\n\n        # Save processed data\n        self.save(data_list, self.processed_paths[0])\n```\n\nFor large datasets that don't fit in memory, inherit from `Dataset` and implement `len()` and `get(idx)`.\n\n### Loading Graphs from CSV\n\n```python\nimport pandas as pd\nimport torch\nfrom torch_geometric.data import HeteroData\n\n# Load nodes\nnodes_df = pd.read_csv('nodes.csv')\nx = torch.tensor(nodes_df[['feat1', 'feat2']].values, dtype=torch.float)\n\n# Load edges\nedges_df = pd.read_csv('edges.csv')\nedge_index = torch.tensor([edges_df['source'].values,\n                           edges_df['target'].values], dtype=torch.long)\n\ndata = Data(x=x, edge_index=edge_index)\n```\n\n## Training Workflows\n\n### Node Classification (Single Graph)\n\n```python\nimport torch\nimport torch.nn.functional as F\nfrom torch_geometric.datasets import Planetoid\n\n# Load dataset\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')\ndata = dataset[0]\n\n# Create model\nmodel = GCN(dataset.num_features, dataset.num_classes)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)\n\n# Training\nmodel.train()\nfor epoch in range(200):\n    optimizer.zero_grad()\n    out = model(data)\n    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])\n    loss.backward()\n    optimizer.step()\n\n    if epoch % 10 == 0:\n        print(f'Epoch {epoch}, Loss: {loss.item():.4f}')\n\n# Evaluation\nmodel.eval()\npred = model(data).argmax(dim=1)\ncorrect = (pred[data.test_mask] == data.y[data.test_mask]).sum()\nacc = int(correct) \u002F int(data.test_mask.sum())\nprint(f'Test Accuracy: {acc:.4f}')\n```\n\n### Graph Classification (Multiple Graphs)\n\n```python\nfrom torch_geometric.datasets import TUDataset\nfrom torch_geometric.loader import DataLoader\nfrom torch_geometric.nn import global_mean_pool\n\nclass GraphClassifier(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 64)\n        self.conv2 = GCNConv(64, 64)\n        self.lin = torch.nn.Linear(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index, batch = data.x, data.edge_index, data.batch\n\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = self.conv2(x, edge_index)\n        x = F.relu(x)\n\n        # Global pooling (aggregate node features to graph-level)\n        x = global_mean_pool(x, batch)\n\n        x = self.lin(x)\n        return F.log_softmax(x, dim=1)\n\n# Load dataset\ndataset = TUDataset(root='\u002Ftmp\u002FENZYMES', name='ENZYMES')\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\n\nmodel = GraphClassifier(dataset.num_features, dataset.num_classes)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n\n# Training\nmodel.train()\nfor epoch in range(100):\n    total_loss = 0\n    for batch in loader:\n        optimizer.zero_grad()\n        out = model(batch)\n        loss = F.nll_loss(out, batch.y)\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n\n    if epoch % 10 == 0:\n        print(f'Epoch {epoch}, Loss: {total_loss \u002F len(loader):.4f}')\n```\n\n### Large-Scale Graphs with Neighbor Sampling\n\nFor large graphs, use `NeighborLoader` to sample subgraphs:\n\n```python\nfrom torch_geometric.loader import NeighborLoader\n\n# Create a neighbor sampler\ntrain_loader = NeighborLoader(\n    data,\n    num_neighbors=[25, 10],  # Sample 25 neighbors for 1st hop, 10 for 2nd hop\n    batch_size=128,\n    input_nodes=data.train_mask,\n)\n\n# Training\nmodel.train()\nfor batch in train_loader:\n    optimizer.zero_grad()\n    out = model(batch)\n    # Only compute loss on seed nodes (first batch_size nodes)\n    loss = F.nll_loss(out[:batch.batch_size], batch.y[:batch.batch_size])\n    loss.backward()\n    optimizer.step()\n```\n\n**Important**:\n- Output subgraphs are directed\n- Node indices are relabeled (0 to batch.num_nodes - 1)\n- Only use seed node predictions for loss computation\n- Sampling beyond 2-3 hops is generally not feasible\n\n## Advanced Features\n\n### Heterogeneous Graphs\n\nFor graphs with multiple node and edge types, use `HeteroData`:\n\n```python\nfrom torch_geometric.data import HeteroData\n\ndata = HeteroData()\n\n# Add node features for different types\ndata['paper'].x = torch.randn(100, 128)  # 100 papers with 128 features\ndata['author'].x = torch.randn(200, 64)  # 200 authors with 64 features\n\n# Add edges for different types (source_type, edge_type, target_type)\ndata['author', 'writes', 'paper'].edge_index = torch.randint(0, 200, (2, 500))\ndata['paper', 'cites', 'paper'].edge_index = torch.randint(0, 100, (2, 300))\n\nprint(data)\n```\n\nConvert homogeneous models to heterogeneous:\n\n```python\nfrom torch_geometric.nn import to_hetero\n\n# Define homogeneous model\nmodel = GNN(...)\n\n# Convert to heterogeneous\nmodel = to_hetero(model, data.metadata(), aggr='sum')\n\n# Use as normal\nout = model(data.x_dict, data.edge_index_dict)\n```\n\nOr use `HeteroConv` for custom edge-type-specific operations:\n\n```python\nfrom torch_geometric.nn import HeteroConv, GCNConv, SAGEConv\n\nclass HeteroGNN(torch.nn.Module):\n    def __init__(self, metadata):\n        super().__init__()\n        self.conv1 = HeteroConv({\n            ('paper', 'cites', 'paper'): GCNConv(-1, 64),\n            ('author', 'writes', 'paper'): SAGEConv((-1, -1), 64),\n        }, aggr='sum')\n\n        self.conv2 = HeteroConv({\n            ('paper', 'cites', 'paper'): GCNConv(64, 32),\n            ('author', 'writes', 'paper'): SAGEConv((64, 64), 32),\n        }, aggr='sum')\n\n    def forward(self, x_dict, edge_index_dict):\n        x_dict = self.conv1(x_dict, edge_index_dict)\n        x_dict = {key: F.relu(x) for key, x in x_dict.items()}\n        x_dict = self.conv2(x_dict, edge_index_dict)\n        return x_dict\n```\n\n### Transforms\n\nApply transforms to modify graph structure or features:\n\n```python\nfrom torch_geometric.transforms import NormalizeFeatures, AddSelfLoops, Compose\n\n# Single transform\ntransform = NormalizeFeatures()\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora', transform=transform)\n\n# Compose multiple transforms\ntransform = Compose([\n    AddSelfLoops(),\n    NormalizeFeatures(),\n])\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora', transform=transform)\n```\n\nCommon transforms:\n- **Structure**: `ToUndirected`, `AddSelfLoops`, `RemoveSelfLoops`, `KNNGraph`, `RadiusGraph`\n- **Features**: `NormalizeFeatures`, `NormalizeScale`, `Center`\n- **Sampling**: `RandomNodeSplit`, `RandomLinkSplit`\n- **Positional Encoding**: `AddLaplacianEigenvectorPE`, `AddRandomWalkPE`\n\nSee `references\u002Ftransforms_reference.md` for the full list.\n\n### Model Explainability\n\nPyG provides explainability tools to understand model predictions:\n\n```python\nfrom torch_geometric.explain import Explainer, GNNExplainer\n\n# Create explainer\nexplainer = Explainer(\n    model=model,\n    algorithm=GNNExplainer(epochs=200),\n    explanation_type='model',  # or 'phenomenon'\n    node_mask_type='attributes',\n    edge_mask_type='object',\n    model_config=dict(\n        mode='multiclass_classification',\n        task_level='node',\n        return_type='log_probs',\n    ),\n)\n\n# Generate explanation for a specific node\nnode_idx = 10\nexplanation = explainer(data.x, data.edge_index, index=node_idx)\n\n# Visualize\nprint(f'Node {node_idx} explanation:')\nprint(f'Important edges: {explanation.edge_mask.topk(5).indices}')\nprint(f'Important features: {explanation.node_mask[node_idx].topk(5).indices}')\n```\n\n### Pooling Operations\n\nFor hierarchical graph representations:\n\n```python\nfrom torch_geometric.nn import TopKPooling, global_mean_pool\n\nclass HierarchicalGNN(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 64)\n        self.pool1 = TopKPooling(64, ratio=0.8)\n        self.conv2 = GCNConv(64, 64)\n        self.pool2 = TopKPooling(64, ratio=0.8)\n        self.lin = torch.nn.Linear(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index, batch = data.x, data.edge_index, data.batch\n\n        x = F.relu(self.conv1(x, edge_index))\n        x, edge_index, _, batch, _, _ = self.pool1(x, edge_index, None, batch)\n\n        x = F.relu(self.conv2(x, edge_index))\n        x, edge_index, _, batch, _, _ = self.pool2(x, edge_index, None, batch)\n\n        x = global_mean_pool(x, batch)\n        x = self.lin(x)\n        return F.log_softmax(x, dim=1)\n```\n\n## Common Patterns and Best Practices\n\n### Check Graph Properties\n\n```python\n# Undirected check\nfrom torch_geometric.utils import is_undirected\nprint(f\"Is undirected: {is_undirected(data.edge_index)}\")\n\n# Connected components\nfrom torch_geometric.utils import connected_components\nprint(f\"Connected components: {connected_components(data.edge_index)}\")\n\n# Contains self-loops\nfrom torch_geometric.utils import contains_self_loops\nprint(f\"Has self-loops: {contains_self_loops(data.edge_index)}\")\n```\n\n### GPU Training\n\n```python\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\ndata = data.to(device)\n\n# For DataLoader\nfor batch in loader:\n    batch = batch.to(device)\n    # Train...\n```\n\n### Save and Load Models\n\n```python\n# Save\ntorch.save(model.state_dict(), 'model.pth')\n\n# Load\nmodel = GCN(num_features, num_classes)\nmodel.load_state_dict(torch.load('model.pth'))\nmodel.eval()\n```\n\n### Layer Capabilities\n\nWhen choosing layers, consider these capabilities:\n- **SparseTensor**: Supports efficient sparse matrix operations\n- **edge_weight**: Handles one-dimensional edge weights\n- **edge_attr**: Processes multi-dimensional edge features\n- **Bipartite**: Works with bipartite graphs (different source\u002Ftarget dimensions)\n- **Lazy**: Enables initialization without specifying input dimensions\n\nSee the GNN cheatsheet at `references\u002Flayer_capabilities.md`.\n\n## Resources\n\n### Bundled References\n\nThis skill includes detailed reference documentation:\n\n- **`references\u002Flayers_reference.md`**: Complete listing of all 40+ GNN layers with descriptions and capabilities\n- **`references\u002Fdatasets_reference.md`**: Comprehensive dataset catalog organized by category\n- **`references\u002Ftransforms_reference.md`**: All available transforms and their use cases\n- **`references\u002Fapi_patterns.md`**: Common API patterns and coding examples\n\n### Scripts\n\nUtility scripts are provided in `scripts\u002F`:\n\n- **`scripts\u002Fvisualize_graph.py`**: Visualize graph structure using networkx and matplotlib\n- **`scripts\u002Fcreate_gnn_template.py`**: Generate boilerplate code for common GNN architectures\n- **`scripts\u002Fbenchmark_model.py`**: Benchmark model performance on standard datasets\n\nExecute scripts directly or read them for implementation patterns.\n\n### Official Resources\n\n- **Documentation**: https:\u002F\u002Fpytorch-geometric.readthedocs.io\u002F\n- **GitHub**: https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\n- **Tutorials**: https:\u002F\u002Fpytorch-geometric.readthedocs.io\u002Fen\u002Flatest\u002Fget_started\u002Fintroduction.html\n- **Examples**: https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\u002Ftree\u002Fmaster\u002Fexamples\n\n","# PyTorch Geometric (PyG)\n\n## Overview\n\nPyTorch Geometric is a library built on PyTorch for developing and training Graph Neural Networks (GNNs). Apply this skill for deep learning on graphs and irregular structures, including mini-batch processing, multi-GPU training, and geometric deep learning applications.\n\n## When to Use This Skill\n\nThis skill should be used when working with:\n- **Graph-based machine learning**: Node classification, graph classification, link prediction\n- **Molecular property prediction**: Drug discovery, chemical property prediction\n- **Social network analysis**: Community detection, influence prediction\n- **Citation networks**: Paper classification, recommendation systems\n- **3D geometric data**: Point clouds, meshes, molecular structures\n- **Heterogeneous graphs**: Multi-type nodes and edges (e.g., knowledge graphs)\n- **Large-scale graph learning**: Neighbor sampling, distributed training\n\n## Quick Start\n\n### Installation\n\n```bash\nuv pip install torch_geometric\n```\n\nFor additional dependencies (sparse operations, clustering):\n```bash\nuv pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https:\u002F\u002Fdata.pyg.org\u002Fwhl\u002Ftorch-${TORCH}+${CUDA}.html\n```\n\n### Basic Graph Creation\n\n```python\nimport torch\nfrom torch_geometric.data import Data\n\n# Create a simple graph with 3 nodes\nedge_index = torch.tensor([[0, 1, 1, 2],  # source nodes\n                           [1, 0, 2, 1]], dtype=torch.long)  # target nodes\nx = torch.tensor([[-1], [0], [1]], dtype=torch.float)  # node features\n\ndata = Data(x=x, edge_index=edge_index)\nprint(f\"Nodes: {data.num_nodes}, Edges: {data.num_edges}\")\n```\n\n### Loading a Benchmark Dataset\n\n```python\nfrom torch_geometric.datasets import Planetoid\n\n# Load Cora citation network\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')\ndata = dataset[0]  # Get the first (and only) graph\n\nprint(f\"Dataset: {dataset}\")\nprint(f\"Nodes: {data.num_nodes}, Edges: {data.num_edges}\")\nprint(f\"Features: {data.num_node_features}, Classes: {dataset.num_classes}\")\n```\n\n## Core Concepts\n\n### Data Structure\n\nPyG represents graphs using the `torch_geometric.data.Data` class with these key attributes:\n\n- **`data.x`**: Node feature matrix `[num_nodes, num_node_features]`\n- **`data.edge_index`**: Graph connectivity in COO format `[2, num_edges]`\n- **`data.edge_attr`**: Edge feature matrix `[num_edges, num_edge_features]` (optional)\n- **`data.y`**: Target labels for nodes or graphs\n- **`data.pos`**: Node spatial positions `[num_nodes, num_dimensions]` (optional)\n- **Custom attributes**: Can add any attribute (e.g., `data.train_mask`, `data.batch`)\n\n**Important**: These attributes are not mandatory—extend Data objects with custom attributes as needed.\n\n### Edge Index Format\n\nEdges are stored in COO (coordinate) format as a `[2, num_edges]` tensor:\n- First row: source node indices\n- Second row: target node indices\n\n```python\n# Edge list: (0→1), (1→0), (1→2), (2→1)\nedge_index = torch.tensor([[0, 1, 1, 2],\n                           [1, 0, 2, 1]], dtype=torch.long)\n```\n\n### Mini-Batch Processing\n\nPyG handles batching by creating block-diagonal adjacency matrices, concatenating multiple graphs into one large disconnected graph:\n\n- Adjacency matrices are stacked diagonally\n- Node features are concatenated along the node dimension\n- A `batch` vector maps each node to its source graph\n- No padding needed—computationally efficient\n\n```python\nfrom torch_geometric.loader import DataLoader\n\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\nfor batch in loader:\n    print(f\"Batch size: {batch.num_graphs}\")\n    print(f\"Total nodes: {batch.num_nodes}\")\n    # batch.batch maps nodes to graphs\n```\n\n## Building Graph Neural Networks\n\n### Message Passing Paradigm\n\nGNNs in PyG follow a neighborhood aggregation scheme:\n1. Transform node features\n2. Propagate messages along edges\n3. Aggregate messages from neighbors\n4. Update node representations\n\n### Using Pre-Built Layers\n\nPyG provides 40+ convolutional layers. Common ones include:\n\n**GCNConv** (Graph Convolutional Network):\n```python\nfrom torch_geometric.nn import GCNConv\nimport torch.nn.functional as F\n\nclass GCN(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 16)\n        self.conv2 = GCNConv(16, num_classes)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = F.dropout(x, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n**GATConv** (Graph Attention Network):\n```python\nfrom torch_geometric.nn import GATConv\n\nclass GAT(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GATConv(num_features, 8, heads=8, dropout=0.6)\n        self.conv2 = GATConv(8 * 8, num_classes, heads=1, concat=False, dropout=0.6)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = F.dropout(x, p=0.6, training=self.training)\n        x = F.elu(self.conv1(x, edge_index))\n        x = F.dropout(x, p=0.6, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n**GraphSAGE**:\n```python\nfrom torch_geometric.nn import SAGEConv\n\nclass GraphSAGE(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = SAGEConv(num_features, 64)\n        self.conv2 = SAGEConv(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index = data.x, data.edge_index\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = F.dropout(x, training=self.training)\n        x = self.conv2(x, edge_index)\n        return F.log_softmax(x, dim=1)\n```\n\n### Custom Message Passing Layers\n\nFor custom layers, inherit from `MessagePassing`:\n\n```python\nfrom torch_geometric.nn import MessagePassing\nfrom torch_geometric.utils import add_self_loops, degree\n\nclass CustomConv(MessagePassing):\n    def __init__(self, in_channels, out_channels):\n        super().__init__(aggr='add')  # \"add\", \"mean\", or \"max\"\n        self.lin = torch.nn.Linear(in_channels, out_channels)\n\n    def forward(self, x, edge_index):\n        # Add self-loops to adjacency matrix\n        edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))\n\n        # Transform node features\n        x = self.lin(x)\n\n        # Compute normalization\n        row, col = edge_index\n        deg = degree(col, x.size(0), dtype=x.dtype)\n        deg_inv_sqrt = deg.pow(-0.5)\n        norm = deg_inv_sqrt[row] * deg_inv_sqrt[col]\n\n        # Propagate messages\n        return self.propagate(edge_index, x=x, norm=norm)\n\n    def message(self, x_j, norm):\n        # x_j: features of source nodes\n        return norm.view(-1, 1) * x_j\n```\n\nKey methods:\n- **`forward()`**: Main entry point\n- **`message()`**: Constructs messages from source to target nodes\n- **`aggregate()`**: Aggregates messages (usually don't override—set `aggr` parameter)\n- **`update()`**: Updates node embeddings after aggregation\n\n**Variable naming convention**: Appending `_i` or `_j` to tensor names automatically maps them to target or source nodes.\n\n## Working with Datasets\n\n### Loading Built-in Datasets\n\nPyG provides extensive benchmark datasets:\n\n```python\n# Citation networks (node classification)\nfrom torch_geometric.datasets import Planetoid\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')  # or 'CiteSeer', 'PubMed'\n\n# Graph classification\nfrom torch_geometric.datasets import TUDataset\ndataset = TUDataset(root='\u002Ftmp\u002FENZYMES', name='ENZYMES')\n\n# Molecular datasets\nfrom torch_geometric.datasets import QM9\ndataset = QM9(root='\u002Ftmp\u002FQM9')\n\n# Large-scale datasets\nfrom torch_geometric.datasets import Reddit\ndataset = Reddit(root='\u002Ftmp\u002FReddit')\n```\n\nCheck `references\u002Fdatasets_reference.md` for a comprehensive list.\n\n### Creating Custom Datasets\n\nFor datasets that fit in memory, inherit from `InMemoryDataset`:\n\n```python\nfrom torch_geometric.data import InMemoryDataset, Data\nimport torch\n\nclass MyOwnDataset(InMemoryDataset):\n    def __init__(self, root, transform=None, pre_transform=None):\n        super().__init__(root, transform, pre_transform)\n        self.load(self.processed_paths[0])\n\n    @property\n    def raw_file_names(self):\n        return ['my_data.csv']  # Files needed in raw_dir\n\n    @property\n    def processed_file_names(self):\n        return ['data.pt']  # Files in processed_dir\n\n    def download(self):\n        # Download raw data to self.raw_dir\n        pass\n\n    def process(self):\n        # Read data, create Data objects\n        data_list = []\n\n        # Example: Create a simple graph\n        edge_index = torch.tensor([[0, 1], [1, 0]], dtype=torch.long)\n        x = torch.randn(2, 16)\n        y = torch.tensor([0], dtype=torch.long)\n\n        data = Data(x=x, edge_index=edge_index, y=y)\n        data_list.append(data)\n\n        # Apply pre_filter and pre_transform\n        if self.pre_filter is not None:\n            data_list = [d for d in data_list if self.pre_filter(d)]\n\n        if self.pre_transform is not None:\n            data_list = [self.pre_transform(d) for d in data_list]\n\n        # Save processed data\n        self.save(data_list, self.processed_paths[0])\n```\n\nFor large datasets that don't fit in memory, inherit from `Dataset` and implement `len()` and `get(idx)`.\n\n### Loading Graphs from CSV\n\n```python\nimport pandas as pd\nimport torch\nfrom torch_geometric.data import HeteroData\n\n# Load nodes\nnodes_df = pd.read_csv('nodes.csv')\nx = torch.tensor(nodes_df[['feat1', 'feat2']].values, dtype=torch.float)\n\n# Load edges\nedges_df = pd.read_csv('edges.csv')\nedge_index = torch.tensor([edges_df['source'].values,\n                           edges_df['target'].values], dtype=torch.long)\n\ndata = Data(x=x, edge_index=edge_index)\n```\n\n## Training Workflows\n\n### Node Classification (Single Graph)\n\n```python\nimport torch\nimport torch.nn.functional as F\nfrom torch_geometric.datasets import Planetoid\n\n# Load dataset\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora')\ndata = dataset[0]\n\n# Create model\nmodel = GCN(dataset.num_features, dataset.num_classes)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)\n\n# Training\nmodel.train()\nfor epoch in range(200):\n    optimizer.zero_grad()\n    out = model(data)\n    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])\n    loss.backward()\n    optimizer.step()\n\n    if epoch % 10 == 0:\n        print(f'Epoch {epoch}, Loss: {loss.item():.4f}')\n\n# Evaluation\nmodel.eval()\npred = model(data).argmax(dim=1)\ncorrect = (pred[data.test_mask] == data.y[data.test_mask]).sum()\nacc = int(correct) \u002F int(data.test_mask.sum())\nprint(f'Test Accuracy: {acc:.4f}')\n```\n\n### Graph Classification (Multiple Graphs)\n\n```python\nfrom torch_geometric.datasets import TUDataset\nfrom torch_geometric.loader import DataLoader\nfrom torch_geometric.nn import global_mean_pool\n\nclass GraphClassifier(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 64)\n        self.conv2 = GCNConv(64, 64)\n        self.lin = torch.nn.Linear(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index, batch = data.x, data.edge_index, data.batch\n\n        x = self.conv1(x, edge_index)\n        x = F.relu(x)\n        x = self.conv2(x, edge_index)\n        x = F.relu(x)\n\n        # Global pooling (aggregate node features to graph-level)\n        x = global_mean_pool(x, batch)\n\n        x = self.lin(x)\n        return F.log_softmax(x, dim=1)\n\n# Load dataset\ndataset = TUDataset(root='\u002Ftmp\u002FENZYMES', name='ENZYMES')\nloader = DataLoader(dataset, batch_size=32, shuffle=True)\n\nmodel = GraphClassifier(dataset.num_features, dataset.num_classes)\noptimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n\n# Training\nmodel.train()\nfor epoch in range(100):\n    total_loss = 0\n    for batch in loader:\n        optimizer.zero_grad()\n        out = model(batch)\n        loss = F.nll_loss(out, batch.y)\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n\n    if epoch % 10 == 0:\n        print(f'Epoch {epoch}, Loss: {total_loss \u002F len(loader):.4f}')\n```\n\n### Large-Scale Graphs with Neighbor Sampling\n\nFor large graphs, use `NeighborLoader` to sample subgraphs:\n\n```python\nfrom torch_geometric.loader import NeighborLoader\n\n# Create a neighbor sampler\ntrain_loader = NeighborLoader(\n    data,\n    num_neighbors=[25, 10],  # Sample 25 neighbors for 1st hop, 10 for 2nd hop\n    batch_size=128,\n    input_nodes=data.train_mask,\n)\n\n# Training\nmodel.train()\nfor batch in train_loader:\n    optimizer.zero_grad()\n    out = model(batch)\n    # Only compute loss on seed nodes (first batch_size nodes)\n    loss = F.nll_loss(out[:batch.batch_size], batch.y[:batch.batch_size])\n    loss.backward()\n    optimizer.step()\n```\n\n**Important**:\n- Output subgraphs are directed\n- Node indices are relabeled (0 to batch.num_nodes - 1)\n- Only use seed node predictions for loss computation\n- Sampling beyond 2-3 hops is generally not feasible\n\n## Advanced Features\n\n### Heterogeneous Graphs\n\nFor graphs with multiple node and edge types, use `HeteroData`:\n\n```python\nfrom torch_geometric.data import HeteroData\n\ndata = HeteroData()\n\n# Add node features for different types\ndata['paper'].x = torch.randn(100, 128)  # 100 papers with 128 features\ndata['author'].x = torch.randn(200, 64)  # 200 authors with 64 features\n\n# Add edges for different types (source_type, edge_type, target_type)\ndata['author', 'writes', 'paper'].edge_index = torch.randint(0, 200, (2, 500))\ndata['paper', 'cites', 'paper'].edge_index = torch.randint(0, 100, (2, 300))\n\nprint(data)\n```\n\nConvert homogeneous models to heterogeneous:\n\n```python\nfrom torch_geometric.nn import to_hetero\n\n# Define homogeneous model\nmodel = GNN(...)\n\n# Convert to heterogeneous\nmodel = to_hetero(model, data.metadata(), aggr='sum')\n\n# Use as normal\nout = model(data.x_dict, data.edge_index_dict)\n```\n\nOr use `HeteroConv` for custom edge-type-specific operations:\n\n```python\nfrom torch_geometric.nn import HeteroConv, GCNConv, SAGEConv\n\nclass HeteroGNN(torch.nn.Module):\n    def __init__(self, metadata):\n        super().__init__()\n        self.conv1 = HeteroConv({\n            ('paper', 'cites', 'paper'): GCNConv(-1, 64),\n            ('author', 'writes', 'paper'): SAGEConv((-1, -1), 64),\n        }, aggr='sum')\n\n        self.conv2 = HeteroConv({\n            ('paper', 'cites', 'paper'): GCNConv(64, 32),\n            ('author', 'writes', 'paper'): SAGEConv((64, 64), 32),\n        }, aggr='sum')\n\n    def forward(self, x_dict, edge_index_dict):\n        x_dict = self.conv1(x_dict, edge_index_dict)\n        x_dict = {key: F.relu(x) for key, x in x_dict.items()}\n        x_dict = self.conv2(x_dict, edge_index_dict)\n        return x_dict\n```\n\n### Transforms\n\nApply transforms to modify graph structure or features:\n\n```python\nfrom torch_geometric.transforms import NormalizeFeatures, AddSelfLoops, Compose\n\n# Single transform\ntransform = NormalizeFeatures()\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora', transform=transform)\n\n# Compose multiple transforms\ntransform = Compose([\n    AddSelfLoops(),\n    NormalizeFeatures(),\n])\ndataset = Planetoid(root='\u002Ftmp\u002FCora', name='Cora', transform=transform)\n```\n\nCommon transforms:\n- **Structure**: `ToUndirected`, `AddSelfLoops`, `RemoveSelfLoops`, `KNNGraph`, `RadiusGraph`\n- **Features**: `NormalizeFeatures`, `NormalizeScale`, `Center`\n- **Sampling**: `RandomNodeSplit`, `RandomLinkSplit`\n- **Positional Encoding**: `AddLaplacianEigenvectorPE`, `AddRandomWalkPE`\n\nSee `references\u002Ftransforms_reference.md` for the full list.\n\n### Model Explainability\n\nPyG provides explainability tools to understand model predictions:\n\n```python\nfrom torch_geometric.explain import Explainer, GNNExplainer\n\n# Create explainer\nexplainer = Explainer(\n    model=model,\n    algorithm=GNNExplainer(epochs=200),\n    explanation_type='model',  # or 'phenomenon'\n    node_mask_type='attributes',\n    edge_mask_type='object',\n    model_config=dict(\n        mode='multiclass_classification',\n        task_level='node',\n        return_type='log_probs',\n    ),\n)\n\n# Generate explanation for a specific node\nnode_idx = 10\nexplanation = explainer(data.x, data.edge_index, index=node_idx)\n\n# Visualize\nprint(f'Node {node_idx} explanation:')\nprint(f'Important edges: {explanation.edge_mask.topk(5).indices}')\nprint(f'Important features: {explanation.node_mask[node_idx].topk(5).indices}')\n```\n\n### Pooling Operations\n\nFor hierarchical graph representations:\n\n```python\nfrom torch_geometric.nn import TopKPooling, global_mean_pool\n\nclass HierarchicalGNN(torch.nn.Module):\n    def __init__(self, num_features, num_classes):\n        super().__init__()\n        self.conv1 = GCNConv(num_features, 64)\n        self.pool1 = TopKPooling(64, ratio=0.8)\n        self.conv2 = GCNConv(64, 64)\n        self.pool2 = TopKPooling(64, ratio=0.8)\n        self.lin = torch.nn.Linear(64, num_classes)\n\n    def forward(self, data):\n        x, edge_index, batch = data.x, data.edge_index, data.batch\n\n        x = F.relu(self.conv1(x, edge_index))\n        x, edge_index, _, batch, _, _ = self.pool1(x, edge_index, None, batch)\n\n        x = F.relu(self.conv2(x, edge_index))\n        x, edge_index, _, batch, _, _ = self.pool2(x, edge_index, None, batch)\n\n        x = global_mean_pool(x, batch)\n        x = self.lin(x)\n        return F.log_softmax(x, dim=1)\n```\n\n## Common Patterns and Best Practices\n\n### Check Graph Properties\n\n```python\n# Undirected check\nfrom torch_geometric.utils import is_undirected\nprint(f\"Is undirected: {is_undirected(data.edge_index)}\")\n\n# Connected components\nfrom torch_geometric.utils import connected_components\nprint(f\"Connected components: {connected_components(data.edge_index)}\")\n\n# Contains self-loops\nfrom torch_geometric.utils import contains_self_loops\nprint(f\"Has self-loops: {contains_self_loops(data.edge_index)}\")\n```\n\n### GPU Training\n\n```python\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\ndata = data.to(device)\n\n# For DataLoader\nfor batch in loader:\n    batch = batch.to(device)\n    # Train...\n```\n\n### Save and Load Models\n\n```python\n# Save\ntorch.save(model.state_dict(), 'model.pth')\n\n# Load\nmodel = GCN(num_features, num_classes)\nmodel.load_state_dict(torch.load('model.pth'))\nmodel.eval()\n```\n\n### Layer Capabilities\n\nWhen choosing layers, consider these capabilities:\n- **SparseTensor**: Supports efficient sparse matrix operations\n- **edge_weight**: Handles one-dimensional edge weights\n- **edge_attr**: Processes multi-dimensional edge features\n- **Bipartite**: Works with bipartite graphs (different source\u002Ftarget dimensions)\n- **Lazy**: Enables initialization without specifying input dimensions\n\nSee the GNN cheatsheet at `references\u002Flayer_capabilities.md`.\n\n## Resources\n\n### Bundled References\n\nThis skill includes detailed reference documentation:\n\n- **`references\u002Flayers_reference.md`**: Complete listing of all 40+ GNN layers with descriptions and capabilities\n- **`references\u002Fdatasets_reference.md`**: Comprehensive dataset catalog organized by category\n- **`references\u002Ftransforms_reference.md`**: All available transforms and their use cases\n- **`references\u002Fapi_patterns.md`**: Common API patterns and coding examples\n\n### Scripts\n\nUtility scripts are provided in `scripts\u002F`:\n\n- **`scripts\u002Fvisualize_graph.py`**: Visualize graph structure using networkx and matplotlib\n- **`scripts\u002Fcreate_gnn_template.py`**: Generate boilerplate code for common GNN architectures\n- **`scripts\u002Fbenchmark_model.py`**: Benchmark model performance on standard datasets\n\nExecute scripts directly or read them for implementation patterns.\n\n### Official Resources\n\n- **Documentation**: https:\u002F\u002Fpytorch-geometric.readthedocs.io\u002F\n- **GitHub**: https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\n- **Tutorials**: https:\u002F\u002Fpytorch-geometric.readthedocs.io\u002Fen\u002Flatest\u002Fget_started\u002Fintroduction.html\n- **Examples**: https:\u002F\u002Fgithub.com\u002Fpyg-team\u002Fpytorch_geometric\u002Ftree\u002Fmaster\u002Fexamples\n\n",{"name":5,"tags":44,"author":48,"license":49,"version":50,"category":33,"metadata":51,"description":7,"dependencies":52},[45,46,21,47],"Graph Neural Networks","Deep Learning","Networks","Synthetic Sciences","MIT license","1.0.0",{"skill-author":48},[53,54],"torch-geometric>=2.5.0","torch>=2.0.0","main","4aa39efd1cdab0b4657ecee16c92a92011a5b10f","openscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub","https:\u002F\u002Fgithub.com\u002Ffadrienne","2026-10-28 00:43:09",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add fadrienne\u002FMyGitHub --skill torch-geometric",{"tool":67,"command":68},"bunx","bunx skills add fadrienne\u002FMyGitHub --skill torch-geometric",{"tool":70,"command":71},"pnpm","pnpm dlx skills add fadrienne\u002FMyGitHub --skill torch-geometric","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002FSKILL.md",true,[75,81,85,89,95,99],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fdatasets_reference.md","REFERENCE","参考文档",15940,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Freferences\u002Fdatasets_reference.md",{"path":82,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Flayers_reference.md",17121,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Freferences\u002Flayers_reference.md",{"path":86,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":87,"sourceHtmlUrl":88},"references\u002Ftransforms_reference.md",17950,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Freferences\u002Ftransforms_reference.md",{"path":90,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":93,"sourceHtmlUrl":94},"scripts\u002Fbenchmark_model.py","SCRIPT","脚本",10028,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Fscripts\u002Fbenchmark_model.py",{"path":96,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":97,"sourceHtmlUrl":98},"scripts\u002Fcreate_gnn_template.py",15342,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Fscripts\u002Fcreate_gnn_template.py",{"path":100,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":101,"sourceHtmlUrl":102},"scripts\u002Fvisualize_graph.py",10267,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fopenscience\u002Fbackend\u002Fcli\u002Fskills\u002Fcoding\u002Ftorch_geometric\u002Fscripts\u002Fvisualize_graph.py",[104,136,162,195,222,249],{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":115,"publishedAt":39},"01M7167B28PK20HP7R7ZED2DY0","statistical-power","Sample size calculation, power analysis, and effect size conversion for scientific studies. Use BEFORE data collection (a priori) to determine required N, or after (post-hoc) to compute achieved power. Covers parametric tests (t-test, ANOVA, chi-square, proportions, correlation, regression), simulation-based power for complex\u002Fclustered\u002Fnested designs, and power curves. Use this skill when someone asks 'how many samples do I need', 'what is my power', 'what effect size can I detect', or any variant. Pairs with \u002Fexperimental-design (choose design first, then compute power) and \u002Fstatistical-analysis (analyze data after collection).","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fstatistical-power\u002FSKILL.md",[110],{"categoryNo":111,"categoryName":112,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135],"power","statistical power","effect","scipy","regression","choose","design","uv","when","Bash","collection","analysis","calculation","ANOVA","conversion","analyze","t-test","chi-square","simulation","sample",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":145,"publishedAt":39},"01M71677EBCM8EPCE9BZCK8505","statistical-analysis","Guided statistical analysis with test selection and reporting. Use when you need help choosing appropriate tests for your data, assumption checking, power analysis, and APA-formatted results. Best for academic research reporting, test selection guidance. For implementing specific models programmatically use statsmodels.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fstatistical-analysis\u002FSKILL.md",[142],{"categoryNo":143,"categoryName":144,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000008","测试与质量",[127,146,116,147,148,149,124,150,151,152,24,153,154,155,156,157,158,159,160,161],"statistical analysis","academic research","implementing","selection","you","reporting","data","tests","use","with","test","research","results","statsmodels","models","help",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":177,"publishedAt":39},"01M71673R93XAHFH81DBNVNG7H","scientific-writing","Core skill for the deep research and writing tool. Write scientific manuscripts in full paragraphs (never bullet points). Use two-stage process with (1) section outlines with key points using research-lookup then (2) convert to flowing prose. IMRAD structure, citations (APA\u002FAMA\u002FVancouver), figures\u002Ftables, reporting guidelines (CONSORT\u002FSTROBE\u002FPRISMA), for research papers and journal submissions.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fscientific-writing\u002FSKILL.md",[168,171,172],{"categoryNo":169,"categoryName":170,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":111,"categoryName":112,"taxonomyType":113,"taxonomyTypeDesc":114},{"categoryNo":173,"categoryName":174,"taxonomyType":175,"taxonomyTypeDesc":176},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[178,179,180,181,20,182,183,184,185,186,125,187,188,189,190,191,192,193,151,194],"writing","scientific","scientific writing","Citations","deep research","never","papers","journal","false","api","prisma","structure","openrouter","Outlines","core skill","read","features",{"skillNo":196,"name":197,"nameZh":6,"description":198,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":199,"categories":200,"keywords":205,"publishedAt":39},"01M7166ZPKXBF4EBPHVTJPQBB1","scientific-visualization","Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib\u002Fseaborn\u002Fplotly with publication styles. For quick exploration use seaborn or plotly directly.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fscientific-visualization\u002FSKILL.md",[201,204],{"categoryNo":202,"categoryName":203,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":111,"categoryName":112,"taxonomyType":113,"taxonomyTypeDesc":114},[206,179,207,208,209,210,211,212,213,185,124,214,215,216,217,218,219,220,24,221],"visualization","scientific visualization","error","ready","quick","exploration","meta-skill","Meta","safe","plotly","annotations","formatting","Publication","figures","panel","submission",{"skillNo":223,"name":224,"nameZh":6,"description":225,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":226,"categories":227,"keywords":234,"publishedAt":39},"01M7166VXJWQSSC3RQZP60WBGR","research-code","Debug, profile, review, and restructure Python research and analysis code. Use when analysis scripts crash, produce wrong results, run too slowly, or need a correctness review. Covers: reading tracebacks and diagnosing root causes, hypothesis-driven debugging, reviewing code for common statistical\u002Fnumerical errors, profiling data pipelines, improving reproducibility (seeds, environments, determinism), and structuring analysis scripts for sharing. Distinct from \u002Fexploratory-data-analysis (which understands data) and \u002Fstatistical-analysis (which chooses and runs tests) — this skill focuses on the code itself.","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fresearch-code\u002FSKILL.md",[228,231],{"categoryNo":229,"categoryName":230,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000021","资料检索与研究",{"categoryNo":232,"categoryName":233,"taxonomyType":175,"taxonomyTypeDesc":176},"01JBSEEDCAT000000000000030","开发工程师",[235,236,157,237,238,239,240,123,241,124,125,127,242,243,244,245,246,247,193,248],"code","research code","which","memory","data-analysis","errors","debugging","common","review","data pipelines","run","scripts","line","write",{"skillNo":250,"name":251,"nameZh":6,"description":252,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":253,"licenseFileUrl":6,"sourceHtmlUrl":254,"categories":255,"keywords":262,"publishedAt":39},"01M7166CF5HSR7SVZYZFWTDX55","markdown-mermaid-writing","Comprehensive markdown and Mermaid diagram writing skill. Use when creating any scientific document, report, analysis, or visualization. Establishes text-based diagrams as the default documentation standard with full style guides (markdown + mermaid), 24 diagram type references, and 9 document templates.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002Fscientific-agent-skills\u002Fskills\u002Fmarkdown-mermaid-writing\u002FSKILL.md",[256,259,260,261],{"categoryNo":257,"categoryName":258,"taxonomyType":113,"taxonomyTypeDesc":114},"01JBSEEDCAT000000000000002","文档处理",{"categoryNo":169,"categoryName":170,"taxonomyType":113,"taxonomyTypeDesc":114},{"categoryNo":111,"categoryName":112,"taxonomyType":113,"taxonomyTypeDesc":114},{"categoryNo":173,"categoryName":174,"taxonomyType":175,"taxonomyTypeDesc":176},[178,263,264,265,266,267,206,268,269,124,125,127,270,271,272,273,274,275,179,193],"markdown mermaid writing","mermaid","markdown","community","diagrams","project","default","team","guides","text","documentation","references","diagram"]