Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions examples/gnrf/args.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"wisconsin": {
"dataset": "wisconsin",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.0014577890711895912,
"weight_decay": 0.0008857926282823821,
"dropout": 0.27372220290104154,
"num_hid": 128,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": true,
"use_bn_out": false,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 0.8483774748255035,
"tol_scale": 2.118818198337877,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 1703,
"num_class": 5,
"rewiring": null,
"damping": true,
"edgenet": true
},
"cornell": {
"dataset": "cornell",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 800,
"lr": 0.002832941670402573,
"weight_decay": 4.315845302779911e-05,
"dropout": 0.20115854835043973,
"num_hid": 192,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": false,
"use_bn_out": false,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 0.10918163696818216,
"tol_scale": 4.348962999711223,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 1703,
"num_class": 5,
"rewiring": null,
"damping": true,
"edgenet": true
},
"texas": {
"dataset": "texas",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.009465689674847282,
"weight_decay": 3.318139009838993e-05,
"dropout": 0.02318890583746977,
"num_hid": 256,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": false,
"use_bn_out": false,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 0.664120788452176,
"tol_scale": 2.2510097955315866,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 1703,
"num_class": 5,
"rewiring": null,
"damping": true,
"edgenet": true
},
"roman-empire": {
"dataset": "Roman-empire",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.0017770294770524057,
"weight_decay": 1.206367283375403e-06,
"dropout": 0.4076238151758252,
"num_hid": 256,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": true,
"use_bn_out": true,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 7.1808984693838624,
"tol_scale": 14766.304417175616,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 300,
"num_class": 18,
"rewiring": null,
"damping": true,
"edgenet": true
},
"cora_full": {
"dataset": "Cora_Full",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.00027656068839244653,
"weight_decay": 9.76581378785642e-05,
"dropout": 0.6837586052894707,
"num_hid": 256,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": true,
"use_bn_out": true,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 4.092580732743444,
"tol_scale": 5.831748380763541,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 8710,
"num_class": 70,
"rewiring": null,
"damping": true,
"edgenet": true
},
"pubmed": {
"dataset": "pubmed",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.000842290192251508,
"weight_decay": 6.724802070706501e-06,
"dropout": 0.3068111160234254,
"num_hid": 64,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": true,
"use_bn_out": true,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 1.562395740177495,
"tol_scale": 76.17766226880025,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 500,
"num_class": 3,
"rewiring": null,
"damping": true,
"edgenet": true
},
"tolokers": {
"dataset": "Tolokers",
"device": "cuda:0",
"trial": 10,
"verbose": false,
"epoch": 500,
"lr": 0.009902825826309957,
"weight_decay": 0.0006860252495670429,
"dropout": 0.0920985414289007,
"num_hid": 64,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": true,
"use_bn_out": true,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 3.02086710208908,
"tol_scale": 172.61973364435173,
"solver": "implicit_adams",
"adjoint": false,
"channel_curv": true,
"num_feat": 10,
"num_class": 2,
"rewiring": null,
"damping": true,
"edgenet": true
},
"ogbn-arxiv": {
"dataset": "ogbn-arxiv",
"device": "cuda:2",
"trial": 10,
"verbose": false,
"epoch": 1500,
"lr": 0.0012487994084971797,
"weight_decay": 4.8251083637061214e-05,
"dropout":0.1127683161361892,
"num_hid": 64,
"use_mlp_in": false,
"use_mlp_out": false,
"use_bn_in": false,
"use_bn_out": true,
"ode": "GNRF",
"t_start": 1e-05,
"t_end": 3.206093833264813,
"tol_scale": 7.211796294690889,
"solver": "implicit_adams",
"adjoint": true,
"channel_curv": true,
"num_feat": 128,
"num_class": 40,
"rewiring": null,
"damping": true,
"edgenet": true
}
}
64 changes: 64 additions & 0 deletions examples/gnrf/dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os
import numpy as np
import tensorlayerx as tlx
from gammagl.datasets import Planetoid, WebKB
from gammagl.utils import to_undirected, remove_self_loops
from gammagl.datasets.custom_datasets import CustomDataset

script_dir = os.path.dirname(os.path.abspath(__file__))
DATASET_ROOT = script_dir + "/Datasets"

class NodeDataset:
def __init__(self, dataset_name: str):
self.dataset_name = dataset_name.lower()
self.file_root = DATASET_ROOT

if self.dataset_name in ['pubmed']:
dataset = Planetoid(root=self.file_root, name=self.dataset_name, force_reload=True)
data = dataset[0]
elif self.dataset_name in ['cornell', 'texas', 'wisconsin']:
dataset = WebKB(root=self.file_root, name=self.dataset_name, force_reload=True)
data = dataset[0]
else:
data = self._load_custom_dataset()

self.x = tlx.convert_to_tensor(data.x, dtype=tlx.float32)
self.edge_index = tlx.convert_to_tensor(data.edge_index, dtype=tlx.int64)
self.y = tlx.convert_to_tensor(data.y, dtype=tlx.int64)

if self.dataset_name == 'ogbn-arxiv' and len(self.y.shape) > 1:
self.y = tlx.reshape(self.y, (-1,))

self.nfeat = self.x.shape[1]
self.nclass = int(tlx.reduce_max(self.y)) + 1
self.nnode = self.x.shape[0]

self.edge_index = remove_self_loops(self.edge_index)[0]
self.edge_index = to_undirected(self.edge_index)

self._normalize_features()

def _load_custom_dataset(self):
if self.dataset_name not in ['roman-empire', 'tolokers', 'cora_full', 'ogbn-arxiv']:
raise ValueError(f"Unsupported dataset: {self.dataset_name}")
dataset = CustomDataset(root=self.file_root, name=self.dataset_name)
return dataset[0]

def _normalize_features(self):
self.x = tlx.where(tlx.is_nan(self.x), tlx.zeros_like(self.x), self.x)
rowsum = tlx.reduce_sum(self.x, axis=1, keepdims=True)
rowsum = tlx.where(rowsum == 0., tlx.ones_like(rowsum), rowsum)
self.x = self.x / rowsum

def random_split(self, seed: int, p_train: float = 0.6, p_val: float = 0.2):
tlx.set_seed(seed)
np.random.seed(seed)
n_train = int(self.nnode * p_train)
n_val = int(self.nnode * p_val)
full_idx = np.random.permutation(self.nnode)
train_idx = full_idx[:n_train]
val_idx = full_idx[n_train+1:n_train + n_val]
test_idx = full_idx[n_train + n_val+1:]
return train_idx, val_idx, test_idx


47 changes: 47 additions & 0 deletions examples/gnrf/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Graph Neural Ricci Flow: Evolving Feature From A Curvature Perspective
---

- Paper link: https://proceedings.iclr.cc/paper_files/paper/2025/file/4d3ac0eee841e6df6e08e51932943266-Paper-Conference.pdf
- Author's code repo (in PyTorch): https://github.com/GalenChen320/GNRF_new

## Datasets and Performances
---

|Datasets|Cornell|Wisconsin|Texas|Roman-Empire|Tolokers|Cora_Full|Pubmed|
|---|---|---|---|---|---|---|---|
|Hom.level|0.1227|0.1778|0.0609|0.0000|0.6344|0.5670|0.8024|
|#Node|183|251|183|22,662|11,758|19,793|19,717|
|Paper|87.28(±3.12)|88.00(±2.00)|87.39(±4.13)|86.25(±0.46)|83.96(±0.39)|72.12(±0.50)|90.37(±0.69)|
|Ours|79.46(±5.57)|87.60(±2.33)|84.86(±6.64)|85.01(±1.04)|81.14(±0.98)|68.62(±0.59)|88.85(±0.39)|

|Datasets|Ogbn-Arxiv|
|---|---|
|depth|3|
|num-hid|64|
|Paper|69.33|
|Ours|60.01|

## Notes
---

- On the Cornell dataset, under the source code and environment described in the paper, the performance on an RTX 3090 is mean: 79.46, std: 7.77. Therefore, the GammaGL version retains mean: 79.46, std: 5.57.
- For the Ogbn-arxiv dataset, with depth=3, num-hid=64, no standard deviation data was reported in the paper. In the original paper's source code environment on an RTX 3090, the results are mean: 66.64, std: 0.62, while the GammaGL version retains mean: 60.01, std: 1.91.
- When using PaddlePaddle or MindSpore as backends, due to the lack of mature and unified Neural ODE solving ecosystems, the odeint module is manually implemented, with only correctness testing performed and no performance guarantees.
- All the data presented in the above tables are obtained only with the PyTorch backend.

## How To Run
---

Execute in the current directory.


```python
python train.py --dataset wisconsin
```

The dataset defaults to GPU mode; under CPU, the command is as follows. Note that the specification of CPU for different backends is case-sensitive.


```python
python train.py --dataset wisconsin --device cpu
```
Loading