'Opposite of the Local Outlier Factor of X (as bigger is better,
i.e. large values correspond to inliers).
The argument X is supposed to contain *new data*: if X contains a
point from training, it consider the later in its own neighborhood.
Also, the samples in X are not considered in the neighborhood of any
point.
The decision function on training data is available by considering the
opposite of the negative_outlier_factor_ attribute.
Parameters
X : array-like, shape (n_samples, n_features)
The query sample or samples to compute the Local Outlier Factor
w.r.t. the training samples.
Returns
opposite_lof_scores : array, shape (n_samples,)
The opposite of the Local Outlier Factor of each input samples.
The lower, the more abnormal.'

def _decision_function(self, X):

    check_is_fitted(self, ['threshold_', 'negative_outlier_factor_', '_distances_fit_X_'])
    X = check_array(X, accept_sparse='csr')
    (distances_X, neighbors_indices_X) = self.kneighbors(X, n_neighbors=self.n_neighbors_)
    X_lrd = self._local_reachability_density(distances_X, neighbors_indices_X)
    lrd_ratios_array = (self._lrd[neighbors_indices_X] / X_lrd[:, np.newaxis])
    return (- np.mean(lrd_ratios_array, axis=1))
