Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MRG+2] LOF algorithm (Anomaly Detection) #5279

Merged
merged 18 commits into from Oct 25, 2016
Merged

[MRG+2] LOF algorithm (Anomaly Detection) #5279

merged 18 commits into from Oct 25, 2016

Conversation

@ngoix
Copy link
Contributor

@ngoix ngoix commented Sep 16, 2015

@agramfort
Copy link
Member

@agramfort agramfort commented Sep 16, 2015

thanks for the early PR

let me know when you need a review ie when you addressed the standard things (tests, example, some basic doc)

@jmschrei
Copy link
Member

@jmschrei jmschrei commented Sep 21, 2015

I'd also be interested in reviewing this when you've moved past the WIP stage.

@ngoix
Copy link
Contributor Author

@ngoix ngoix commented Oct 9, 2015

I think it is ready for a first review @agramfort @jmschrei !

__all__ = ["LOF"]


class LOFMixin(object):

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

why do you need a mixin here?

I would put all methods from Mixin into LOF class and make them private.

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

I agree. Mixins imply that multiple estimators will be using them,

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

Ok

"""
def __init__(self, n_neighbors=5, algorithm='auto', leaf_size=30,
metric='minkowski', p=2, metric_params=None,
n_jobs=1, **kwargs):

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

**kwargs in init are not ok. why do you need this?

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

Ok I will remove it.

metric_params=metric_params, n_jobs=n_jobs, **kwargs)

def predict(self, X=None, n_neighbors=None):
"""Predict LOF score of X.

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

empty line missing

leaf_size=leaf_size, metric=metric, p=p,
metric_params=metric_params, n_jobs=n_jobs, **kwargs)

def predict(self, X=None, n_neighbors=None):

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

predict signature should be

def predict(self, X):

that's it

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

@agramfort mentions this, but X must be provided in predict methods.

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

discussion below ? predict must not be able to handle X=None?

Parameters
----------

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

remove line

X : array-like, last dimension same as that of fit data, optional
(default=None)
The querry sample or samples to compute the LOF wrt to the training

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

bad indent

Returns
-------
lof_scores : array of shape (n_samples,)
The LOF score of each input samples. The lower, the more normal.

This comment has been minimized.

@agramfort

agramfort Oct 9, 2015
Member

indent


def k_distance(self, X=None):
"""
Compute the k_distance and the neighborhood of querry samples X wrt

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

This isn't a terribly informative docstring. It doesn't define what k_distance is, or what self._fit_X is. Maybe change it to describe things in terms of the algorithm, irrespective of the underlying implementation. Also, query not querry.

Parameters
----------

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

remove line

Parameters
----------

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

remove line

# Test LOF
clf = neighbors.LOF()
clf.fit(X)
pred = clf.predict()

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

Predict must take in values to predict anomalies in.

clf = neighbors.LOF()
clf.fit(X)
pred = clf.predict()
assert_array_equal(clf._fit_X, X)

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

The ranking of samples as to their anomaly status must be easily received by the user; usually returned by the predict method. Having to do in and get an attribute is not okay.

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

Sorry I don't see your point, the ranking is received directly in pred...
clf._fit_X is just the training samples (defined in the base estimator NeighborsBase), the user doesn't see or need it...

"""
distances, neighbors_indices = self.kneighbors(
X=X, n_neighbors=self.n_neighbors)
neighbors_indices = neighbors_indices

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

What is the point of this line?

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

Right thanks!

The LRD of p.
"""

p_0 = self._fit_X if p is None else p

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

You should have to explicitly pass in a dataset to this function.

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

discussion below


neighbors_indices = self.neighbors_indices_fit_X_ if p is None else self.k_distance(p)[1]

n_jobs = _get_n_jobs(self.n_jobs)

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

When you merge this into the LOF class, just call _get_n_jobs once in the __init__ function.

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

Ok

dist = pairwise_distances(p_0, self._fit_X,
self.effective_metric_,
n_jobs=n_jobs,
**self.effective_metric_params_)

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

What is **self.effective_metric_params_?

lrd = p_lrd if p is None else self.local_reachability_density(p=None)

for j in range(p_0.shape[0]):
cpt = -1

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

I don't understand what's going on with this cpt variable

This comment has been minimized.

@ngoix

ngoix Oct 12, 2015
Author Contributor

I rename it neighbors_number.

Parameters
----------
p : array-like of shape (n_samples, n_features)

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

p should be named X

p_lrd = self.local_reachability_density(p)
lrd_ratios_array = np.zeros((p_0.shape[0], self.n_neighbors))

# Avoid re-computing p_lrd if p is None:

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

p should never be None



class LOF(NeighborsBase, KNeighborsMixin, LOFMixin, UnsupervisedMixin):
"""Unsupervised Outlier Detection.

This comment has been minimized.

@jmschrei

jmschrei Oct 9, 2015
Member

I like the documentation.

@jmschrei
Copy link
Member

@jmschrei jmschrei commented Oct 9, 2015

I would like to see some more extensive unit tests, particularly in cases where the algorithm should fail (wrong dimensions or other incorrect types of data passed in). I'll be able to look more at the performance of the code once you merge the mixin with the other class, and change the API to always take in an X matrix.

@jmschrei
Copy link
Member

@jmschrei jmschrei commented Oct 9, 2015

I'd also like to see an example of it performing against a/many current algorithm(s), so that it is clear it is a valuable contribution.

@ngoix
Copy link
Contributor Author

@ngoix ngoix commented Oct 12, 2015

If you have a dataset X and want to remove outliers from it, you don't want to do

fit(X)
predict(X)

because then each sample is considered in its own neighbourhoud: in predict(X), X is considered as 'new observations'.

What the user wants is:

for each x in X,
fit(X-{x})
predict(x)

which is allowed by

fit(X)
predict()

It is like looking for k-nearest-neighbors of points in a dataset X: you can do:

neigh = NearestNeighbors()
neigh.fit(X)
neigh.kneighbors()

which is different from

neigh = NearestNeighbors()
neigh.fit(X)
neigh.kneighbors(X)

I can make predict() have as signature

def predict(self, X):

and allows taking X=None in argument... Is it allowed ?

@agramfort
Copy link
Member

@agramfort agramfort commented Oct 12, 2015

If you have a dataset X and want to remove outliers from it, you don't want to do

fit(X)
predict(X)

implement a fit_predict(X) method is the way to go.

@ngoix
Copy link
Contributor Author

@ngoix ngoix commented Oct 12, 2015

Ok thanks !

@ngoix
Copy link
Contributor Author

@ngoix ngoix commented Oct 12, 2015

I merged the mixin with LOF class, changed the API and added a comparison example.
@agramfort @jmschrei what do you think?

clf.fit(X)
y_pred = clf.decision_function(X).ravel()

if clf_name=="Local Outlier Factor":

This comment has been minimized.

ngoix added 2 commits Oct 18, 2016
@ngoix ngoix force-pushed the ngoix:lof branch from ed1ab7e to 8337597 Oct 19, 2016
@ngoix
Copy link
Contributor Author

@ngoix ngoix commented Oct 19, 2016

done!

@agramfort
Copy link
Member

@agramfort agramfort commented Oct 20, 2016

@amueller want to take a final look?

for me it's good enough to merge

Copy link
Member

@amueller amueller left a comment

I think caching the LRD on the training set would be good (and actually make the code easier to follow). I think either predict and decision_function should both be private or neither. I kinda tend towards both, as making public is easier than hiding.
The rest is mostly minor, though how to tune n_neighbors seems pretty important.

Returns
-------
lof_scores : array, shape (n_samples,)
The Local Outlier Factor of each input samples. The lower,

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

This seems to contradict the title of the docstring.

This comment has been minimized.

@ngoix

ngoix Oct 22, 2016
Author Contributor

Yes it is -lof_scores

return is_inlier

