File size: 6,485 Bytes
5b10376 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""exposure_analysis.py — «تعرّض فعلي» لا «توافر»:
يعيد تشغيل build_examples بنفس البذرة (13) وعبر قائمة المجمّع الأصلية (pairs.jsonl من
مخرجات النواة) لتحديد الأزواج التي دخلت أمثلة التدريب فعلًا، ثم يقارنها بعناصر التقييم.
تحقق سلامة إعادة البناء: عدد النصوص الفريدة (md5) يجب أن يطابق feat_cache_300000.npz
المُنتَج وقت التدريب نفسه (إن تطابق ⇒ إعادة البناء مطابقة حرفيًا)."""
import os, sys, json, time, random, hashlib
import numpy as np
sys.path.insert(0, "/home/user/lhc/code"); sys.path.insert(0, "/home/user/lhc/recon")
T0=time.time()
def log(*a): print(f"[{time.time()-T0:6.1f}s]", *a, flush=True)
W4="/var/tmp/lhc_w4"
N_EXAMPLES=300000; SEED=13
# --- نفس الاستيرادات التي يستخدمها build_examples الأصلي ---
from phase_c_augment import augment
from phase_p2_slot import make_sibling, novel_view
from phase_s_scale import make_scaled_corpus
kb=json.load(open("/home/user/lhc/code/knowledge_bank_superbrain.json", encoding="utf-8"))
kb_prompts=[e["prompt"] for e in kb]
synth=kb_prompts+[e["prompt"] for e in make_scaled_corpus(3000, seed=0)]
NS=len(synth)
# عدّ أسطر pairs.jsonl
with open(f"{W4}/pairs.jsonl","rb") as f:
n_pairs=sum(1 for _ in f)
log(f"pairs.jsonl: {n_pairs:,} زوجًا | len(synth)={NS}")
# --- (أ) إعادة تشغيل RNG فقط لتحديد الفهارس ---
rng=random.Random(SEED)
par_idx=[]; mono_idx=[]; branch_counts={"par":0,"mono_pair":0,"mono_synth":0,"slot":0,"prot":0}
for i in range(N_EXAMPLES):
r=rng.random()
if r<0.40:
p_i=rng.randrange(n_pairs); par_idx.append(p_i); branch_counts["par"]+=1
elif r<0.65:
if rng.random()<0.5:
p_i=rng.randrange(n_pairs); rng.choice(("en","ar")); mono_idx.append(p_i); branch_counts["mono_pair"]+=1
else:
rng.randrange(NS); branch_counts["mono_synth"]+=1
elif r<0.85:
rng.randrange(NS); branch_counts["slot"]+=1
else:
rng.randrange(NS); branch_counts["prot"]+=1
log(f"الفروع: {branch_counts} | فهارس الأزواج: {len(par_idx):,} + {len(mono_idx):,}")
# --- (ب) استخراج نصوص الفهارس المطلوبة من pairs.jsonl (جولة واحدة) ---
need=set(par_idx)|set(mono_idx)
texts={}
with open(f"{W4}/pairs.jsonl", encoding="utf-8") as f:
for i,line in enumerate(f):
if i in need:
o=json.loads(line); texts[i]=(o.get("ar",""),o.get("en",""))
log(f"استُخرج {len(texts):,} زوجًا نصيًا")
# --- (ج) بناء مجموعات نصوص التعرّض ---
def h(s): return hashlib.md5(s.encode()).hexdigest()
exact_ar=set(); exact_en=set(); mono_ar=set(); mono_en=set()
for i in par_idx:
a,e=texts[i]; exact_ar.add(h(a)); exact_en.add(h(e))
# للفرع الأحادي: النص الخام يُغذّى إلى augment() — تعرّض «مشتق» (نحتفظ بالنص الخام للمقارنة)
for i in mono_idx:
a,e=texts[i]
mono_ar.add(h(a)); mono_en.add(h(e))
log(f"نصوص تعرّض صريح: ar={len(exact_ar):,} en={len(exact_en):,} | مشتق: +ar={len(mono_ar-exact_ar):,} +en={len(mono_en-exact_en):,}")
# --- (د) العناصر المُقيَّمة: كم منها مُتعرَّض فعلًا؟ ---
sys.path.insert(0,"/home/user/lhc/recon")
exec(open('/home/user/lhc/recon/build_masks_stream.py').read().split('# ---------------- مجموعات التقييم')[0])
from phase_w1_data import download_corpus
DD="/home/user/lhc/data/opus"
OPUS=[("Tanzil","https://object.pouta.csc.fi/OPUS-Tanzil/v1/moses/ar-en.txt.zip",20000),
("Bible","https://object.pouta.csc.fi/OPUS-bible-uedin/v1/moses/ar-en.txt.zip",20000),
("NeuLab-TED","https://object.pouta.csc.fi/OPUS-NeuLab-TedTalks/v1/moses/ar-en.txt.zip",20000)]
pairs={}
for name,url,lim in OPUS: pairs[name]=download_corpus(name,url,lim,DD)
DEV="/home/user/lhc/data/flores101_dataset/devtest"
ld=lambda p:[l.strip() for l in open(p,encoding="utf-8") if l.strip()]
pairs["FLORES"]=[{"ar":a,"en":e} for a,e in zip(ld(f"{DEV}/ara.devtest"),ld(f"{DEV}/eng.devtest"))]
M=json.load(open("/home/user/lhc/results/masks_v2.json"))
def norm_h(side, s):
return h(norm_ar(s) if side=="ar" else norm_en(s))
# مجموعات مُطبَّعة للتعرّض (بمقارنة مُطبَّعة — أدق للاختلافات الشكلية)
nsexact_ar={norm_h("ar",texts[i][0]) for i in par_idx}
nsexact_en={norm_h("en",texts[i][1]) for i in par_idx}
nsmono_ar={norm_h("ar",texts[i][0]) for i in mono_idx}
nsmono_en={norm_h("en",texts[i][1]) for i in mono_idx}
report={"pairs_in_pool":n_pairs,"n_examples":N_EXAMPLES,"branch_counts":branch_counts,
"n_par_pairs":len(par_idx),"n_mono_pairs":len(mono_idx),
"sets":{}}
for cn,ps in pairs.items():
n=len(ps)
avail=set(M["masks_strong"][cn])
ex=0; ex_ar=0; ex_en=0; dv=0
for i,p in enumerate(ps):
ha=norm_h("ar",p["ar"]); he=norm_h("en",p["en"])
a_in = ha in nsexact_ar; e_in = he in nsexact_en
a_m = ha in nsmono_ar; e_m = he in nsmono_en
hit_exact = a_in or e_in
hit_deriv = (a_m or e_m)
if hit_exact: ex+=1
if a_in: ex_ar+=1
if e_in: ex_en+=1
if hit_exact or hit_deriv: dv+=1
report["sets"][cn]={"n":n,"available_mask":len(avail),
"exposed_exact":ex,"exposed_exact_ar":ex_ar,"exposed_exact_en":ex_en,
"exposed_exact_or_derived":dv,
"exposure_rate_pct":round(100*ex/n,3),
"availability_rate_pct":round(100*len(avail)/n,3),
"exposure_over_availability":round(ex/max(1,len(avail)),3) if avail else None}
log(f"{cn:12s} توافر={len(avail):>5} ({100*len(avail)/n:.2f}%) → تعرّض صريح={ex:>5} ({100*ex/n:.3f}%) | +مشتق={dv:>5}")
# --- (هـ) تحقق feat_cache (عدد النصوص الفريدة) ---
fc=np.load(f"{W4}/feat_cache.npz")
report["feat_cache"]={"n_texts":int(fc["n_texts"]),"rows_shape":list(fc["rows"].shape),
"example_texts_slots":int(fc["rows"].shape[0])}
log(f"feat_cache: n_texts={int(fc['n_texts']):,} rows={fc['rows'].shape}")
json.dump(report, open("/home/user/lhc/results/exposure_analysis.json","w"), ensure_ascii=False, indent=1)
log("SAVED results/exposure_analysis.json")
|