def _get_pairwise_affinities(self, X): """Computes pairwise affinities.""" affines = np.zeros((self.n_samples, self.n_samples), dtype=np.float32) target_entropy = np.log(self.perplexity) distances = l2_distance(X) for i in range(self.n_samples): affines[i, :] = self._binary_search(distances[i], target_entropy) # Fill diagonal with near zero value np.fill_diagonal(affines, 1.0e-12) affines = affines.clip(min=1e-100) affines = (affines + affines.T) / (2 * self.n_samples) return affines
def _get_pairwise_affinities(self, X): """Computes pairwise affinities.""" affines = np.zeros((self.n_samples, self.n_samples), dtype=np.float32) target_entropy = np.log(self.perplexity) distances = l2_distance(X) for i in range(self.n_samples): affines[i, :] = self._binary_search(distances[i], target_entropy) # Fill diagonal with near zero value np.fill_diagonal(affines, 1.e-12) affines = affines.clip(min=1e-100) affines = (affines + affines.T) / (2 * self.n_samples) return affines
def fit_transform(self, X, y=None): self._setup_input(X, y) Y = np.random.randn(self.n_samples, self.n_components) velocity = np.zeros_like(Y) gains = np.ones_like(Y) P = self._get_pairwise_affinities(X) iter_num = 0 while iter_num < self.max_iter: iter_num += 1 D = l2_distance(Y) Q = self._q_distribution(D) # Normalizer q distribution Q_n = Q / np.sum(Q) # Early exaggeration & momentum pmul = 4.0 if iter_num < 100 else 1.0 momentum = 0.5 if iter_num < 20 else 0.8 # Perform gradient step grads = np.zeros(Y.shape) for i in range(self.n_samples): grad = 4 * np.dot((pmul * P[i] - Q_n[i]) * Q[i], Y[i] - Y) grads[i] = grad gains = (gains + 0.2) * ((grads > 0) != (velocity > 0)) + (gains * 0.8) * ( (grads > 0) == (velocity > 0)) gains = gains.clip(min=self.min_gain) velocity = momentum * velocity - self.lr * (gains * grads) Y += velocity Y = Y - np.mean(Y, 0) error = np.sum(P * np.log(P / Q_n)) logging.info("Iteration %s, error %s" % (iter_num, error)) return Y
def fit_transform(self, X, y=None): self._setup_input(X, y) Y = np.random.randn(self.n_samples, self.n_components) velocity = np.zeros_like(Y) gains = np.ones_like(Y) P = self._get_pairwise_affinities(X) iter_num = 0 while iter_num < self.max_iter: iter_num += 1 D = l2_distance(Y) Q = self._q_distribution(D) # Normalizer q distribution Q_n = Q / np.sum(Q) # Early exaggeration & momentum pmul = 4.0 if iter_num < 100 else 1.0 momentum = 0.5 if iter_num < 20 else 0.8 # Perform gradient step grads = np.zeros(Y.shape) for i in range(self.n_samples): grad = 4 * np.dot((pmul * P[i] - Q_n[i]) * Q[i], Y[i] - Y) grads[i] = grad gains = (gains + 0.2) * ((grads > 0) != (velocity > 0)) + (gains * 0.8) * ((grads > 0) == (velocity > 0)) gains = gains.clip(min=self.min_gain) velocity = momentum * velocity - self.lr * (gains * grads) Y += velocity Y = Y - np.mean(Y, 0) error = np.sum(P * np.log(P / Q_n)) logging.info("Iteration %s, error %s" % (iter_num, error)) return Y