From c3a2e2760c531503df9a252298312fed49bf0094 Mon Sep 17 00:00:00 2001 From: Bamdad Dashtban Date: Mon, 13 Jul 2026 12:37:20 +0100 Subject: [PATCH] Make ControlVector.train() deterministic read_representations fits PCA(n_components=1) with the default svd_solver='auto', which selects the randomized SVD solver for hidden-state widths (>500 features). That solver is unseeded (random_state=None), so identical inputs produce different directions across runs. svd_solver='full' is exact and deterministic, and negligibly priced at n_components=1. Fixes #78 --- repeng/extract.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/repeng/extract.py b/repeng/extract.py index 80cb541..6c74541 100644 --- a/repeng/extract.py +++ b/repeng/extract.py @@ -316,7 +316,10 @@ def read_representations( if method != "umap": # shape (1, n_features) - pca_model = PCA(n_components=1, whiten=False).fit(train) + # svd_solver="full" is exact and deterministic. The default "auto" + # picks the randomized solver for hidden-state dims (>500 features), + # which is unseeded and makes train() non-reproducible run to run. + pca_model = PCA(n_components=1, whiten=False, svd_solver="full").fit(train) # shape (n_features,) directions[layer] = pca_model.components_.astype(np.float32).squeeze(axis=0) else: