EvoRM / code /experiments /run_ablation_v2.py
eduzrh's picture
Upload code/experiments/run_ablation_v2.py with huggingface_hub
ff9b61c verified
Raw
History Blame Contribute Delete
6.31 kB
#!/usr/bin/env python3
"""
EvoRM Ablation Study - All 6 modes
Uses ref_pairs order for entity selection (correct approach).
"""
import os, sys, json, time, shutil
from datetime import datetime
sys.path.insert(0, '/root/autodl-tmp/AdaCoAgentEA')
sys.path.insert(0, '/root/autodl-tmp/AdaCoAgentEA/Area2')
os.environ["OPENAI_API_BASE"] = "https://hk.xty.app/v1"
os.environ["OPENAI_API_KEY"] = "sk-7a7Ev4VcVyysPLT5hqtqIVD6PybzJ1ZlEIVZddIR3NtZvPgK"
DATA_DIR = "/root/autodl-tmp/AdaCoAgentEA/data/icews_wiki"
RESULTS_DIR = "/root/autodl-tmp/AdaCoAgentEA/results"
ALIGNED_FILE = os.path.join(DATA_DIR, "message_pool", "aligned_entities.txt")
REF_PAIRS_FILE = os.path.join(DATA_DIR, "ref_pairs")
IMPORTANT_FILE = os.path.join(DATA_DIR, "message_pool", "important_entities.txt")
RETRIEVER_FILE = os.path.join(DATA_DIR, "message_pool", "retriever_outputs.txt")
EVORM_STATE = os.path.join(DATA_DIR, "evorm_state")
os.makedirs(RESULTS_DIR, exist_ok=True)
def load_ref_pairs():
pairs = {}
with open(REF_PAIRS_FILE, 'r') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
try:
pairs[int(parts[0])] = int(parts[1])
except:
pass
return pairs
def compute_metrics(ref_subset=None):
aligned = set()
if os.path.exists(ALIGNED_FILE):
with open(ALIGNED_FILE, 'r') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
try:
aligned.add((int(parts[0]), int(parts[1])))
except:
continue
if ref_subset:
ref_set = set(ref_subset.items())
else:
ref_set = set(load_ref_pairs().items())
if not ref_set:
return {'error': 'No ref pairs'}
tp = len(aligned & ref_set)
fp = len(aligned - ref_set)
fn = len(ref_set - aligned)
return {
'Hits@1': round(tp / max(1, len(ref_set)), 4),
'MRR': round(tp / max(1, len(ref_set)), 4),
'Precision': round(tp / max(1, tp + fp), 4),
'Recall': round(tp / max(1, tp + fn), 4),
'F1': round(2*tp/max(1, 2*tp+fp+fn), 4),
'TP': tp, 'FP': fp, 'FN': fn,
'Total_Ref': len(ref_set),
'Total_Aligned': len(aligned),
}
def clear_state():
if os.path.exists(EVORM_STATE):
shutil.rmtree(EVORM_STATE)
if os.path.exists(ALIGNED_FILE):
os.remove(ALIGNED_FILE)
def create_subset_from_ref_order(n_entities, ref_map):
"""Create subset using ref_pairs order (not retriever order)."""
# Get entities in ref_pairs order
ref_order = []
with open(REF_PAIRS_FILE, 'r') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
try:
e1 = int(parts[0])
if e1 not in ref_order:
ref_order.append(e1)
except:
pass
actual_n = min(n_entities, len(ref_order))
subset_kg1 = set(ref_order[:actual_n])
# Filter retriever lines for these entities
subset_lines = []
with open(RETRIEVER_FILE, 'r') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
try:
if int(parts[0]) in subset_kg1:
subset_lines.append(line)
except:
pass
with open(IMPORTANT_FILE, 'w') as f:
f.writelines(subset_lines)
subset_ref = {e1: ref_map[e1] for e1 in subset_kg1 if e1 in ref_map}
print(f" Created subset: {len(subset_kg1)} entities, {len(subset_ref)} ref pairs, {len(subset_lines)} retriever lines")
return subset_ref
def main():
n_entities = 200
ref_map = load_ref_pairs()
print(f"Loaded {len(ref_map)} reference pairs")
import tokens_cal
from LLM1_label_selector import align_entities
configs = [
('Full System (EvoRM)', None),
('w/o Stage-1 (Symbolic)', 'no_stage1'),
('w/o Maintenance', 'no_maintenance'),
('w/o MLP Gate', 'no_mlp_gate'),
('w/o Hypergraph', 'no_hypergraph'),
('w/o Mlight', 'no_mlight'),
]
results = {}
for config_name, ablation_mode in configs:
print(f"\n{'='*50}")
print(f" {config_name}")
print(f"{'='*50}")
subset_ref = create_subset_from_ref_order(n_entities, ref_map)
clear_state()
tokens_cal.global_tokens = 0
start = time.time()
aligned_pairs = align_entities(DATA_DIR, from_m3=False, ablation_mode=ablation_mode)
elapsed = time.time() - start
tokens = tokens_cal.global_tokens
n_pairs = len(aligned_pairs)
metrics = compute_metrics(ref_subset=subset_ref)
results[config_name] = {
'aligned_pairs': n_pairs,
'time_seconds': round(elapsed, 1),
'tokens': tokens,
'tokens_per_pair': round(tokens / max(1, n_pairs), 1),
'metrics': metrics,
}
print(f" Aligned: {n_pairs}, Time: {elapsed:.1f}s, Tokens: {tokens}")
print(f" Hits@1: {metrics['Hits@1']}, Precision: {metrics['Precision']}, Recall: {metrics['Recall']}")
# Save
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
result_file = os.path.join(RESULTS_DIR, f"ablation_6modes_{timestamp}.json")
with open(result_file, 'w') as f:
json.dump({
'experiment': 'EvoRM Ablation Study (6 modes)',
'dataset': 'ICEWS-WIKI',
'n_entities': n_entities,
'results': results,
}, f, indent=2)
# Summary
print(f"\n{'='*70}")
print("ABLATION SUMMARY")
print(f"{'='*70}")
print(f"{'Configuration':<30} {'Hits@1':>8} {'Prec':>8} {'Recall':>8} {'F1':>8} {'Tok':>10}")
print("-" * 70)
for cname, _ in configs:
if cname in results:
m = results[cname]['metrics']
print(f"{cname:<30} {m['Hits@1']:>8.4f} {m['Precision']:>8.4f} {m['Recall']:>8.4f} {m['F1']:>8.4f} {results[cname]['tokens']:>10}")
print(f"\nResults saved to: {result_file}")
if __name__ == '__main__':
main()