(self, X)
return embedding
Transform X into the existing embedded space and return that
        transformed output.

        Parameters
        ----------
        X : array, shape (n_samples, n_features)
            New data to be transformed.

        Returns
        -------
        X_new : array, shape (n_samples, n_components)
            Embedding of the new data in low-dimensional space.
Transform X into the existing embedded space and return that
        transformed output.
Transform X into the existing embedded space and return that transformed output .
def transform(self, X):
        """Transform X into the existing embedded space and return that
        transformed output.

        Parameters
        ----------
        X : array, shape (n_samples, n_features)
            New data to be transformed.

        Returns
        -------
        X_new : array, shape (n_samples, n_components)
            Embedding of the new data in low-dimensional space.
        """
        # If we fit just a single instance then error
        if self._raw_data.shape[0] == 1:
            raise ValueError(
                "Transform unavailable when model was fit with only a single data sample."
            )
        # If we just have the original input then short circuit things
        X = check_array(X, dtype=np.float32, accept_sparse="csr", order="C")
        x_hash = joblib.hash(X)
        if x_hash == self._input_hash:
            if self.transform_mode == "embedding":
                return self.embedding_
            elif self.transform_mode == "graph":
                return self.graph_
            else:
                raise ValueError(
                    "Unrecognized transform mode {}; should be one of 'embedding' or 'graph'".format(
                        self.transform_mode
                    )
                )
        if self.densmap:
            raise NotImplementedError(
                "Transforming data into an existing embedding not supported for densMAP."
            )

        # X = check_array(X, dtype=np.float32, order="C", accept_sparse="csr")
        random_state = check_random_state(self.transform_seed)
        rng_state = random_state.randint(INT32_MIN, INT32_MAX, 3).astype(np.int64)

        if self.metric == "precomputed":
            warn(
                "Transforming new data with precomputed metric. "
                "We are assuming the input data is a matrix of distances from the new points "
                "to the points in the training set. If the input matrix is sparse, it should "
                "contain distances from the new points to their nearest neighbours "
                "or approximate nearest neighbours in the training set."
            )
            assert X.shape[1] == self._raw_data.shape[0]
            if scipy.sparse.issparse(X):
                indices = np.full(
                    (X.shape[0], self._n_neighbors), dtype=np.int32, fill_value=-1
                )
                dists = np.full_like(indices, dtype=np.float32, fill_value=-1)
                for i in range(X.shape[0]):
                    data_indices = np.argsort(X[i].data)
                    if len(data_indices) < self._n_neighbors:
                        raise ValueError(
                            f"Need at least n_neighbors ({self.n_neighbors}) distances for each row!"
                        )
                    indices[i] = X[i].indices[data_indices[: self._n_neighbors]]
                    dists[i] = X[i].data[data_indices[: self._n_neighbors]]
            else:
                indices = np.argsort(X, axis=1)[:, : self._n_neighbors].astype(np.int32)
                dists = np.take_along_axis(X, indices, axis=1)
            assert np.min(indices) >= 0 and np.min(dists) >= 0.0
        elif self._small_data:
            try:
                # sklearn pairwise_distances fails for callable metric on sparse data
                _m = self.metric if self._sparse_data else self._input_distance_func
                dmat = pairwise_distances(
                    X, self._raw_data, metric=_m, **self._metric_kwds
                )
            except (TypeError, ValueError):
                # metric is numba.jit'd or not supported by sklearn,
                # fallback to pairwise special
                if self._sparse_data:
                    # Get a fresh metric since we are casting to dense
                    if not callable(self.metric):
                        _m = dist.named_distances[self.metric]
                        dmat = dist.pairwise_special_metric(
                            X.toarray(),
                            self._raw_data.toarray(),
                            metric=_m,
                            kwds=self._metric_kwds,
                        )
                    else:
                        dmat = dist.pairwise_special_metric(
                            X,
                            self._raw_data,
                            metric=self._input_distance_func,
                            kwds=self._metric_kwds,
                        )
                else:
                    dmat = dist.pairwise_special_metric(
                        X,
                        self._raw_data,
                        metric=self._input_distance_func,
                        kwds=self._metric_kwds,
                    )
            indices = np.argpartition(dmat, self._n_neighbors)[:, : self._n_neighbors]
            dmat_shortened = submatrix(dmat, indices, self._n_neighbors)
            indices_sorted = np.argsort(dmat_shortened)
            indices = submatrix(indices, indices_sorted, self._n_neighbors)
            dists = submatrix(dmat_shortened, indices_sorted, self._n_neighbors)
        else:
            epsilon = 0.24 if self._knn_search_index._angular_trees else 0.12
            indices, dists = self._knn_search_index.query(
                X, self.n_neighbors, epsilon=epsilon
            )

        dists = dists.astype(np.float32, order="C")
        # Remove any nearest neighbours who's distances are greater than our disconnection_distance
        indices[dists >= self._disconnection_distance] = -1
        adjusted_local_connectivity = max(0.0, self.local_connectivity - 1.0)
        sigmas, rhos = smooth_knn_dist(
            dists,
            float(self._n_neighbors),
            local_connectivity=float(adjusted_local_connectivity),
        )

        rows, cols, vals, dists = compute_membership_strengths(
            indices, dists, sigmas, rhos, bipartite=True
        )

        graph = scipy.sparse.coo_matrix(
            (vals, (rows, cols)), shape=(X.shape[0], self._raw_data.shape[0])
        )

        if self.transform_mode == "graph":
            return graph

        # This was a very specially constructed graph with constant degree.
        # That lets us do fancy unpacking by reshaping the csr matrix indices
        # and data. Doing so relies on the constant degree assumption!
        # csr_graph = normalize(graph.tocsr(), norm="l1")
        # inds = csr_graph.indices.reshape(X.shape[0], self._n_neighbors)
        # weights = csr_graph.data.reshape(X.shape[0], self._n_neighbors)
        # embedding = init_transform(inds, weights, self.embedding_)
        # This is less fast code than the above numba.jit'd code.
        # It handles the fact that our nearest neighbour graph can now contain variable numbers of vertices.
        csr_graph = graph.tocsr()
        csr_graph.eliminate_zeros()
        embedding = init_graph_transform(csr_graph, self.embedding_)

        if self.n_epochs is None:
            # For smaller datasets we can use more epochs
            if graph.shape[0] <= 10000:
                n_epochs = 100
            else:
                n_epochs = 30
        else:
            n_epochs = int(self.n_epochs // 3.0)

        graph.data[graph.data < (graph.data.max() / float(n_epochs))] = 0.0
        graph.eliminate_zeros()

        epochs_per_sample = make_epochs_per_sample(graph.data, n_epochs)

        head = graph.row
        tail = graph.col
        weight = graph.data

        # optimize_layout = make_optimize_layout(
        #     self._output_distance_func,
        #     tuple(self.output_metric_kwds.values()),
        # )

        if self.output_metric == "euclidean":
            embedding = optimize_layout_euclidean(
                embedding,
                self.embedding_.astype(np.float32, copy=True),  # Fixes #179 & #217,
                head,
                tail,
                n_epochs,
                graph.shape[1],
                epochs_per_sample,
                self._a,
                self._b,
                rng_state,
                self.repulsion_strength,
                self._initial_alpha / 4.0,
                self.negative_sample_rate,
                self.random_state is None,
                verbose=self.verbose,
                tqdm_kwds=self.tqdm_kwds,
            )
        else:
            embedding = optimize_layout_generic(
                embedding,
                self.embedding_.astype(np.float32, copy=True),  # Fixes #179 & #217
                head,
                tail,
                n_epochs,
                graph.shape[1],
                epochs_per_sample,
                self._a,
                self._b,
                rng_state,
                self.repulsion_strength,
                self._initial_alpha / 4.0,
                self.negative_sample_rate,
                self._output_distance_func,
                tuple(self._output_metric_kwds.values()),
                verbose=self.verbose,
                tqdm_kwds=self.tqdm_kwds,
            )

        return embedding
def transform ( self , X ) : # If we fit just a single instance then error if self . _raw_data . shape [ 0 ] == 1 : raise ValueError ( "Transform unavailable when model was fit with only a single data sample." ) # If we just have the original input then short circuit things X = check_array ( X , dtype = np . float32 , accept_sparse = "csr" , order = "C" ) x_hash = joblib . hash ( X ) if x_hash == self . _input_hash : if self . transform_mode == "embedding" : return self . embedding_ elif self . transform_mode == "graph" : return self . graph_ else : raise ValueError ( "Unrecognized transform mode {}; should be one of 'embedding' or 'graph'" . format ( self . transform_mode ) ) if self . densmap : raise NotImplementedError ( "Transforming data into an existing embedding not supported for densMAP." ) # X = check_array(X, dtype=np.float32, order="C", accept_sparse="csr") random_state = check_random_state ( self . transform_seed ) rng_state = random_state . randint ( INT32_MIN , INT32_MAX , 3 ) . astype ( np . int64 ) if self . metric == "precomputed" : warn ( "Transforming new data with precomputed metric. " "We are assuming the input data is a matrix of distances from the new points " "to the points in the training set. If the input matrix is sparse, it should " "contain distances from the new points to their nearest neighbours " "or approximate nearest neighbours in the training set." ) assert X . shape [ 1 ] == self . _raw_data . shape [ 0 ] if scipy . sparse . issparse ( X ) : indices = np . full ( ( X . shape [ 0 ] , self . _n_neighbors ) , dtype = np . int32 , fill_value = - 1 ) dists = np . full_like ( indices , dtype = np . float32 , fill_value = - 1 ) for i in range ( X . shape [ 0 ] ) : data_indices = np . argsort ( X [ i ] . data ) if len ( data_indices ) < self . _n_neighbors : raise ValueError ( f"Need at least n_neighbors ({self.n_neighbors}) distances for each row!" ) indices [ i ] = X [ i ] . indices [ data_indices [ : self . _n_neighbors ] ] dists [ i ] = X [ i ] . data [ data_indices [ : self . _n_neighbors ] ] else : indices = np . argsort ( X , axis = 1 ) [ : , : self . _n_neighbors ] . astype ( np . int32 ) dists = np . take_along_axis ( X , indices , axis = 1 ) assert np . min ( indices ) >= 0 and np . min ( dists ) >= 0.0 elif self . _small_data : try : # sklearn pairwise_distances fails for callable metric on sparse data _m = self . metric if self . _sparse_data else self . _input_distance_func dmat = pairwise_distances ( X , self . _raw_data , metric = _m , * * self . _metric_kwds ) except ( TypeError , ValueError ) : # metric is numba.jit'd or not supported by sklearn, # fallback to pairwise special if self . _sparse_data : # Get a fresh metric since we are casting to dense if not callable ( self . metric ) : _m = dist . named_distances [ self . metric ] dmat = dist . pairwise_special_metric ( X . toarray ( ) , self . _raw_data . toarray ( ) , metric = _m , kwds = self . _metric_kwds , ) else : dmat = dist . pairwise_special_metric ( X , self . _raw_data , metric = self . _input_distance_func , kwds = self . _metric_kwds , ) else : dmat = dist . pairwise_special_metric ( X , self . _raw_data , metric = self . _input_distance_func , kwds = self . _metric_kwds , ) indices = np . argpartition ( dmat , self . _n_neighbors ) [ : , : self . _n_neighbors ] dmat_shortened = submatrix ( dmat , indices , self . _n_neighbors ) indices_sorted = np . argsort ( dmat_shortened ) indices = submatrix ( indices , indices_sorted , self . _n_neighbors ) dists = submatrix ( dmat_shortened , indices_sorted , self . _n_neighbors ) else : epsilon = 0.24 if self . _knn_search_index . _angular_trees else 0.12 indices , dists = self . _knn_search_index . query ( X , self . n_neighbors , epsilon = epsilon ) dists = dists . astype ( np . float32 , order = "C" ) # Remove any nearest neighbours who's distances are greater than our disconnection_distance indices [ dists >= self . _disconnection_distance ] = - 1 adjusted_local_connectivity = max ( 0.0 , self . local_connectivity - 1.0 ) sigmas , rhos = smooth_knn_dist ( dists , float ( self . _n_neighbors ) , local_connectivity = float ( adjusted_local_connectivity ) , ) rows , cols , vals , dists = compute_membership_strengths ( indices , dists , sigmas , rhos , bipartite = True ) graph = scipy . sparse . coo_matrix ( ( vals , ( rows , cols ) ) , shape = ( X . shape [ 0 ] , self . _raw_data . shape [ 0 ] ) ) if self . transform_mode == "graph" : return graph # This was a very specially constructed graph with constant degree. # That lets us do fancy unpacking by reshaping the csr matrix indices # and data. Doing so relies on the constant degree assumption! # csr_graph = normalize(graph.tocsr(), norm="l1") # inds = csr_graph.indices.reshape(X.shape[0], self._n_neighbors) # weights = csr_graph.data.reshape(X.shape[0], self._n_neighbors) # embedding = init_transform(inds, weights, self.embedding_) # This is less fast code than the above numba.jit'd code. # It handles the fact that our nearest neighbour graph can now contain variable numbers of vertices. csr_graph = graph . tocsr ( ) csr_graph . eliminate_zeros ( ) embedding = init_graph_transform ( csr_graph , self . embedding_ ) if self . n_epochs is None : # For smaller datasets we can use more epochs if graph . shape [ 0 ] <= 10000 : n_epochs = 100 else : n_epochs = 30 else : n_epochs = int ( self . n_epochs // 3.0 ) graph . data [ graph . data < ( graph . data . max ( ) / float ( n_epochs ) ) ] = 0.0 graph . eliminate_zeros ( ) epochs_per_sample = make_epochs_per_sample ( graph . data , n_epochs ) head = graph . row tail = graph . col weight = graph . data # optimize_layout = make_optimize_layout( #     self._output_distance_func, #     tuple(self.output_metric_kwds.values()), # ) if self . output_metric == "euclidean" : embedding = optimize_layout_euclidean ( embedding , self . embedding_ . astype ( np . float32 , copy = True ) , # Fixes #179 & #217, head , tail , n_epochs , graph . shape [ 1 ] , epochs_per_sample , self . _a , self . _b , rng_state , self . repulsion_strength , self . _initial_alpha / 4.0 , self . negative_sample_rate , self . random_state is None , verbose = self . verbose , tqdm_kwds = self . tqdm_kwds , ) else : embedding = optimize_layout_generic ( embedding , self . embedding_ . astype ( np . float32 , copy = True ) , # Fixes #179 & #217 head , tail , n_epochs , graph . shape [ 1 ] , epochs_per_sample , self . _a , self . _b , rng_state , self . repulsion_strength , self . _initial_alpha / 4.0 , self . negative_sample_rate , self . _output_distance_func , tuple ( self . _output_metric_kwds . values ( ) ) , verbose = self . verbose , tqdm_kwds = self . tqdm_kwds , ) return embedding