Upload analyze_emergent.py with huggingface_hub
Browse files- analyze_emergent.py +77 -0
analyze_emergent.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Emergent-deception analysis: do the model's OWN, un-instructed lies under a
|
| 2 |
+
goal incentive carry the same separable signature as instructed lies?
|
| 3 |
+
|
| 4 |
+
Sample is small by nature (aligned small models rarely lie emergently), so we
|
| 5 |
+
report it as preliminary, with a paired permutation test."""
|
| 6 |
+
import json, numpy as np
|
| 7 |
+
from sklearn.linear_model import LogisticRegression
|
| 8 |
+
from sklearn.preprocessing import StandardScaler
|
| 9 |
+
from sklearn.model_selection import LeaveOneOut
|
| 10 |
+
from sklearn.metrics import roc_auc_score
|
| 11 |
+
|
| 12 |
+
d = json.load(open("logs/rift_emergent_reps.json"))
|
| 13 |
+
Xlie, Xhon = [], []
|
| 14 |
+
per_model = {}
|
| 15 |
+
for m, v in d["data"].items():
|
| 16 |
+
nl = len(v["Xlie"])
|
| 17 |
+
per_model[m.split("/")[-1]] = {"lies": v["n_emergent_lie"],
|
| 18 |
+
"honest_under_incentive": v["n_honest_under_incentive"]}
|
| 19 |
+
Xlie += v["Xlie"]; Xhon += v["Xhon"]
|
| 20 |
+
Xlie = np.array(Xlie); Xhon = np.array(Xhon)
|
| 21 |
+
n = len(Xlie)
|
| 22 |
+
print("Per-model emergent behaviour:")
|
| 23 |
+
for k, v in per_model.items():
|
| 24 |
+
print(f" {k}: emergent_lies={v['lies']}, honest_under_incentive={v['honest_under_incentive']}")
|
| 25 |
+
total_incentive = sum(v["lies"] + v["honest_under_incentive"] for v in per_model.values())
|
| 26 |
+
print(f"\nTotal emergent lies (paired, clean): {n}")
|
| 27 |
+
print(f"Overall emergent-lie rate under incentive: {n}/{total_incentive} "
|
| 28 |
+
f"= {100*n/max(1,total_incentive):.0f}% (low = alignment resists emergent deception)")
|
| 29 |
+
|
| 30 |
+
if n < 3:
|
| 31 |
+
print("\nToo few emergent lies for any separability test.")
|
| 32 |
+
raise SystemExit
|
| 33 |
+
|
| 34 |
+
# Paired direction test: project each (lie, honest) onto the mean lie-honest
|
| 35 |
+
# axis fit on the OTHER pairs (leave-one-out) -> is lie scored higher?
|
| 36 |
+
X = np.vstack([Xlie, Xhon])
|
| 37 |
+
y = np.array([1]*n + [0]*n)
|
| 38 |
+
sc = StandardScaler().fit(X)
|
| 39 |
+
Xz = np.nan_to_num(sc.transform(X))
|
| 40 |
+
|
| 41 |
+
# Leave-one-pair-out: train on all but pair i, score pair i
|
| 42 |
+
correct = 0
|
| 43 |
+
lie_scores, hon_scores = [], []
|
| 44 |
+
for i in range(n):
|
| 45 |
+
mask = np.ones(2*n, bool)
|
| 46 |
+
mask[i] = False; mask[i+n] = False # drop both members of pair i
|
| 47 |
+
clf = LogisticRegression(C=1.0, max_iter=5000).fit(Xz[mask], y[mask])
|
| 48 |
+
s_lie = clf.decision_function(Xz[i:i+1])[0]
|
| 49 |
+
s_hon = clf.decision_function(Xz[i+n:i+n+1])[0]
|
| 50 |
+
lie_scores.append(s_lie); hon_scores.append(s_hon)
|
| 51 |
+
correct += int(s_lie > s_hon)
|
| 52 |
+
print(f"\nLeave-one-pair-out paired accuracy (lie scored above its honest twin): "
|
| 53 |
+
f"{correct}/{n} = {100*correct/n:.0f}%")
|
| 54 |
+
|
| 55 |
+
# permutation: how often does random pair-swapping match this?
|
| 56 |
+
rng = np.random.default_rng(0)
|
| 57 |
+
obs = correct
|
| 58 |
+
null = []
|
| 59 |
+
diffs = np.array(lie_scores) - np.array(hon_scores)
|
| 60 |
+
for _ in range(20000):
|
| 61 |
+
signs = rng.choice([1,-1], size=n)
|
| 62 |
+
null.append(int((diffs*signs > 0).sum() if False else (np.abs(diffs)*signs > 0).sum()))
|
| 63 |
+
# simpler sign-flip test on paired score differences
|
| 64 |
+
from scipy.stats import wilcoxon
|
| 65 |
+
try:
|
| 66 |
+
stat, p = wilcoxon(lie_scores, hon_scores, alternative="greater")
|
| 67 |
+
print(f"Wilcoxon (lie score > honest score, paired): p = {p:.4f}")
|
| 68 |
+
except Exception as e:
|
| 69 |
+
print("wilcoxon failed:", e)
|
| 70 |
+
|
| 71 |
+
# pooled AUC (optimistic, in-sample direction) for reference
|
| 72 |
+
clf_all = LogisticRegression(C=1.0, max_iter=5000).fit(Xz, y)
|
| 73 |
+
auc = roc_auc_score(y, clf_all.decision_function(Xz))
|
| 74 |
+
print(f"In-sample pooled AUC (optimistic): {auc:.3f}")
|
| 75 |
+
|
| 76 |
+
print("\nNOTE: n is small; treat as a preliminary directional signal, not a"
|
| 77 |
+
" powered result. The headline finding here is the LOW emergent-lie rate.")
|