Transcendental-Programmer
Refactor core logic: move and modularize all latent space, sampling, and utility code into faceforge_core/
e3af1ef
| import numpy as np | |
| from typing import Tuple, List, Optional | |
| from sklearn.decomposition import PCA | |
| from sklearn.linear_model import LogisticRegression | |
| class LatentDirectionFinder: | |
| """ | |
| Provides methods to discover semantic directions in latent space using PCA or classifier-based approaches. | |
| """ | |
| def __init__(self, latent_vectors: np.ndarray): | |
| """ | |
| :param latent_vectors: Array of shape (N, D) where N is the number of samples and D is the latent dimension. | |
| """ | |
| self.latent_vectors = latent_vectors | |
| def pca_direction(self, n_components: int = 10) -> Tuple[np.ndarray, np.ndarray]: | |
| """ | |
| Perform PCA on the latent vectors to find principal directions. | |
| :return: (components, explained_variance) | |
| """ | |
| pca = PCA(n_components=n_components) | |
| pca.fit(self.latent_vectors) | |
| return pca.components_, pca.explained_variance_ratio_ | |
| def classifier_direction(self, labels: List[int]) -> np.ndarray: | |
| """ | |
| Fit a linear classifier to find a direction separating two classes in latent space. | |
| :param labels: List of 0/1 labels for each latent vector. | |
| :return: Normalized direction vector (D,) | |
| """ | |
| clf = LogisticRegression() | |
| clf.fit(self.latent_vectors, labels) | |
| direction = clf.coef_[0] | |
| direction = direction / np.linalg.norm(direction) | |
| return direction |