Spaces:
Running
Running
| """M4 — LAT: Linear Artificial Tomography — SVM decision boundary direction.""" | |
| import numpy as np | |
| from sklearn.svm import LinearSVC | |
| from sklearn.preprocessing import StandardScaler | |
| from src.methods.base import SteeringMethod | |
| class LAT(SteeringMethod): | |
| """LAT — SVM decision boundary as steering direction.""" | |
| def name(self) -> str: | |
| return "LAT" | |
| def method_id(self) -> str: | |
| return "M4" | |
| def extract_vector( | |
| self, | |
| h_pos: np.ndarray, | |
| h_neg: np.ndarray, | |
| **kwargs, | |
| ) -> np.ndarray: | |
| """Compute SVM decision boundary direction. | |
| Args: | |
| h_pos: (N_pos, d) positive activations | |
| h_neg: (N_neg, d) negative activations | |
| Returns: | |
| (d,) normal vector to SVM decision boundary | |
| """ | |
| X = np.concatenate([h_pos, h_neg], axis=0) | |
| y = np.concatenate([ | |
| np.ones(len(h_pos)), | |
| np.zeros(len(h_neg)), | |
| ]) | |
| # Standardise for numeric stability | |
| scaler = StandardScaler() | |
| X_scaled = scaler.fit_transform(X) | |
| C = kwargs.get("C", 1.0) | |
| max_iter = kwargs.get("max_iter", 5000) | |
| svm = LinearSVC(C=C, max_iter=max_iter, dual="auto") | |
| svm.fit(X_scaled, y) | |
| # Get weight vector in original (unscaled) space | |
| w = svm.coef_[0] / scaler.scale_ | |
| # Normalise to unit vector | |
| w = w / (np.linalg.norm(w) + 1e-8) | |
| return w | |