summaryrefslogtreecommitdiff
path: root/experiments/run_combo_20seeds.py
diff options
context:
space:
mode:
authorYurenHao0426 <blackhao0426@gmail.com>2026-05-04 23:10:10 -0500
committerYurenHao0426 <blackhao0426@gmail.com>2026-05-04 23:10:10 -0500
commitba6ead6d7a41b7ed78bb228181b7262d0c75d2eb (patch)
tree726171fb4b0c536d9287a15daf52929ec65fa3d0 /experiments/run_combo_20seeds.py
parent37ba0f83e3652a215680fd8515af9c14fc02e21c (diff)
Global rename GRAFT → KAFT (incl. internal class + filenames)
- src/trainers.py: GraphGrAPETrainer → KAFTTrainer; module docstring + comments. VanillaGrAPETrainer kept as-is (it is a separate control method, not KAFT). - experiments/: all 19 runners pick up the new class name; result keys ('Cora_GRAFT' etc) become 'Cora_KAFT'; OUT_DIRs renamed (e.g. bp_graft_depth_20seeds → bp_kaft_depth_20seeds). - figures/: data-lookup keys + display labels both 'KAFT'; output filename graft_depth_sweep.{pdf,png} → kaft_depth_sweep.{pdf,png}. - File rename: experiments/run_bp_graft_depth.py → run_bp_kaft_depth.py; figures/graft_depth_sweep.pdf → kaft_depth_sweep.pdf. - README aligned. Imports verified: from src.trainers import KAFTTrainer succeeds.
Diffstat (limited to 'experiments/run_combo_20seeds.py')
-rw-r--r--experiments/run_combo_20seeds.py72
1 files changed, 36 insertions, 36 deletions
diff --git a/experiments/run_combo_20seeds.py b/experiments/run_combo_20seeds.py
index 1598964..acc8846 100644
--- a/experiments/run_combo_20seeds.py
+++ b/experiments/run_combo_20seeds.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
-"""Task 2ceadaa7: GRAFT + Forward Tricks combo experiments (20 seeds).
+"""Task 2ceadaa7: KAFT + Forward Tricks combo experiments (20 seeds).
-Combos: GRAFT+ResGCN, GRAFT+DropEdge, GRAFT+PairNorm, GRAFT+JKNet
+Combos: KAFT+ResGCN, KAFT+DropEdge, KAFT+PairNorm, KAFT+JKNet
Each compared to: BP, forward_trick_only, GRAFT_only, combo
"""
@@ -12,7 +12,7 @@ import json
import os
from scipy import stats as scipy_stats
from src.data import load_dataset, spmm, build_normalized_adj
-from src.trainers import BPTrainer, GraphGrAPETrainer, _FeedbackTrainerBase
+from src.trainers import BPTrainer, KAFTTrainer, _FeedbackTrainerBase
from run_deep_baselines import ResGCNTrainer, JKNetTrainer
from run_dropedge import BPDropEdgeTrainer
from run_pairnorm_baseline import BPPairNormTrainer, pairnorm
@@ -28,10 +28,10 @@ grape_extra = dict(diffusion_alpha=0.5, diffusion_iters=10,
# ═══════════════════════════════════════════════════════════════════════════
-# GRAFT + ResGCN combo (fixed version)
+# KAFT + ResGCN combo (fixed version)
# ═══════════════════════════════════════════════════════════════════════════
-class GRAFTResGCN(GraphGrAPETrainer):
- """GRAFT backward + ResGCN forward (skip connections)."""
+class GRAFTResGCN(KAFTTrainer):
+ """KAFT backward + ResGCN forward (skip connections)."""
def forward(self):
X = self.data['X']
@@ -57,10 +57,10 @@ class GRAFTResGCN(GraphGrAPETrainer):
# ═══════════════════════════════════════════════════════════════════════════
-# GRAFT + DropEdge combo
+# KAFT + DropEdge combo
# ═══════════════════════════════════════════════════════════════════════════
-class GRAFTDropEdge(GraphGrAPETrainer):
- """GRAFT backward + DropEdge forward (random edge dropping)."""
+class GRAFTDropEdge(KAFTTrainer):
+ """KAFT backward + DropEdge forward (random edge dropping)."""
def __init__(self, *args, drop_rate=0.5, **kwargs):
super().__init__(*args, **kwargs)
@@ -81,9 +81,9 @@ class GRAFTDropEdge(GraphGrAPETrainer):
).coalesce()
def forward(self):
- # DropEdge only in forward pass, GRAFT backward uses original A_hat
+ # DropEdge only in forward pass, KAFT backward uses original A_hat
self.data['A_hat'] = self._drop_edges()
- result = super().forward() # uses GraphGrAPETrainer.forward()
+ result = super().forward() # uses KAFTTrainer.forward()
self.data['A_hat'] = self._A_hat_orig
return result
@@ -93,10 +93,10 @@ class GRAFTDropEdge(GraphGrAPETrainer):
# ═══════════════════════════════════════════════════════════════════════════
-# GRAFT + PairNorm combo
+# KAFT + PairNorm combo
# ═══════════════════════════════════════════════════════════════════════════
-class GRAFTPairNorm(GraphGrAPETrainer):
- """GRAFT backward + PairNorm forward (center & scale normalization)."""
+class GRAFTPairNorm(KAFTTrainer):
+ """KAFT backward + PairNorm forward (center & scale normalization)."""
def __init__(self, *args, pn_scale=1.0, **kwargs):
super().__init__(*args, **kwargs)
@@ -138,13 +138,13 @@ class GRAFTPairNorm(GraphGrAPETrainer):
# ═══════════════════════════════════════════════════════════════════════════
-# GRAFT + JKNet combo
+# KAFT + JKNet combo
# ═══════════════════════════════════════════════════════════════════════════
-class GRAFTJKNet(GraphGrAPETrainer):
- """GRAFT backward + JKNet forward (jumping knowledge max-pool).
+class GRAFTJKNet(KAFTTrainer):
+ """KAFT backward + JKNet forward (jumping knowledge max-pool).
Note: JKNet changes the output architecture. We max-pool hidden layers
- and project to num_classes. GRAFT backward operates on hidden layers
+ and project to num_classes. KAFT backward operates on hidden layers
as usual; the JK projection is treated as the output layer.
"""
@@ -187,7 +187,7 @@ class GRAFTJKNet(GraphGrAPETrainer):
def _update_weights(self, inter, E0, deltas):
"""Override to handle JK projection separately."""
- # Update hidden layers using GRAFT feedback as usual
+ # Update hidden layers using KAFT feedback as usual
X = self.data['X']
Hs = inter['Hs']
H0 = inter['H0']
@@ -265,7 +265,7 @@ def main():
per_seed_data = {}
# Reuse existing per-seed data from other experiments
- # BP, ResGCN, GRAFT from resgcn_20seeds
+ # BP, ResGCN, KAFT from resgcn_20seeds
try:
with open('results/resgcn_20seeds/per_seed_data.json') as f:
resgcn_cache = json.load(f)
@@ -292,11 +292,11 @@ def main():
'DropEdge': (BPDropEdgeTrainer, {'drop_rate': 0.5}),
'PairNorm': (BPPairNormTrainer, {'pn_scale': 1.0}),
'JKNet': (JKNetTrainer, {}),
- 'GRAFT': (GraphGrAPETrainer, grape_extra),
- 'GRAFT+ResGCN': (GRAFTResGCN, grape_extra),
- 'GRAFT+DropEdge': (GRAFTDropEdge, {**grape_extra, 'drop_rate': 0.5}),
- 'GRAFT+PairNorm': (GRAFTPairNorm, {**grape_extra, 'pn_scale': 1.0}),
- 'GRAFT+JKNet': (GRAFTJKNet, grape_extra),
+ 'KAFT': (KAFTTrainer, grape_extra),
+ 'KAFT+ResGCN': (GRAFTResGCN, grape_extra),
+ 'KAFT+DropEdge': (GRAFTDropEdge, {**grape_extra, 'drop_rate': 0.5}),
+ 'KAFT+PairNorm': (GRAFTPairNorm, {**grape_extra, 'pn_scale': 1.0}),
+ 'KAFT+JKNet': (GRAFTJKNet, grape_extra),
}
datasets_cfg = {
@@ -330,7 +330,7 @@ def main():
cached = resgcn_cache[f"{ds_name}_BP"].get(sk)
elif mname == 'ResGCN' and f"{ds_name}_ResGCN" in resgcn_cache:
cached = resgcn_cache[f"{ds_name}_ResGCN"].get(sk)
- elif mname == 'GRAFT' and f"{ds_name}_GRAFT" in resgcn_cache:
+ elif mname == 'KAFT' and f"{ds_name}_GRAFT" in resgcn_cache:
cached = resgcn_cache[f"{ds_name}_GRAFT"].get(sk)
elif mname == 'DropEdge':
de_key = f"{ds_name}_gcn_L6"
@@ -369,14 +369,14 @@ def main():
for ds in ['Cora', 'CiteSeer', 'DBLP']:
print(f"\n--- {ds} GCN L=6 lr=0.01 ---")
- print(f"{'Method':<18} {'Mean±Std':>12} {'vs GRAFT':>18} {'vs FwdTrick':>18}")
+ print(f"{'Method':<18} {'Mean±Std':>12} {'vs KAFT':>18} {'vs FwdTrick':>18}")
print("-" * 70)
- # Get GRAFT accs for comparison
+ # Get KAFT accs for comparison
gr_accs = np.array([per_seed_data[f"{ds}_GRAFT"][str(s)] for s in SEEDS]) * 100
for mname in ['BP', 'ResGCN', 'DropEdge', 'PairNorm', 'JKNet',
- 'GRAFT', 'GRAFT+ResGCN', 'GRAFT+DropEdge', 'GRAFT+PairNorm', 'GRAFT+JKNet']:
+ 'KAFT', 'KAFT+ResGCN', 'KAFT+DropEdge', 'KAFT+PairNorm', 'KAFT+JKNet']:
key = f"{ds}_{mname}"
if key not in per_seed_data or len(per_seed_data[key]) < 20:
print(f" {mname:<16} MISSING ({len(per_seed_data.get(key, {}))} seeds)")
@@ -387,8 +387,8 @@ def main():
results[key] = {'mean': float(m), 'std': float(s), 'accs': accs.tolist()}
- # Paired t-test vs GRAFT
- if mname != 'GRAFT':
+ # Paired t-test vs KAFT
+ if mname != 'KAFT':
t_stat, p_val = scipy_stats.ttest_rel(accs, gr_accs)
delta = m - gr_accs.mean()
sig = '***' if p_val < 0.001 else ('**' if p_val < 0.01 else ('*' if p_val < 0.05 else 'ns'))
@@ -402,8 +402,8 @@ def main():
# Paired t-test vs forward trick only
fwd_map = {
- 'GRAFT+ResGCN': 'ResGCN', 'GRAFT+DropEdge': 'DropEdge',
- 'GRAFT+PairNorm': 'PairNorm', 'GRAFT+JKNet': 'JKNet'
+ 'KAFT+ResGCN': 'ResGCN', 'KAFT+DropEdge': 'DropEdge',
+ 'KAFT+PairNorm': 'PairNorm', 'KAFT+JKNet': 'JKNet'
}
if mname in fwd_map:
fwd_key = f"{ds}_{fwd_map[mname]}"
@@ -431,8 +431,8 @@ def main():
for ds in ['Cora', 'CiteSeer', 'DBLP']:
print(f"\n{ds}:")
gr_m = results.get(f"{ds}_GRAFT", {}).get('mean', 0)
- for combo, fwd in [('GRAFT+ResGCN', 'ResGCN'), ('GRAFT+DropEdge', 'DropEdge'),
- ('GRAFT+PairNorm', 'PairNorm'), ('GRAFT+JKNet', 'JKNet')]:
+ for combo, fwd in [('KAFT+ResGCN', 'ResGCN'), ('KAFT+DropEdge', 'DropEdge'),
+ ('KAFT+PairNorm', 'PairNorm'), ('KAFT+JKNet', 'JKNet')]:
ck = f"{ds}_{combo}"
fk = f"{ds}_{fwd}"
if ck in results and fk in results:
@@ -442,7 +442,7 @@ def main():
vs_fw = results[ck].get(f'vs_{fwd}', {})
better_than_both = c_m > gr_m and c_m > f_m
marker = "✓ ADDITIVE" if better_than_both else "✗ not additive"
- print(f" {combo}: {c_m:.1f} | GRAFT={gr_m:.1f} | {fwd}={f_m:.1f} → {marker}")
+ print(f" {combo}: {c_m:.1f} | KAFT={gr_m:.1f} | {fwd}={f_m:.1f} → {marker}")
# Save
with open(os.path.join(OUT_DIR, 'results.json'), 'w') as f: