This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-doc.git
The following commit(s) were added to refs/heads/master by this push:
new f84516469 doc(ai): sync hugegraph-ml with main (#482)
f84516469 is described below
commit f845164690a4dab2f5041b94f20b9d7c9701c8e6
Author: KAI <[email protected]>
AuthorDate: Sun Sep 6 20:07:22 2026 +0530
doc(ai): sync hugegraph-ml with main (#482)
Rebuild the Implemented Models table from src/hugegraph_ml/models/ so it
lists every module, its entry class and its paper, including GIN and
MLPClassifier. Correct the BGNN row: the bundled example runs regression
over tabular node features, not fraud detection.
Add sections for the HugeGraph2DGL conversion methods, the dataset
importers and the datasets each accepts, the task classes and their
entry points, and the runnable example scripts. Record the ML dependency
pins from the root constraint-dependencies block, and add troubleshooting
entries for the missing node attributes error, the unsupported dataset
error, the bgrl_example MLP_Predictor import mismatch and the missing
CARE-GNN dataset importer.
---
.../docs/quickstart/hugegraph-ai/hugegraph-ml.md | 163 +++++++++++++++++++--
.../docs/quickstart/hugegraph-ai/hugegraph-ml.md | 163 +++++++++++++++++++--
2 files changed, 298 insertions(+), 28 deletions(-)
diff --git a/content/cn/docs/quickstart/hugegraph-ai/hugegraph-ml.md
b/content/cn/docs/quickstart/hugegraph-ai/hugegraph-ml.md
index a53281a0f..da8e67f52 100644
--- a/content/cn/docs/quickstart/hugegraph-ai/hugegraph-ml.md
+++ b/content/cn/docs/quickstart/hugegraph-ai/hugegraph-ml.md
@@ -4,7 +4,7 @@ linkTitle: "HugeGraph-ML"
weight: 2
---
-HugeGraph-ML 从 HugeGraph 读取图数据并转换为 DGL 图,供节点嵌入、节点分类和图分类等任务使用。模型实现位于
`hugegraph-ml/src/hugegraph_ml/models/`。
+HugeGraph-ML 从 HugeGraph 读取图数据并转换为 DGL 图,供节点嵌入、节点分类、图分类、链接预测和欺诈检测等任务使用。模型实现位于
`hugegraph-ml/src/hugegraph_ml/models/`。
## 环境要求
@@ -12,6 +12,23 @@ HugeGraph-ML 从 HugeGraph 读取图数据并转换为 DGL 图,供节点嵌入
- HugeGraph Server 1.0 或更高版本,推荐 1.5 及以上版本
- `uv` 0.7 或更高版本
+所有服务端访问都通过同一仓库中的 `hugegraph-python-client`(即 `pyhugegraph`
包)完成。`HugeGraph2DGL` 使用 Gremlin 接口的 `g.V().hasLabel(...)` 和
`g.E().hasLabel(...)` 拉取点边,数据集导入函数则通过 schema 接口和顶点、边的批量接口写入,每批 500 条。
+
+ML 依赖在仓库根目录的 `[tool.uv] constraint-dependencies` 中固定版本:
+
+| 依赖 | 版本约束 |
+|---|---|
+| `torch` | `==2.2.0` |
+| `dgl` | `~=2.1.0` |
+| `ogb` | `~=1.3.6` |
+| `torchdata` | `~=0.7.0` |
+| `catboost` | `~=1.2.3` |
+| `category-encoders` | `~=2.6.3` |
+| `numpy` | `~=1.24.4` |
+| `pandas` | `~=2.2.3` |
+
+上述约束安装的是 CPU 版本。每个任务都有 `gpu` 参数,默认值 `-1` 表示使用 CPU;只有自行安装 CUDA 版的 `torch` 和
`dgl` 之后,才可以传入设备编号。
+
## 安装
```bash
@@ -26,22 +43,136 @@ HugeGraph-ML 是根项目的路径依赖,但不属于 `uv` workspace members
## 已实现模型
-当前 README 列出的模型如下:
+下列模块均位于 `hugegraph-ml/src/hugegraph_ml/models/`。`models/__init__.py`
不做任何再导出,需要直接从模块文件导入。
+
+| 模型 | 模块 | 入口类 | 用途 | 论文 |
+|---|---|---|---|---|
+| AGNN | `agnn.py` | `AGNN` | 节点分类 |
[1803.03735](https://arxiv.org/abs/1803.03735) |
+| APPNP | `appnp.py` | `APPNP` | 节点分类 |
[1810.05997](https://arxiv.org/abs/1810.05997) |
+| ARMA | `arma.py` | `ARMA4NC` | 节点分类 |
[1901.01343](https://arxiv.org/abs/1901.01343) |
+| BGNN | `bgnn.py` | `BGNNPredictor` | 梯度提升与 GNN 结合处理节点特征,自带示例执行回归任务 |
[2101.08543](https://arxiv.org/abs/2101.08543) |
+| BGRL | `bgrl.py` | `BGRL` | 自监督节点嵌入 |
[2102.06514](https://arxiv.org/abs/2102.06514) |
+| CARE-GNN | `care_gnn.py` | `CAREGNN` | 欺诈检测 |
[2008.08692](https://arxiv.org/abs/2008.08692) |
+| Cluster-GCN | `cluster_gcn.py` | `SAGE` | 基于子图采样的节点分类 |
[1905.07953](https://arxiv.org/abs/1905.07953) |
+| C&S | `correct_and_smooth.py` | `MLP`、`CorrectAndSmooth`、`LabelPropagation`
| 对基础预测结果做校正与平滑 | [2010.13993](https://arxiv.org/abs/2010.13993) |
+| DAGNN | `dagnn.py` | `DAGNN` | 节点分类 |
[2007.09296](https://arxiv.org/abs/2007.09296) |
+| DeeperGCN | `deepergcn.py` | `DeeperGCN` | 带边特征的节点分类 |
[2006.07739](https://arxiv.org/abs/2006.07739) |
+| DGI | `dgi.py` | `DGI` | 自监督节点嵌入 |
[1809.10341](https://arxiv.org/abs/1809.10341) |
+| DiffPool | `diffpool.py` | `DiffPool` | 图分类 |
[1806.08804](https://arxiv.org/abs/1806.08804) |
+| GATNE | `gatne.py` | `DGLGATNE` | 异构网络嵌入 |
[1905.01669](https://arxiv.org/abs/1905.01669) |
+| GIN | `gin_global_pool.py` | `GIN` | 图分类 | |
+| GRACE | `grace.py` | `GRACE` | 自监督节点嵌入 |
[2006.04131](https://arxiv.org/abs/2006.04131) |
+| GRAND | `grand.py` | `GRAND` | 节点分类 |
[2005.11079](https://arxiv.org/abs/2005.11079) |
+| JKNet | `jknet.py` | `JKNet` | 节点分类 |
[1806.03536](https://arxiv.org/abs/1806.03536) |
+| MLP | `mlp.py` | `MLPClassifier` | 基于已学习嵌入的下游分类器 | |
+| P-GNN | `pgnn.py` | `PGNN` | 链接预测 |
[you19b](http://proceedings.mlr.press/v97/you19b/you19b.pdf) |
+| SEAL | `seal.py` | `DGCNN`、`SEALData` | 链接预测 |
[1802.09691](https://arxiv.org/abs/1802.09691) |
+
+`GIN` 的 `pooling` 参数可取 `sum`(默认)、`mean`、`max`、`global_attention` 和 `set2set`。
+
+## 读取图数据
+
+`hugegraph-ml/src/hugegraph_ml/data/hugegraph2dgl.py` 中的 `HugeGraph2DGL` 会创建
`PyHugeClient`,并把查询结果转换为 DGL 对象:
-| 模型 | 主要用途 |
-|---|---|
-| AGNN、APPNP、ARMA、Cluster-GCN、DAGNN、DeeperGCN、GRAND、JKNet | 节点分类 |
-| BGNN、CARE-GNN | 欺诈检测 |
-| BGRL、DGI、GRACE | 表示学习 |
-| DiffPool | 图分类 |
-| GATNE、P-GNN、SEAL | 链接预测或网络嵌入 |
-| C&S | 预测结果校正与平滑 |
+```python
+from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
+
+hg2d = HugeGraph2DGL(
+ url="http://127.0.0.1:8080",
+ graph="hugegraph",
+ user="",
+ pwd="",
+ graphspace=None,
+)
+```
+
+| 方法 | 返回值 | 说明 |
+|---|---|---|
+| `convert_graph(vertex_label, edge_label, feat_key="feat", label_key="label",
mask_keys=None)` | `dgl.DGLGraph` | `mask_keys` 为空时取 `["train_mask",
"val_mask", "test_mask"]` |
+| `convert_hetero_graph(vertex_labels, edge_labels, feat_key="feat",
label_key="label", mask_keys=None)` | DGL 异构图 | 参数为标签列表 |
+| `convert_graph_dataset(graph_vertex_label, vertex_label, edge_label,
feat_key="feat", label_key="label")` | `HugeGraphDataset` | `info` 中写入
`n_graphs`、`max_n_nodes`、`n_feat_dim`、`n_classes` |
+| `convert_graph_nx(vertex_label, edge_label)` | `networkx.Graph` | P-GNN 使用 |
+| `convert_graph_with_edge_feat(vertex_label, edge_label,
node_feat_key="feat", edge_feat_key="edge_feat", label_key="label",
mask_keys=None)` | `dgl.DGLGraph` | 同时填充 `edata["feat"]` |
+| `convert_graph_ogb(vertex_label, edge_label, split_label)` | `(dgl.DGLGraph,
split_edge)` | SEAL 使用 |
+| `convert_hetero_graph_bgnn(vertex_labels, edge_labels, feat_key="feat",
label_key="class", cat_key="cat_features", mask_keys=None)` | DGL 异构图 | BGNN 使用
|
+
+节点特征写入 `ndata["feat"]`,标签写入 `ndata["label"]`,各掩码写入 `ndata[<mask
key>]`。`NodeEmbed` 只要求 `feat`;`NodeClassify`、`NodeClassifyWithEdge` 和
`NodeClassifyWithSample` 要求 `feat`、`label`、`train_mask`、`val_mask` 和
`test_mask`,缺少任意一项都会抛出 `ValueError`。
+
+## 导入示例数据集
+
+`hugegraph_ml.utils.dgl2hugegraph_utils` 负责把 DGL、OGB 和 NetworkX 数据集写入
HugeGraph,供转换层读取。这些函数都接受与 `HugeGraph2DGL` 相同的 `url`、`graph`、`user`、`pwd` 和
`graphspace` 参数,并且多数会先把数据集名转为大写再匹配。
+
+| 函数 | 支持的数据集 | 创建的标签 |
+|---|---|---|
+| `import_graph_from_dgl` | `CORA`、`CITESEER`、`PUBMED` |
`<NAME>_vertex`、`<NAME>_edge` |
+| `import_graphs_from_dgl` |
`MUTAG`、`COLLAB`、`NCI1`、`PROTEINS`、`PTC`、`ENZYMES`、`DD` |
`<NAME>_graph_vertex`、`<NAME>_vertex`、`<NAME>_edge` |
+| `import_hetero_graph_from_dgl` | `ACM` |
`<NAME>_<ntype>_v`、`<NAME>_<etype>_e` |
+| `import_hetero_graph_from_dgl_no_feat` | `AMAZONGATNE` |
`<NAME>_<ntype>_v`、`<NAME>_<etype>_e` |
+| `import_hetero_graph_from_dgl_bgnn` | `AVAZU` |
`<NAME>_<ntype>_v`、`<NAME>_<etype>_e` |
+| `import_graph_from_nx` | `CAVEMAN` | `<NAME>_vertex`、`<NAME>_edge` |
+| `import_graph_from_dgl_with_edge_feat` | `CORA`、`CITESEER`、`PUBMED` |
`<NAME>_edge_feat_vertex`、`<NAME>_edge_feat_edge` |
+| `import_graph_from_ogb` | `ogbl-collab`,不做大写转换 |
`<NAME>_vertex`、`<NAME>_edge` |
+| `import_split_edge_from_ogb` | `ogbl-collab`,不做大写转换 | `<NAME>_split_edge` |
+
+传入其他名称会抛出 `ValueError("dataset not supported")`。`import_split_edge_from_ogb`
还需要顶点导入返回的 `idx_to_vertex_id` 映射和 `max_nodes` 上限。
+
+`clear_all_data()` 会清空目标图中的全部点和边。测试 fixture 先调用它,再导入 `CORA`、`MUTAG` 和
`ACM`,结束时再次调用。
+
+`AMAZONGATNE` 和 `AVAZU` 不会自动下载,压缩包地址写在 `import_hetero_graph_from_dgl_no_feat`
和 `import_hetero_graph_from_dgl_bgnn` 上方的注释里。
+
+## 任务
+
+任务类位于 `hugegraph-ml/src/hugegraph_ml/tasks/`,均接收转换后的图和模型实例。
+
+| 类 | 模块 | 入口方法 |
+|---|---|---|
+| `NodeEmbed` | `node_embed.py` | `train_and_embed(add_self_loop=True,
lr=1e-3, weight_decay=0, n_epochs=200, patience=inf, gpu=-1)`,返回
`ndata["feat"]` 被替换为嵌入结果的图 |
+| `NodeClassify` | `node_classify.py` | 先 `train(lr, weight_decay, n_epochs,
patience, early_stopping_monitor, gpu)`,再 `evaluate()` 返回 `{"accuracy": ...,
"loss": ...}` |
+| `NodeClassifyWithEdge` | `node_classify_with_edge.py` | 结构相同,适用于同时读取
`edata["feat"]` 的模型 |
+| `NodeClassifyWithSample` | `node_classify_with_sample.py` | 基于
`ClusterGCNSampler` 分区的训练,仅使用 CPU,没有 `gpu` 参数 |
+| `GraphClassify` | `graph_classify.py` | `train(batch_size=20, lr,
weight_decay, n_epochs, patience, early_stopping_monitor, clip=2.0, gpu)`,在
`HugeGraphDataset` 上按 70/20/10 划分 |
+| `DetectorCaregnn` | `fraud_detector_caregnn.py` | CARE-GNN 训练,`evaluate()`
输出 recall 和 ROC AUC,并读取 `ndata["feature"]` 而非 `ndata["feat"]` |
+| `HeteroSampleEmbedGATNE` | `hetero_sample_embed_gatne.py` |
`train_and_embed(lr=1e-3, n_epochs=200, gpu=-1)` |
+| `LinkPredictionPGNN` | `link_prediction_pgnn.py` | `train(lr, weight_decay,
n_epochs, gpu)` |
+| `LinkPredictionSeal` | `link_prediction_seal.py` | 构造函数内部已调用
`data_prepare()`,随后执行 `train(lr=1e-3, n_epochs=200, gpu=-1)` |
+
+`patience` 默认值为 `float("inf")`。`utils/early_stopping.py` 中的 `EarlyStopping`
可以监控 `loss` 或 `accuracy`,保存最优权重并在训练结束时恢复。
+
+## 可运行示例
+
+脚本位于 `hugegraph-ml/src/hugegraph_ml/examples/`。在 `hugegraph-ml/src` 目录下执行:
+
+```bash
+python ./hugegraph_ml/examples/dgi_example.py
+```
-源码中还包含 `GIN` 图分类实现和供下游分类使用的 `MLPClassifier`。模型数量会随版本变化,以
`src/hugegraph_ml/models/` 为准。
+每个脚本同时提供同名函数,可以导入后用较小的 epoch 数调用。
+
+| 脚本 | 模型 | 任务 | 读取的标签 |
+|---|---|---|---|
+| `agnn_example.py` | `AGNN` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `appnp_example.py` | `APPNP` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `arma_example.py` | `ARMA4NC` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `bgnn_example.py` | `BGNNPredictor` | 模型自带的 `fit()` |
`AVAZU__N_v`、`AVAZU__E_e` |
+| `bgrl_example.py` | `BGRL` | `NodeEmbed`、`NodeClassify` |
`CORA_vertex`、`CORA_edge` |
+| `care_gnn_example.py` | `CAREGNN` | `DetectorCaregnn` | `AMAZON_user_v` 以及
`AMAZON_net_upu_e`、`AMAZON_net_usu_e`、`AMAZON_net_uvu_e` |
+| `cluster_gcn_example.py` | `SAGE` | `NodeClassifyWithSample` |
`CORA_vertex`、`CORA_edge` |
+| `correct_and_smooth_example.py` | `correct_and_smooth` 中的 `MLP` |
`NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `dagnn_example.py` | `DAGNN` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `deepergcn_example.py` | `DeeperGCN` | `NodeClassifyWithEdge` | 通过
`convert_graph_with_edge_feat` 读取 `CORA_vertex`、`CORA_edge` |
+| `dgi_example.py` | `DGI` | `NodeEmbed`、`NodeClassify` |
`CORA_vertex`、`CORA_edge` |
+| `diffpool_example.py` | `DiffPool` | `GraphClassify` |
`MUTAG_graph_vertex`、`MUTAG_vertex`、`MUTAG_edge` |
+| `gatne_example.py` | `DGLGATNE` | `HeteroSampleEmbedGATNE` |
`AMAZONGATNE__N_v`、`AMAZONGATNE_1_e`、`AMAZONGATNE_2_e` |
+| `gin_example.py` | `GIN` | `GraphClassify` |
`MUTAG_graph_vertex`、`MUTAG_vertex`、`MUTAG_edge` |
+| `grace_example.py` | `GRACE` | `NodeEmbed`、`NodeClassify` |
`CORA_vertex`、`CORA_edge` |
+| `grand_example.py` | `GRAND` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `jknet_example.py` | `JKNet` | `NodeClassify` | `CORA_vertex`、`CORA_edge` |
+| `pgnn_example.py` | `PGNN` | `LinkPredictionPGNN` |
`CAVEMAN_vertex`、`CAVEMAN_edge` |
+| `seal_example.py` | `DGCNN` | `LinkPredictionSeal` |
`ogbl-collab_vertex`、`ogbl-collab_edge`、`ogbl-collab_split_edge` |
## DGI 节点嵌入示例
-先把 DGL 的 Cora 数据集导入 HugeGraph:
+先把 DGL 的 Cora 数据集导入 HugeGraph。数据集名会先转为大写,因此 `cora` 和 `CORA` 都会生成 `CORA_vertex`
和 `CORA_edge` 标签:
```python
from hugegraph_ml.utils.dgl2hugegraph_utils import import_graph_from_dgl
@@ -81,7 +212,7 @@ classify_task.train(lr=1e-3, n_epochs=400, patience=40)
print(classify_task.evaluate())
```
-完整脚本是 `hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py`。
+`evaluate()` 返回类似 `{'accuracy': 0.82, 'loss': 0.5714246034622192}` 的字典。完整脚本是
`hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py`。
## GRAND 节点分类示例
@@ -104,10 +235,14 @@ task.train(lr=1e-2, weight_decay=5e-4, n_epochs=2000,
patience=100)
print(task.evaluate())
```
-完整脚本是 `hugegraph-ml/src/hugegraph_ml/examples/grand_example.py`。
+GRAND 每次增强采样都会返回一组 logits,`NodeClassify` 会对列表中的每个元素分别应用掩码后再计算损失。完整脚本是
`hugegraph-ml/src/hugegraph_ml/examples/grand_example.py`。
## 排查问题
- 连接失败:检查 HugeGraph Server 地址、端口和认证信息。
- Schema 不匹配:示例默认使用 `CORA_vertex` 和 `CORA_edge`,自有数据需要传入实际标签。
+- `ValueError: Graph is missing required node attribute ...`:节点分类任务需要 `ndata`
中包含 `feat`、`label`、`train_mask`、`val_mask` 和 `test_mask`。请导入带掩码的数据集,或给
`convert_graph` 传入自定义的 `mask_keys`。
+- `ValueError: dataset not supported`:导入函数只接受上表列出的名称,且 `import_graph_from_ogb`
匹配 `ogbl-collab` 时不做大写转换。
- DGL 或 PyTorch 导入失败:回到仓库根目录重新执行 `uv sync --extra ml`,并确认当前 Python 来自根目录
`.venv`。
+- `bgrl_example.py` 目前在导入阶段就会失败:它从 `hugegraph_ml.models.bgrl` 导入
`MLP_Predictor`,而该模块中的类名是 `MLPPredictor`。
+- `care_gnn_example.py` 读取 `AMAZON_user_v` 和三个 `AMAZON_net_*_e`
边标签,仓库内没有对应的导入函数,需要自行准备该数据集后再运行。
diff --git a/content/en/docs/quickstart/hugegraph-ai/hugegraph-ml.md
b/content/en/docs/quickstart/hugegraph-ai/hugegraph-ml.md
index fce14ca13..891c7af0a 100644
--- a/content/en/docs/quickstart/hugegraph-ai/hugegraph-ml.md
+++ b/content/en/docs/quickstart/hugegraph-ai/hugegraph-ml.md
@@ -4,7 +4,7 @@ linkTitle: "HugeGraph-ML"
weight: 2
---
-HugeGraph-ML reads graph data from HugeGraph and converts it to DGL graphs for
tasks such as node embedding, node classification, and graph classification.
Model implementations are under `hugegraph-ml/src/hugegraph_ml/models/`.
+HugeGraph-ML reads graph data from HugeGraph and converts it to DGL graphs for
tasks such as node embedding, node classification, graph classification, link
prediction and fraud detection. Model implementations are under
`hugegraph-ml/src/hugegraph_ml/models/`.
## Requirements
@@ -12,6 +12,23 @@ HugeGraph-ML reads graph data from HugeGraph and converts it
to DGL graphs for t
- HugeGraph Server 1.0 or later; 1.5 or later is recommended
- `uv` 0.7 or later
+All server access goes through `hugegraph-python-client` (the `pyhugegraph`
package) from the same repository. `HugeGraph2DGL` pulls vertices and edges
over the Gremlin endpoint with `g.V().hasLabel(...)` and `g.E().hasLabel(...)`,
and the dataset importers write through the schema and batch vertex/edge APIs
in batches of 500.
+
+The ML stack is version pinned at the repository root under `[tool.uv]
constraint-dependencies`:
+
+| Package | Pin |
+|---|---|
+| `torch` | `==2.2.0` |
+| `dgl` | `~=2.1.0` |
+| `ogb` | `~=1.3.6` |
+| `torchdata` | `~=0.7.0` |
+| `catboost` | `~=1.2.3` |
+| `category-encoders` | `~=2.6.3` |
+| `numpy` | `~=1.24.4` |
+| `pandas` | `~=2.2.3` |
+
+Those pins install CPU builds. Every task accepts a `gpu` argument that
defaults to `-1`, meaning CPU; pass a device index only after installing CUDA
builds of `torch` and `dgl` yourself.
+
## Installation
```bash
@@ -26,22 +43,136 @@ HugeGraph-ML is a path dependency of the root project but
is not a `uv` workspac
## Implemented Models
-The current README lists these models:
+Every module below lives in `hugegraph-ml/src/hugegraph_ml/models/`.
`models/__init__.py` re-exports nothing, so import from the module file
directly.
+
+| Model | Module | Entry class | Used for | Paper |
+|---|---|---|---|---|
+| AGNN | `agnn.py` | `AGNN` | Node classification |
[1803.03735](https://arxiv.org/abs/1803.03735) |
+| APPNP | `appnp.py` | `APPNP` | Node classification |
[1810.05997](https://arxiv.org/abs/1810.05997) |
+| ARMA | `arma.py` | `ARMA4NC` | Node classification |
[1901.01343](https://arxiv.org/abs/1901.01343) |
+| BGNN | `bgnn.py` | `BGNNPredictor` | Gradient boosting over node features
combined with a GNN; the bundled example runs regression |
[2101.08543](https://arxiv.org/abs/2101.08543) |
+| BGRL | `bgrl.py` | `BGRL` | Self-supervised node embedding |
[2102.06514](https://arxiv.org/abs/2102.06514) |
+| CARE-GNN | `care_gnn.py` | `CAREGNN` | Fraud detection |
[2008.08692](https://arxiv.org/abs/2008.08692) |
+| Cluster-GCN | `cluster_gcn.py` | `SAGE` | Node classification with subgraph
sampling | [1905.07953](https://arxiv.org/abs/1905.07953) |
+| C&S | `correct_and_smooth.py` | `MLP`, `CorrectAndSmooth`,
`LabelPropagation` | Correcting and smoothing base predictions |
[2010.13993](https://arxiv.org/abs/2010.13993) |
+| DAGNN | `dagnn.py` | `DAGNN` | Node classification |
[2007.09296](https://arxiv.org/abs/2007.09296) |
+| DeeperGCN | `deepergcn.py` | `DeeperGCN` | Node classification with edge
features | [2006.07739](https://arxiv.org/abs/2006.07739) |
+| DGI | `dgi.py` | `DGI` | Self-supervised node embedding |
[1809.10341](https://arxiv.org/abs/1809.10341) |
+| DiffPool | `diffpool.py` | `DiffPool` | Graph classification |
[1806.08804](https://arxiv.org/abs/1806.08804) |
+| GATNE | `gatne.py` | `DGLGATNE` | Heterogeneous network embedding |
[1905.01669](https://arxiv.org/abs/1905.01669) |
+| GIN | `gin_global_pool.py` | `GIN` | Graph classification | |
+| GRACE | `grace.py` | `GRACE` | Self-supervised node embedding |
[2006.04131](https://arxiv.org/abs/2006.04131) |
+| GRAND | `grand.py` | `GRAND` | Node classification |
[2005.11079](https://arxiv.org/abs/2005.11079) |
+| JKNet | `jknet.py` | `JKNet` | Node classification |
[1806.03536](https://arxiv.org/abs/1806.03536) |
+| MLP | `mlp.py` | `MLPClassifier` | Downstream classifier over learned
embeddings | |
+| P-GNN | `pgnn.py` | `PGNN` | Link prediction |
[you19b](http://proceedings.mlr.press/v97/you19b/you19b.pdf) |
+| SEAL | `seal.py` | `DGCNN`, `SEALData` | Link prediction |
[1802.09691](https://arxiv.org/abs/1802.09691) |
+
+`GIN` accepts `pooling` values `sum` (default), `mean`, `max`,
`global_attention` and `set2set`.
+
+## Reading Graph Data
+
+`HugeGraph2DGL` in `hugegraph-ml/src/hugegraph_ml/data/hugegraph2dgl.py` opens
a `PyHugeClient` and converts query results into DGL objects:
-| Models | Main purpose |
-|---|---|
-| AGNN, APPNP, ARMA, Cluster-GCN, DAGNN, DeeperGCN, GRAND, JKNet | Node
classification |
-| BGNN, CARE-GNN | Fraud detection |
-| BGRL, DGI, GRACE | Representation learning |
-| DiffPool | Graph classification |
-| GATNE, P-GNN, SEAL | Link prediction or network embedding |
-| C&S | Correction and smoothing of predictions |
+```python
+from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
+
+hg2d = HugeGraph2DGL(
+ url="http://127.0.0.1:8080",
+ graph="hugegraph",
+ user="",
+ pwd="",
+ graphspace=None,
+)
+```
+
+| Method | Returns | Notes |
+|---|---|---|
+| `convert_graph(vertex_label, edge_label, feat_key="feat", label_key="label",
mask_keys=None)` | `dgl.DGLGraph` | `mask_keys` falls back to `["train_mask",
"val_mask", "test_mask"]` |
+| `convert_hetero_graph(vertex_labels, edge_labels, feat_key="feat",
label_key="label", mask_keys=None)` | DGL heterograph | Takes lists of labels |
+| `convert_graph_dataset(graph_vertex_label, vertex_label, edge_label,
feat_key="feat", label_key="label")` | `HugeGraphDataset` | Fills `info` with
`n_graphs`, `max_n_nodes`, `n_feat_dim`, `n_classes` |
+| `convert_graph_nx(vertex_label, edge_label)` | `networkx.Graph` | Used by
P-GNN |
+| `convert_graph_with_edge_feat(vertex_label, edge_label,
node_feat_key="feat", edge_feat_key="edge_feat", label_key="label",
mask_keys=None)` | `dgl.DGLGraph` | Also fills `edata["feat"]` |
+| `convert_graph_ogb(vertex_label, edge_label, split_label)` | `(dgl.DGLGraph,
split_edge)` | Used by SEAL |
+| `convert_hetero_graph_bgnn(vertex_labels, edge_labels, feat_key="feat",
label_key="class", cat_key="cat_features", mask_keys=None)` | DGL heterograph |
Used by BGNN |
+
+Node features land in `ndata["feat"]`, labels in `ndata["label"]` and each
mask in `ndata[<mask key>]`. `NodeEmbed` requires `feat` only; `NodeClassify`,
`NodeClassifyWithEdge` and `NodeClassifyWithSample` require `feat`, `label`,
`train_mask`, `val_mask` and `test_mask` and raise `ValueError` when one is
missing.
+
+## Importing Sample Datasets
+
+`hugegraph_ml.utils.dgl2hugegraph_utils` writes DGL, OGB and NetworkX datasets
into HugeGraph so the conversion layer has something to read. Every function
takes the same `url`, `graph`, `user`, `pwd` and `graphspace` arguments as
`HugeGraph2DGL`, and most upper-case the dataset name before matching it.
+
+| Function | Accepted datasets | Labels created |
+|---|---|---|
+| `import_graph_from_dgl` | `CORA`, `CITESEER`, `PUBMED` | `<NAME>_vertex`,
`<NAME>_edge` |
+| `import_graphs_from_dgl` | `MUTAG`, `COLLAB`, `NCI1`, `PROTEINS`, `PTC`,
`ENZYMES`, `DD` | `<NAME>_graph_vertex`, `<NAME>_vertex`, `<NAME>_edge` |
+| `import_hetero_graph_from_dgl` | `ACM` | `<NAME>_<ntype>_v`,
`<NAME>_<etype>_e` |
+| `import_hetero_graph_from_dgl_no_feat` | `AMAZONGATNE` | `<NAME>_<ntype>_v`,
`<NAME>_<etype>_e` |
+| `import_hetero_graph_from_dgl_bgnn` | `AVAZU` | `<NAME>_<ntype>_v`,
`<NAME>_<etype>_e` |
+| `import_graph_from_nx` | `CAVEMAN` | `<NAME>_vertex`, `<NAME>_edge` |
+| `import_graph_from_dgl_with_edge_feat` | `CORA`, `CITESEER`, `PUBMED` |
`<NAME>_edge_feat_vertex`, `<NAME>_edge_feat_edge` |
+| `import_graph_from_ogb` | `ogbl-collab`, matched without upper-casing |
`<NAME>_vertex`, `<NAME>_edge` |
+| `import_split_edge_from_ogb` | `ogbl-collab`, matched without upper-casing |
`<NAME>_split_edge` |
+
+Any other name raises `ValueError("dataset not supported")`.
`import_split_edge_from_ogb` additionally requires the `idx_to_vertex_id`
mapping and a `max_nodes` cap returned by the vertex import.
+
+`clear_all_data()` drops every vertex and edge in the target graph. The test
fixture calls it, loads `CORA`, `MUTAG` and `ACM`, and calls it again on
teardown.
+
+`AMAZONGATNE` and `AVAZU` are not fetched automatically. Their archive URLs
are recorded in comments above `import_hetero_graph_from_dgl_no_feat` and
`import_hetero_graph_from_dgl_bgnn`.
+
+## Tasks
+
+Task classes live in `hugegraph-ml/src/hugegraph_ml/tasks/`. Each one takes
the converted graph and a model instance.
+
+| Class | Module | Entry points |
+|---|---|---|
+| `NodeEmbed` | `node_embed.py` | `train_and_embed(add_self_loop=True,
lr=1e-3, weight_decay=0, n_epochs=200, patience=inf, gpu=-1)` returns the graph
with `ndata["feat"]` replaced by the embedding |
+| `NodeClassify` | `node_classify.py` | `train(lr, weight_decay, n_epochs,
patience, early_stopping_monitor, gpu)` then `evaluate()`, which returns
`{"accuracy": ..., "loss": ...}` |
+| `NodeClassifyWithEdge` | `node_classify_with_edge.py` | Same shape, for
models that also read `edata["feat"]` |
+| `NodeClassifyWithSample` | `node_classify_with_sample.py` | Cluster-GCN
style training on `ClusterGCNSampler` partitions; runs on CPU and takes no
`gpu` argument |
+| `GraphClassify` | `graph_classify.py` | `train(batch_size=20, lr,
weight_decay, n_epochs, patience, early_stopping_monitor, clip=2.0, gpu)` over
a `HugeGraphDataset`, split 70/20/10 |
+| `DetectorCaregnn` | `fraud_detector_caregnn.py` | CARE-GNN training;
`evaluate()` reports recall and ROC AUC and reads `ndata["feature"]` rather
than `ndata["feat"]` |
+| `HeteroSampleEmbedGATNE` | `hetero_sample_embed_gatne.py` |
`train_and_embed(lr=1e-3, n_epochs=200, gpu=-1)` |
+| `LinkPredictionPGNN` | `link_prediction_pgnn.py` | `train(lr, weight_decay,
n_epochs, gpu)` |
+| `LinkPredictionSeal` | `link_prediction_seal.py` | The constructor calls
`data_prepare()` itself, then `train(lr=1e-3, n_epochs=200, gpu=-1)` |
+
+`patience` defaults to `float("inf")`. `EarlyStopping` in
`utils/early_stopping.py` monitors either `loss` or `accuracy`, keeps a copy of
the best weights and restores them when training stops.
+
+## Runnable Examples
+
+Scripts sit in `hugegraph-ml/src/hugegraph_ml/examples/`. From
`hugegraph-ml/src`, run one with:
+
+```bash
+python ./hugegraph_ml/examples/dgi_example.py
+```
-The source also includes `GIN` for graph classification and `MLPClassifier`
for downstream classification. The model count changes between versions; use
`src/hugegraph_ml/models/` as the authoritative list.
+Each script also exposes a function of the same name, so it can be imported
and called with a smaller epoch count.
+
+| Script | Model | Task | Reads |
+|---|---|---|---|
+| `agnn_example.py` | `AGNN` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `appnp_example.py` | `APPNP` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `arma_example.py` | `ARMA4NC` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `bgnn_example.py` | `BGNNPredictor` | Its own `fit()` | `AVAZU__N_v`,
`AVAZU__E_e` |
+| `bgrl_example.py` | `BGRL` | `NodeEmbed`, `NodeClassify` | `CORA_vertex`,
`CORA_edge` |
+| `care_gnn_example.py` | `CAREGNN` | `DetectorCaregnn` | `AMAZON_user_v` plus
`AMAZON_net_upu_e`, `AMAZON_net_usu_e`, `AMAZON_net_uvu_e` |
+| `cluster_gcn_example.py` | `SAGE` | `NodeClassifyWithSample` |
`CORA_vertex`, `CORA_edge` |
+| `correct_and_smooth_example.py` | `MLP` from `correct_and_smooth` |
`NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `dagnn_example.py` | `DAGNN` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `deepergcn_example.py` | `DeeperGCN` | `NodeClassifyWithEdge` |
`CORA_vertex`, `CORA_edge` through `convert_graph_with_edge_feat` |
+| `dgi_example.py` | `DGI` | `NodeEmbed`, `NodeClassify` | `CORA_vertex`,
`CORA_edge` |
+| `diffpool_example.py` | `DiffPool` | `GraphClassify` | `MUTAG_graph_vertex`,
`MUTAG_vertex`, `MUTAG_edge` |
+| `gatne_example.py` | `DGLGATNE` | `HeteroSampleEmbedGATNE` |
`AMAZONGATNE__N_v`, `AMAZONGATNE_1_e`, `AMAZONGATNE_2_e` |
+| `gin_example.py` | `GIN` | `GraphClassify` | `MUTAG_graph_vertex`,
`MUTAG_vertex`, `MUTAG_edge` |
+| `grace_example.py` | `GRACE` | `NodeEmbed`, `NodeClassify` | `CORA_vertex`,
`CORA_edge` |
+| `grand_example.py` | `GRAND` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `jknet_example.py` | `JKNet` | `NodeClassify` | `CORA_vertex`, `CORA_edge` |
+| `pgnn_example.py` | `PGNN` | `LinkPredictionPGNN` | `CAVEMAN_vertex`,
`CAVEMAN_edge` |
+| `seal_example.py` | `DGCNN` | `LinkPredictionSeal` | `ogbl-collab_vertex`,
`ogbl-collab_edge`, `ogbl-collab_split_edge` |
## DGI Node Embedding Example
-First import DGL's Cora dataset into HugeGraph:
+First import DGL's Cora dataset into HugeGraph. The name is upper-cased before
use, so `cora` and `CORA` both produce the `CORA_vertex` and `CORA_edge` labels:
```python
from hugegraph_ml.utils.dgl2hugegraph_utils import import_graph_from_dgl
@@ -76,7 +207,7 @@ classify_task.train(lr=1e-3, n_epochs=400, patience=40)
print(classify_task.evaluate())
```
-The complete script is `hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py`.
+`evaluate()` returns a dictionary such as `{'accuracy': 0.82, 'loss':
0.5714246034622192}`. The complete script is
`hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py`.
## GRAND Node Classification Example
@@ -96,10 +227,14 @@ task.train(lr=1e-2, weight_decay=5e-4, n_epochs=2000,
patience=100)
print(task.evaluate())
```
-The complete script is
`hugegraph-ml/src/hugegraph_ml/examples/grand_example.py`.
+GRAND returns a list of logits per augmentation sample, and `NodeClassify`
masks each element of that list before computing the loss. The complete script
is `hugegraph-ml/src/hugegraph_ml/examples/grand_example.py`.
## Troubleshooting
- Connection failures: check the HugeGraph Server address, port, and
credentials.
- Schema mismatches: the examples use `CORA_vertex` and `CORA_edge`; pass the
actual labels for your own data.
+- `ValueError: Graph is missing required node attribute ...`: the node
classification tasks need `feat`, `label`, `train_mask`, `val_mask` and
`test_mask` in `ndata`. Import a dataset that carries masks, or pass your own
`mask_keys` to `convert_graph`.
+- `ValueError: dataset not supported`: the importer only accepts the names in
the table above, and `import_graph_from_ogb` matches `ogbl-collab` without
upper-casing.
- DGL or PyTorch import failures: rerun `uv sync --extra ml` from the
repository root and confirm that Python comes from the root `.venv`.
+- `bgrl_example.py` currently fails on import: it asks for `MLP_Predictor`
from `hugegraph_ml.models.bgrl`, but that module defines the class as
`MLPPredictor`.
+- `care_gnn_example.py` reads `AMAZON_user_v` and the three `AMAZON_net_*_e`
edge labels. No bundled importer creates them, so load that dataset yourself
before running the script.