'Fit the model using X as training data.
Note that sparse arrays can only be handled by method=\'exact\'.
It is recommended that you convert your sparse array to dense
(e.g. `X.toarray()`) if it fits in memory, or otherwise using a
dimensionality reduction technique (e.g. TruncatedSVD).
Parameters
X : array, shape (n_samples, n_features) or (n_samples, n_samples)
If the metric is \'precomputed\' X must be a square distance
matrix. Otherwise it contains a sample per row. Note that this
when method=\'barnes_hut\', X cannot be a sparse array and if need be
will be converted to a 32 bit float array. Method=\'exact\' allows
sparse arrays and 64bit floating point inputs.
skip_num_points : int (optional, default:0)
This does not compute the gradient for points with indices below
`skip_num_points`. This is useful when computing transforms of new
data where you\'d like to keep the old data fixed.'

def _fit(self, X, skip_num_points=0):

    if (self.method not in ['barnes_hut', 'exact']):
        raise ValueError("'method'    must    be    'barnes_hut'    or    'exact'")
    if ((self.angle < 0.0) or (self.angle > 1.0)):
        raise ValueError("'angle'    must    be    between    0.0    -    1.0")
    if (self.metric == 'precomputed'):
        if (isinstance(self.init, string_types) and (self.init == 'pca')):
            raise ValueError('The    parameter    init="pca"    cannot    be    used    with    metric="precomputed".')
        if (X.shape[0] != X.shape[1]):
            raise ValueError('X    should    be    a    square    distance    matrix')
        if np.any((X < 0)):
            raise ValueError('All    distances    should    be    positive,    the    precomputed    distances    given    as    X    is    not    correct')
    if ((self.method == 'barnes_hut') and sp.issparse(X)):
        raise TypeError('A    sparse    matrix    was    passed,    but    dense    data    is    required    for    method="barnes_hut".    Use    X.toarray()    to    convert    to    a    dense    numpy    array    if    the    array    is    small    enough    for    it    to    fit    in    memory.    Otherwise    consider    dimensionality    reduction    techniques    (e.g.    TruncatedSVD)')
    else:
        X = check_array(X, accept_sparse=['csr', 'csc', 'coo'], dtype=[np.float32, np.float64])
    if ((self.method == 'barnes_hut') and (self.n_components > 3)):
        raise ValueError("'n_components'    should    be    inferior    to    4    for    the    barnes_hut    algorithm    as    it    relies    on    quad-tree    or    oct-tree.")
    random_state = check_random_state(self.random_state)
    if (self.early_exaggeration < 1.0):
        raise ValueError('early_exaggeration    must    be    at    least    1,    but    is    {}'.format(self.early_exaggeration))
    if (self.n_iter < 250):
        raise ValueError('n_iter    should    be    at    least    250')
    n_samples = X.shape[0]
    neighbors_nn = None
    if (self.method == 'exact'):
        if (self.metric == 'precomputed'):
            distances = X
        else:
            if self.verbose:
                print '[t-SNE]    Computing    pairwise    distances...'
            if (self.metric == 'euclidean'):
                distances = pairwise_distances(X, metric=self.metric, squared=True)
            else:
                distances = pairwise_distances(X, metric=self.metric)
            if np.any((distances < 0)):
                raise ValueError('All    distances    should    be    positive,    the    metric    given    is    not    correct')
        P = _joint_probabilities(distances, self.perplexity, self.verbose)
        assert np.all(np.isfinite(P)), 'All    probabilities    should    be    finite'
        assert np.all((P >= 0)), 'All    probabilities    should    be    non-negative'
        assert np.all((P <= 1)), 'All    probabilities    should    be    less    or    then    equal    to    one'
    else:
        k = min((n_samples - 1), int(((3.0 * self.perplexity) + 1)))
        if self.verbose:
            print '[t-SNE]    Computing    {}    nearest    neighbors...'.format(k)
        neighbors_method = 'ball_tree'
        if (self.metric == 'precomputed'):
            neighbors_method = 'brute'
        knn = NearestNeighbors(algorithm=neighbors_method, n_neighbors=k, metric=self.metric)
        t0 = time()
        knn.fit(X)
        duration = (time() - t0)
        if self.verbose:
            print '[t-SNE]    Indexed    {}    samples    in    {:.3f}s...'.format(n_samples, duration)
        t0 = time()
        (distances_nn, neighbors_nn) = knn.kneighbors(None, n_neighbors=k)
        duration = (time() - t0)
        if self.verbose:
            print '[t-SNE]    Computed    neighbors    for    {}    samples    in    {:.3f}s...'.format(n_samples, duration)
        del knn
        if (self.metric == 'euclidean'):
            distances_nn **= 2
        P = _joint_probabilities_nn(distances_nn, neighbors_nn, self.perplexity, self.verbose)
    if isinstance(self.init, np.ndarray):
        X_embedded = self.init
    elif (self.init == 'pca'):
        pca = PCA(n_components=self.n_components, svd_solver='randomized', random_state=random_state)
        X_embedded = pca.fit_transform(X).astype(np.float32, copy=False)
    elif (self.init == 'random'):
        X_embedded = (0.0001 * random_state.randn(n_samples, self.n_components).astype(np.float32))
    else:
        raise ValueError("'init'    must    be    'pca',    'random',    or    a    numpy    array")
    degrees_of_freedom = max((self.n_components - 1.0), 1)
    return self._tsne(P, degrees_of_freedom, n_samples, random_state, X_embedded=X_embedded, neighbors=neighbors_nn, skip_num_points=skip_num_points)
