基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/majiayu000/claude-skill-registry --skill graph-neural-networks命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
LLM token logprobs and calibration. Per-decision confidence, ECE, Brier, reliability diagrams, low-confidence triage.
Analyze LLM token logprobs and calibration. Use for per-decision confidence, ECE, Brier scores, reliability diagrams, and low-confidence triage.
回顾最近 N 天的 Claude Code 使用记录——扫描原始会话数据,按主题分组汇总"我都做了什么",并从个人操作系统视角输出模式、风险与增删建议。当用户说 /recap、"看看我这几天做了什么"、"回顾一下我最近的会话"、"这两天我用 claude 干了啥"、"活动回顾" 时使用。
| name | graph-neural-networks |
| description | Implement graph neural networks with PyTorch Geometric for node, edge, and graph tasks |
| Architecture | Best For | Key Property | Complexity |
|---|---|---|---|
| GCN | Homogeneous graphs, semi-supervised | Spectral convolution, fixed aggregation | Low |
| GAT | Graphs with varying neighbor importance | Learned attention weights | Medium |
| GraphSAGE | Large graphs, inductive learning | Sampling + aggregation, works on unseen nodes | Medium |
| GIN | Graph classification, WL-test expressiveness | Injective aggregation, maximally powerful | Medium |
| HGT | Heterogeneous graphs, multiple relations | Type-aware attention | High |
| TransE/RotatE | Knowledge graph link prediction | Translation/rotation in embedding space | Low |
| Task | Recommended | Reason |
|---|---|---|
| Node classification | GAT or GraphSAGE | Attention captures varying neighbor relevance |
| Link prediction | GraphSAGE + dot product | Inductive; generalizes to unseen nodes |
| Graph classification | GIN + global pooling | Most expressive message passing for graph-level |
| Heterogeneous | HGT or to_hetero wrapper | Handles multiple node/edge types natively |
| Knowledge graph | RotatE | Handles symmetric, antisymmetric, composition |
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, GATConv, SAGEConv, global_mean_pool
from torch_geometric.data import Data
class GCN(torch.nn.Module):
"""2-layer GCN for node classification."""
def __init__(self, in_ch: int, hidden: int, out_ch: int, dropout: float = 0.5):
super().__init__()
self.conv1 = GCNConv(in_ch, hidden)
self.conv2 = GCNConv(hidden, out_ch)
self.dropout = dropout
def forward(self, x, edge_index):
x = F.dropout(F.relu(self.conv1(x, edge_index)), p=self.dropout, training=self.training)
return self.conv2(x, edge_index) # Raw logits; apply softmax externally
class GAT(torch.nn.Module):
"""Multi-head GAT for node classification."""
def __init__(self, in_ch: int, hidden: int, out_ch: int, heads: int = 8, dropout: float = 0.6):
super().__init__()
self.conv1 = GATConv(in_ch, hidden, heads=heads, dropout=dropout)
.conv2 = GATConv(hidden * heads, out_ch, heads=, concat=, dropout=dropout)
.dropout = dropout
():
x = F.dropout(x, p=.dropout, training=.training)
x = F.elu(.conv1(x, edge_index))
x = F.dropout(x, p=.dropout, training=.training)
.conv2(x, edge_index)
(torch.nn.Module):
():
().__init__()
.convs = torch.nn.ModuleList()
.convs.append(SAGEConv(in_ch, hidden))
_ (num_layers - ):
.convs.append(SAGEConv(hidden, hidden))
.convs.append(SAGEConv(hidden, out_ch))
():
conv .convs[:-]:
x = F.dropout(F.relu(conv(x, edge_index)), p=, training=.training)
.convs[-](x, edge_index)
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops, degree
class CustomMP(MessagePassing):
"""Custom message passing: demonstrates the propagate framework."""
def __init__(self, in_channels: int, out_channels: int):
super().__init__(aggr="add") # "add", "mean", "max"
self.lin = torch.nn.Linear(in_channels, out_channels)
def forward(self, x, edge_index):
edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))
x = self.lin(x)
row, col = edge_index
deg = degree(col, x.size(0), dtype=x.dtype)
deg_inv_sqrt = deg.pow(-0.5)
deg_inv_sqrt[deg_inv_sqrt == float("inf")] = 0
norm = deg_inv_sqrt[row] * deg_inv_sqrt[col]
return self.propagate(edge_index, x=x, norm=norm)
def message(self, x_j, norm):
return norm.view(-1, 1) * x_j # Scale neighbor features
class TransE(torch.nn.Module):
"""TransE: h + r ~ t in embedding space."""
def __init__(self, n_ent: int, n_rel: int, dim: int = 128, margin: float = 1.0):
super().__init__()
self.ent = torch.nn.Embedding(n_ent, dim)
self.rel = torch.nn.Embedding(n_rel, dim)
self.margin = margin
torch.nn.init.xavier_uniform_(self.ent.weight)
torch.nn.init.xavier_uniform_(self.rel.weight)
def score(self, h, r, t):
return torch.norm(self.ent(h) + self.rel(r) - self.ent(t), p=2, dim=-1)
def forward(self, pos_h, pos_r, pos_t, neg_h, neg_r, neg_t):
return F.relu(self.margin + self.score(pos_h, pos_r, pos_t) - self.score(neg_h, neg_r, neg_t)).mean()
class RotatE(torch.nn.Module):
"""RotatE: h * r ~ t via complex rotation."""
def __init__(self, n_ent: int, n_rel: int, dim: int = 128, margin: float = ):
().__init__()
.ent_re = torch.nn.Embedding(n_ent, dim)
.ent_im = torch.nn.Embedding(n_ent, dim)
.rel_phase = torch.nn.Embedding(n_rel, dim)
.margin = margin
():
h_re, h_im = .ent_re(h_idx), .ent_im(h_idx)
t_re, t_im = .ent_re(t_idx), .ent_im(t_idx)
r_re, r_im = torch.cos(.rel_phase(r_idx)), torch.sin(.rel_phase(r_idx))
diff_re = (h_re * r_re - h_im * r_im) - t_re
diff_im = (h_re * r_im + h_im * r_re) - t_im
torch.sqrt(diff_re** + diff_im** + ).(dim=-)
from torch_geometric.data import HeteroData
from torch_geometric.nn import to_hetero
def build_hetero_data():
data = HeteroData()
data["user"].x = torch.randn(1000, 64)
data["item"].x = torch.randn(5000, 128)
data["user", "buys", "item"].edge_index = torch.randint(0, 1000, (2, 10000))
data["user", "rates", "item"].edge_index = torch.randint(0, 1000, (2, 20000))
return data
def create_hetero_model(data: HeteroData, hidden: int = 64, out: int = 32):
model = GraphSAGE(in_ch=-1, hidden=hidden, out_ch=out, num_layers=2)
return to_hetero(model, data.metadata(), aggr="sum") # Separate weights per type
from torch_geometric.loader import NeighborLoader
def train_node_classification(data: Data, model, epochs: int = 50, lr: float = 0.01):
loader = NeighborLoader(
data, num_neighbors=[25, 10], # 25 1-hop, 10 2-hop
batch_size=512, input_nodes=data.train_mask, shuffle=True,
)
optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=5e-4)
model.train()
for epoch in range(epochs):
for batch in loader:
optimizer.zero_grad()
out = model(batch.x, batch.edge_index)
loss = F.cross_entropy(out[:batch.batch_size], batch.y[:batch.batch_size])
loss.backward()
optimizer.step()
return model
from torch_geometric.transforms import RandomLinkSplit
from torch_geometric.utils import negative_sampling
def setup_link_prediction(data: Data):
transform = RandomLinkSplit(num_val=0.1, num_test=0.1,
add_negative_train_samples=True, neg_sampling_ratio=1.0)
return transform(data) # (train, val, test)
def link_prediction_loss(model, data):
z = model(data.x, data.edge_index)
src, dst = data.edge_label_index
pos_score = (z[src] * z[dst]).sum(dim=-1)
neg_edge = negative_sampling(data.edge_index, num_nodes=data.num_nodes, num_neg_samples=src.size(0))
neg_score = (z[neg_edge[0]] * z[neg_edge[1]]).sum(dim=-1)
scores = torch.cat([pos_score, neg_score])
labels = torch.cat([torch.ones(pos_score.size(0)), torch.zeros(neg_score.size(0))])
return F.binary_cross_entropy_with_logits(scores, labels.to(scores.device))
add_self_loops=True); forgetting this drops accuracy 5-15%in_channels=-1RandomLinkSplit handles this automaticallySparseTensor from torch_sparse for >500K edges