def decision_function(self, X):
"""Opposite of the Local Outlier Factor of X (as bigger is better).

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

I think the docstring should be more explicit. Is low outlier or high outlier?
Actually, to be consistent with the other estimators, I think negative needs to be outlier.

This comment has been minimized.

@ngoix

ngoix Oct 22, 2016
Author Contributor

I don't think so, for all the decision functions, bigger is better (large values correspond to inliers). For prediction, negative values (-1) correspond to outliers though. (It's true that this is a bit odd)

@@ -18,6 +18,9 @@
hence more adapted to large-dimensional settings, even if it performs
quite well in the examples below.
- using the Local Outlier Factor to measure the local deviation of a given

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

It's kinda odd that this example lives in this folder... but whatever..

This comment has been minimized.

@ngoix

ngoix Oct 22, 2016
Author Contributor

Yes very weird! it is the folder of the first outlier detection algorithm in scikit-learn.


# Avoid re-computing X_lrd if same parameters:
if not (np.all(distances_X == self._distances_fit_X_) *
np.all(self._neighbors_indices_fit_X_ == neighbors_indices_X)):

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

this == raises a deprecation warning

/home/andy/checkout/scikit-learn/sklearn/neighbors/lof.py:279: DeprecationWarning: elementwise == comparison failed; this will raise an error in the future.
np.all(self.neighbors_indices_fit_X == neighbors_indices_X)):

This means they have different size, I think. So I guess you should check the shape first?

Also happens for the line above.

The question is not, how isolated the sample is, but how isolated it is
with respect to the surrounding neighborhood.

This strategy is illustrated below.

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

I don't feel that the example illustrates the point that was just made about the different densities. I'm fine to leave it as-is but I don't get a good idea of the global vs local. It would be nice to also illustrate a failure mode maybe?

This comment has been minimized.

@ngoix

ngoix Oct 22, 2016
Author Contributor

No global vs local anymore!

# Avoid re-computing X_lrd if same parameters:
if not (np.all(distances_X == self._distances_fit_X_) *
np.all(self._neighbors_indices_fit_X_ == neighbors_indices_X)):
lrd = self._local_reachability_density(

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

It seems that lrd is "small" compared to _distances_fit_X_ and _neighbors_indices_fit_X_. Why not compute it in fit and store it once and for all? You are currently recomputing it on every call to _local_outlier_factor.

Parameters
----------
distances_X : array, shape (n_query, self.n_neighbors)
Distances to the neighbors (in the training samples self._fit_X) of

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

I would put backticks around _fit_X to be save ;)

This comment has been minimized.

@ngoix

ngoix Oct 24, 2016
Author Contributor

Do you mean replacing self._fit_X by self._fit_X or self._fit_X or just by _fit_X? I don't understand the purpose...

This comment has been minimized.

@amueller

amueller Oct 24, 2016
Member

I meant putting backticks around self._fit_X. a) for nicer highlighting b) I'm not sure sphinx will render the current version correctly because of the underscore. But I might be paranoid.

score = clf.fit(X).outlier_factor_
assert_array_equal(clf._fit_X, X)

# Assert scores are good:

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

Assert smallest outlier score is is greater than largest inlier score

This comment has been minimized.

@ngoix

ngoix Oct 23, 2016
Author Contributor

ok

clf = neighbors.LocalOutlierFactor().fit(X_train)

# predict scores (the lower, the more normal)
y_pred = - clf.decision_function(X_test)

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

I would find it more natural to give the outliers the negative label. If you want to leave it like this, remove space after -

This comment has been minimized.

@ngoix

ngoix Oct 23, 2016
Author Contributor

I agree but this is to be consistent with OneClassSVM, EllipticEnvelop and IsolationForest.

distance between them. This works for Scipy's metrics, but is less
efficient than passing the metric name as a string.
Distance matrices are not supported.

This comment has been minimized.

@amueller

amueller Oct 20, 2016
Member

I don't understand this comment.

@ngoix ngoix force-pushed the ngoix:lof branch 4 times, most recently from 95036df to 662ed9c Oct 24, 2016
@ngoix ngoix force-pushed the ngoix:lof branch from 662ed9c to 6500640 Oct 24, 2016
clf = neighbors.LocalOutlierFactor().fit(X_train)

# predict scores (the lower, the more normal)
y_pred = -clf.decision_function(X_test)

This comment has been minimized.

@amueller

amueller Oct 24, 2016
Member

I meant changing y_test to be [0] * 20 + [-1] * 20 and then remove the -


return self

def _predict(self, X=None):

This comment has been minimized.

@amueller

amueller Oct 24, 2016
Member

I would really like to be consistent. I don't think there's a good argument to have one but not the other. Not sure if the example is a strong enough point to make them both public.

for i, (clf_name, clf) in enumerate(classifiers.items()):
# fit the data and tag outliers
clf.fit(X)
scores_pred = clf.decision_function(X)
if clf_name == "Local Outlier Factor":

This comment has been minimized.

@amueller

amueller Oct 24, 2016
Member

Wait, I don't understand this. Please elaborate.

Attributes
----------
outlier_factor_ : numpy array, shape (n_samples,)
The LOF of X. The lower, the more normal.

This comment has been minimized.

@amueller

amueller Oct 24, 2016
Member

I don't know which comment of yours refers to which comment of mine.

For the first comment: Yes, I'd either do negative_outlier_factor or inlier_score or something generic?

For the second comment: The explanation of outlier_factor_ as an attribute says "The LOF of X" what is X? It's the training set this LocalOutlierFactor estimator was trained on, right?

@amueller amueller merged commit 788a458 into scikit-learn:master Oct 25, 2016
2 of 3 checks passed
2 of 3 checks passed
continuous-integration/appveyor/pr Waiting for AppVeyor build to complete
Details
ci/circleci Your tests passed on CircleCI!
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@amueller
Copy link
Member

@amueller amueller commented Oct 25, 2016

thanks :)

@raghavrv
Copy link
Member

@raghavrv raghavrv commented Oct 25, 2016

Hurray 🍻 Thanks @ngoix !!

@tguillemot
Copy link
Contributor

@tguillemot tguillemot commented Oct 25, 2016

Youpi 🍻 !!

@albertcthomas
Copy link
Contributor

@albertcthomas albertcthomas commented Oct 25, 2016

Thanks @ngoix !!

@GaelVaroquaux
Copy link
Member

@GaelVaroquaux GaelVaroquaux commented Oct 25, 2016

@agramfort
Copy link
Member

@agramfort agramfort commented Oct 25, 2016

Congrats !

sergeyf added a commit to sergeyf/scikit-learn that referenced this pull request Feb 28, 2017
* LOF algorithm

add tests and example

fix DepreciationWarning by reshape(1,-1) one-sample data

LOF with inheritance

lof and lof2 return same score

fix bugs

fix bugs

optimized and cosmit

rm lof2

cosmit

rm MixinLOF + fit_predict

fix travis - optimize pairwise_distance like in KNeighborsMixin.kneighbors

add comparison example + doc

LOF -> LocalOutlierFactor
cosmit

change LOF API:
-fit(X).predict() and fit(X).decision_function() do prediction on X without
 considering samples as their own neighbors (ie without considering X as a
 new dataset as does fit(X).predict(X))
-rm fit_predict() method
-add a contamination parameter st predict returns a binary value like other
 anomaly detection algos

cosmit

doc + debug example

correction doc

pass on doc + examples

pep8 + fix warnings

first attempt at fixing API issues

minor changes

takes into account tguillemot advice

-remove pairwise_distance calculation as to heavy in memory
-add benchmarks

cosmit

minor changes + deals with duplicates

fix depreciation warnings

* factorize the two for loops

* take into account @albertthomas88 review and cosmit

* fix doc

* alex review + rebase

* make predict private add outlier_factor_ attribute and update tests

* make fit_predict take y argument

* fix benchmarks file

* update examples

* make decision_function public (rm X=None default)

* fix travis

* take into account tguillemot review + remove useless k_distance function

* fix broken links :meth:`kneighbors`

* cosmit

* whatsnew

* amueller review + remove _local_outlier_factor method

* add n_neighbors_ parameter the effective nb neighbors we use

* make decision_function private and negative_outlier_factor attribute
afiodorov added a commit to unravelin/scikit-learn that referenced this pull request Apr 25, 2017
* LOF algorithm

add tests and example

fix DepreciationWarning by reshape(1,-1) one-sample data

LOF with inheritance

lof and lof2 return same score

fix bugs

fix bugs

optimized and cosmit

rm lof2

cosmit

rm MixinLOF + fit_predict

fix travis - optimize pairwise_distance like in KNeighborsMixin.kneighbors

add comparison example + doc

LOF -> LocalOutlierFactor
cosmit

change LOF API:
-fit(X).predict() and fit(X).decision_function() do prediction on X without
 considering samples as their own neighbors (ie without considering X as a
 new dataset as does fit(X).predict(X))
-rm fit_predict() method
-add a contamination parameter st predict returns a binary value like other
 anomaly detection algos

cosmit

doc + debug example

correction doc

pass on doc + examples

pep8 + fix warnings

first attempt at fixing API issues

minor changes

takes into account tguillemot advice

-remove pairwise_distance calculation as to heavy in memory
-add benchmarks

cosmit

minor changes + deals with duplicates

fix depreciation warnings

* factorize the two for loops

* take into account @albertthomas88 review and cosmit

* fix doc

* alex review + rebase

* make predict private add outlier_factor_ attribute and update tests

* make fit_predict take y argument

* fix benchmarks file

* update examples

* make decision_function public (rm X=None default)

* fix travis

* take into account tguillemot review + remove useless k_distance function

* fix broken links :meth:`kneighbors`

* cosmit

* whatsnew

* amueller review + remove _local_outlier_factor method

* add n_neighbors_ parameter the effective nb neighbors we use

* make decision_function private and negative_outlier_factor attribute
Sundrique added a commit to Sundrique/scikit-learn that referenced this pull request Jun 14, 2017
* LOF algorithm

add tests and example

fix DepreciationWarning by reshape(1,-1) one-sample data

LOF with inheritance

lof and lof2 return same score

fix bugs

fix bugs

optimized and cosmit

rm lof2

cosmit

rm MixinLOF + fit_predict

fix travis - optimize pairwise_distance like in KNeighborsMixin.kneighbors

add comparison example + doc

LOF -> LocalOutlierFactor
cosmit

change LOF API:
-fit(X).predict() and fit(X).decision_function() do prediction on X without
 considering samples as their own neighbors (ie without considering X as a
 new dataset as does fit(X).predict(X))
-rm fit_predict() method
-add a contamination parameter st predict returns a binary value like other
 anomaly detection algos

cosmit

doc + debug example

correction doc

pass on doc + examples

pep8 + fix warnings

first attempt at fixing API issues

minor changes

takes into account tguillemot advice

-remove pairwise_distance calculation as to heavy in memory
-add benchmarks

cosmit

minor changes + deals with duplicates

fix depreciation warnings

* factorize the two for loops

* take into account @albertthomas88 review and cosmit

* fix doc

* alex review + rebase

* make predict private add outlier_factor_ attribute and update tests

* make fit_predict take y argument

* fix benchmarks file

* update examples

* make decision_function public (rm X=None default)

* fix travis

* take into account tguillemot review + remove useless k_distance function

* fix broken links :meth:`kneighbors`

* cosmit

* whatsnew

* amueller review + remove _local_outlier_factor method

* add n_neighbors_ parameter the effective nb neighbors we use

* make decision_function private and negative_outlier_factor attribute
paulha added a commit to paulha/scikit-learn that referenced this pull request Aug 19, 2017
* LOF algorithm

add tests and example

fix DepreciationWarning by reshape(1,-1) one-sample data

LOF with inheritance

lof and lof2 return same score

fix bugs

fix bugs

optimized and cosmit

rm lof2

cosmit

rm MixinLOF + fit_predict

fix travis - optimize pairwise_distance like in KNeighborsMixin.kneighbors

add comparison example + doc

LOF -> LocalOutlierFactor
cosmit

change LOF API:
-fit(X).predict() and fit(X).decision_function() do prediction on X without
 considering samples as their own neighbors (ie without considering X as a
 new dataset as does fit(X).predict(X))
-rm fit_predict() method
-add a contamination parameter st predict returns a binary value like other
 anomaly detection algos

cosmit

doc + debug example

correction doc

pass on doc + examples

pep8 + fix warnings

first attempt at fixing API issues

minor changes

takes into account tguillemot advice

-remove pairwise_distance calculation as to heavy in memory
-add benchmarks

cosmit

minor changes + deals with duplicates

fix depreciation warnings

* factorize the two for loops

* take into account @albertthomas88 review and cosmit

* fix doc

* alex review + rebase

* make predict private add outlier_factor_ attribute and update tests

* make fit_predict take y argument

* fix benchmarks file

* update examples

* make decision_function public (rm X=None default)

* fix travis

* take into account tguillemot review + remove useless k_distance function

* fix broken links :meth:`kneighbors`

* cosmit

* whatsnew

* amueller review + remove _local_outlier_factor method

* add n_neighbors_ parameter the effective nb neighbors we use

* make decision_function private and negative_outlier_factor attribute
maskani-moh added a commit to maskani-moh/scikit-learn that referenced this pull request Nov 15, 2017
* LOF algorithm

add tests and example

fix DepreciationWarning by reshape(1,-1) one-sample data

LOF with inheritance

lof and lof2 return same score

fix bugs

fix bugs

optimized and cosmit

rm lof2

cosmit

rm MixinLOF + fit_predict

fix travis - optimize pairwise_distance like in KNeighborsMixin.kneighbors

add comparison example + doc

LOF -> LocalOutlierFactor
cosmit

change LOF API:
-fit(X).predict() and fit(X).decision_function() do prediction on X without
 considering samples as their own neighbors (ie without considering X as a
 new dataset as does fit(X).predict(X))
-rm fit_predict() method
-add a contamination parameter st predict returns a binary value like other
 anomaly detection algos

cosmit

doc + debug example

correction doc

pass on doc + examples

pep8 + fix warnings

first attempt at fixing API issues

minor changes

takes into account tguillemot advice

-remove pairwise_distance calculation as to heavy in memory
-add benchmarks

cosmit

minor changes + deals with duplicates

fix depreciation warnings

* factorize the two for loops

* take into account @albertthomas88 review and cosmit

* fix doc

* alex review + rebase

* make predict private add outlier_factor_ attribute and update tests

* make fit_predict take y argument

* fix benchmarks file

* update examples

* make decision_function public (rm X=None default)

* fix travis

* take into account tguillemot review + remove useless k_distance function

* fix broken links :meth:`kneighbors`

* cosmit

* whatsnew

* amueller review + remove _local_outlier_factor method

* add n_neighbors_ parameter the effective nb neighbors we use

* make decision_function private and negative_outlier_factor attribute
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet