# LocalOutlierFactor

Local outlier factor model for anomaly detection

## Description

Use a local outlier factor model object
`LocalOutlierFactor`

for anomaly detection.

Outlier detection (detecting anomalies in training data) — Detect anomalies in training data by using the

`lof`

function. The`lof`

function creates a`LocalOutlierFactor`

object and returns anomaly indicators and scores (local outlier factor values) for the training data.Novelty detection (detecting anomalies in new data with uncontaminated training data) — Create a

`LocalOutlierFactor`

object by passing uncontaminated training data (data with no outliers) to`lof`

, and detect anomalies in new data by passing the object and the new data to the object function`isanomaly`

. The`isanomaly`

function returns anomaly indicators and scores for the new data.

## Creation

Create a `LocalOutlierFactor`

object by using the `lof`

function.

## Properties

`X`

— Predictors

numeric matrix | table

This property is read-only.

Predictors used to train the local outlier factor model, specified as a numeric
matrix or a table. Each row of `X`

corresponds to one observation,
and each column corresponds to one variable.

`BucketSize`

— Maximum number of data points in each leaf node

positive integer | `[]`

This property is read-only.

Maximum number of data points in each leaf node of the *K*d-tree,
specified as a positive integer.

This property is valid when `SearchMethod`

is `'kdtree'`

. If `SearchMethod`

is
`'exhaustive'`

, the `BucketSize`

value is empty
(`[]`

).

`CategoricalPredictors`

— Categorical predictor indices

vector of positive integers | `[]`

This property is read-only.

Categorical predictor
indices, specified as a vector of positive integers. `CategoricalPredictors`

contains index values indicating that the corresponding predictors are categorical. The index
values are between 1 and `p`

, where `p`

is the number of
predictors used to train the model. If none of the predictors are categorical, then this
property is empty (`[]`

).

`ContaminationFraction`

— Fraction of anomalies in training data

numeric scalar in the range `[0,1]`

This property is read-only.

Fraction of anomalies in the training data, specified as a numeric scalar in the
range `[0,1]`

.

If the

`ContaminationFraction`

value is 0, then`lof`

treats all training observations as normal observations, and sets the score threshold (`ScoreThreshold`

property value) to the maximum anomaly score value of the training data.If the

`ContaminationFraction`

value is in the range (`0`

,`1`

], then`lof`

determines the threshold value (`ScoreThreshold`

property value) so that the function detects the specified fraction of training observations as anomalies.

`Distance`

— Distance metric

character vector

This property is read-only.

Distance metric, specified as a character vector.

If all the predictor variables are continuous (numeric) variables, then the

`Distance`

value can be one of these distance metrics.Value Description `'euclidean'`

Euclidean distance

`'mahalanobis'`

Mahalanobis distance — The distance uses the covariance matrix stored in the

`DistParameter`

property.`'minkowski'`

Minkowski distance — The distance uses the exponent value stored in the

`DistParameter`

property.`'chebychev'`

Chebychev distance (maximum coordinate difference)

`'cityblock'`

City block distance

`'correlation'`

One minus the sample correlation between observations (treated as sequences of values)

`'cosine'`

One minus the cosine of the included angle between observations (treated as vectors)

`'spearman'`

One minus the sample Spearman's rank correlation between observations (treated as sequences of values)

If all the predictor variables are categorical variables, then the

`Distance`

value can be one of these distance metrics.Value Description `'hamming'`

Hamming distance, which is the percentage of coordinates that differ

`'jaccard'`

One minus the Jaccard coefficient, which is the percentage of nonzero coordinates that differ

For more information on the various distance metrics, see Distance Metrics.

`DistParameter`

— Distance metric parameter value

positive scalar | `[]`

This property is read-only.

Distance metric parameter value for the Mahalanobis or Minkowski distance, specified
as a positive scalar. The `DistParameter`

value is empty
(`[]`

) for the other distances, indicating that the specified
distance metric formula has no parameters.

If

`Distance`

is`'mahalanobis'`

, then`DistParameter`

is the covariance matrix in the Mahalanobis distance formula. The`Cov`

name-value argument of`lof`

sets this property.If

`Distance`

is`'minkowski'`

, then`DistParameter`

is the exponent in the Minkowski distance formula. The`Exponent`

name-value argument of`lof`

sets this property.

`IncludeTies`

— Tie inclusion flag

`false`

or `0`

| `true`

or `1`

This property is read-only.

Tie inclusion flag indicating whether `LocalOutlierFactor`

includes
all the neighbors whose distance values are equal to the *k*th smallest
distance, specified as logical `0`

(`false`

) or
`1`

(`true`

). If `IncludeTies`

is
`true`

, `LocalOutlierFactor`

includes all of these
neighbors. Otherwise, `LocalOutlierFactor`

includes exactly
*k* neighbors.

`NumNeighbors`

— Number of nearest neighbors

positive integer value

This property is read-only.

Number of nearest neighbors in `X`

used to compute local outlier
factor values, specified as a positive integer value.

`PredictorNames`

— Predictor variable names

cell array of character vectors

This property is read-only.

Predictor variable names, specified as a cell array of character vectors. The order of the elements of `PredictorNames`

corresponds to the order in which the predictor names appear in the training data.

`ScoreThreshold`

— Threshold for anomaly score

nonnegative scalar

This property is read-only.

Threshold for the anomaly score used to identify anomalies in the training data, specified as a nonnegative scalar.

The software identifies observations with anomaly scores above the threshold as anomalies.

The

`lof`

function determines the threshold value to detect the specified fraction (`ContaminationFraction`

property) of training observations as anomalies.

The

`isanomaly`

object function uses the`ScoreThreshold`

property value as the default value of the`ScoreThreshold`

name-value argument.

`SearchMethod`

— Nearest neighbor search method

`'kdtree'`

| `'exhaustive'`

This property is read-only.

Nearest neighbor search method, specified as `'kdtree'`

or
`'exhaustive'`

.

`'kdtree'`

— This method uses a*K*d-tree algorithm to find nearest neighbors. This option is valid when the distance metric (`Distance`

) is one of the following:`'euclidean'`

— Euclidean distance`'cityblock'`

— City block distance`'minkowski'`

— Minkowski distance`'chebychev'`

— Chebychev distance

`'exhaustive'`

— This method uses the exhaustive search algorithm to find nearest neighbors.When you compute local outlier factor values for

`X`

using the`lof`

function, the function finds nearest neighbors by computing the distance values from all points in`X`

to each point in`X`

.When you compute local outlier factor values for new data

`Xnew`

using the`isanomaly`

function, the function finds nearest neighbors by computing the distance values from all points in`X`

to each point in`Xnew`

.

## Object Functions

`isanomaly` | Find anomalies in data using local outlier factor |

## Examples

### Detect Outliers

Detect outliers (anomalies in training data) by using the `lof`

function.

Load the sample data set `NYCHousing2015`

.

`load NYCHousing2015`

The data set includes 10 variables with information on the sales of properties in New York City in 2015. Display a summary of the data set.

summary(NYCHousing2015)

Variables: BOROUGH: 91446x1 double Values: Min 1 Median 3 Max 5 NEIGHBORHOOD: 91446x1 cell array of character vectors BUILDINGCLASSCATEGORY: 91446x1 cell array of character vectors RESIDENTIALUNITS: 91446x1 double Values: Min 0 Median 1 Max 8759 COMMERCIALUNITS: 91446x1 double Values: Min 0 Median 0 Max 612 LANDSQUAREFEET: 91446x1 double Values: Min 0 Median 1700 Max 2.9306e+07 GROSSSQUAREFEET: 91446x1 double Values: Min 0 Median 1056 Max 8.9422e+06 YEARBUILT: 91446x1 double Values: Min 0 Median 1939 Max 2016 SALEPRICE: 91446x1 double Values: Min 0 Median 3.3333e+05 Max 4.1111e+09 SALEDATE: 91446x1 datetime Values: Min 01-Jan-2015 Median 09-Jul-2015 Max 31-Dec-2015

Remove nonnumeric variables from `NYCHousing2015`

. The data type of the `BOROUGH`

variable is double, but it is a categorical variable indicating the borough in which the property is located. Remove the `BOROUGH`

variable as well.

```
NYCHousing2015 = NYCHousing2015(:,vartype("numeric"));
NYCHousing2015.BOROUGH = [];
```

Train a local outlier factor model for `NYCHousing2015`

. Specify the fraction of anomalies in the training observations as 0.01.

[Mdl,tf,scores] = lof(NYCHousing2015,ContaminationFraction=0.01);

`Mdl`

is a `LocalOutlierFactor`

object. `lof`

also returns the anomaly indicators (`tf`

) and anomaly scores (`scores`

) for the training data `NYCHousing2015`

.

Plot a histogram of the score values. Create a vertical line at the score threshold corresponding to the specified fraction.

h = histogram(scores,NumBins=50); h.Parent.YScale = 'log'; xline(Mdl.ScoreThreshold,"r-",["Threshold" Mdl.ScoreThreshold])

If you want to identify anomalies with a different contamination fraction (for example, 0.05), you can train a new local outlier factor model.

[newMdl,newtf,scores] = lof(NYCHousing2015,ContaminationFraction=0.05);

Note that changing the contamination fraction changes the anomaly indicators only, and does not affect the anomaly scores. Therefore, if you do not want to compute the anomaly scores again by using `lof`

, you can obtain a new anomaly indicator with the existing score values.

Change the fraction of anomalies in the training data to 0.05.

newContaminationFraction = 0.05;

Find a new score threshold by using the `quantile`

function.

newScoreThreshold = quantile(scores,1-newContaminationFraction)

newScoreThreshold = 6.7493

Obtain a new anomaly indicator.

newtf = scores > newScoreThreshold;

### Detect Novelties

Create a `LocalOutlierFactor`

object for uncontaminated training observations by using the `lof`

function. Then detect novelties (anomalies in new data) by passing the object and the new data to the object function `isanomaly`

.

Load the 1994 census data stored in `census1994.mat`

. The data set consists of demographic data from the US Census Bureau to predict whether an individual makes over $50,000 per year.

`load census1994`

`census1994`

contains the training data set `adultdata`

and the test data set `adulttest`

. The predictor data must be either all continuous or all categorical to train a `LocalOutlierFactor`

object. Remove nonnumeric variables from `adultdata`

and `adulttest`

.

adultdata = adultdata(:,vartype("numeric")); adulttest = adulttest(:,vartype("numeric"));

Train a local outlier factor model for `adultdata`

. Assume that `adultdata`

does not contain outliers.

[Mdl,tf,s] = lof(adultdata);

`Mdl`

is a `LocalOutlierFactor`

object. `lof`

also returns the anomaly indicators `tf`

and anomaly scores `s`

for the training data `adultdata`

. If you do not specify the `ContaminationFraction`

name-value argument as a value greater than 0, then `lof`

treats all training observations as normal observations, meaning all the values in `tf`

are logical 0 (`false`

). The function sets the score threshold to the maximum score value. Display the threshold value.

Mdl.ScoreThreshold

ans = 28.6719

Find anomalies in `adulttest`

by using the trained local outlier factor model.

[tf_test,s_test] = isanomaly(Mdl,adulttest);

The `isanomaly`

function returns the anomaly indicators `tf_test`

and scores `s_test`

for `adulttest`

. By default, `isanomaly`

identifies observations with scores above the threshold (`Mdl.ScoreThreshold`

) as anomalies.

Create histograms for the anomaly scores `s`

and `s_test`

. Create a vertical line at the threshold of the anomaly scores.

h1 = histogram(s,NumBins=50,Normalization="probability"); hold on h2 = histogram(s_test,h1.BinEdges,Normalization="probability"); xline(Mdl.ScoreThreshold,"r-",join(["Threshold" Mdl.ScoreThreshold])) h1.Parent.YScale = 'log'; h2.Parent.YScale = 'log'; legend("Training Data","Test Data",Location="north") hold off

Display the observation index of the anomalies in the test data.

find(tf_test)

ans = 0x1 empty double column vector

The anomaly score distribution of the test data is similar to that of the training data, so `isanomaly`

does not detect any anomalies in the test data with the default threshold value. You can specify a different threshold value by using the `ScoreThreshold`

name-value argument. For an example, see Specify Anomaly Score Threshold.

## More About

### Local Outlier Factor

The local outlier factor (LOF) algorithm detects anomalies based on the relative density of an observation with respect to the surrounding neighborhood.

The algorithm finds the *k*-nearest neighbors of an observation and computes the local reachability densities for the observation and its neighbors. The local outlier factor is the average density ratio of the observation to its neighbor. That is, the local outlier factor of observation *p* is

$$LO{F}_{k}(p)=\frac{1}{\left|{N}_{k}(p)\right|}{\displaystyle \sum _{o\in {N}_{k}(p)}\frac{lr{d}_{k}(o)}{lr{d}_{k}(p)}},$$

where

*lrd*(·) is the local reachability density of an observation._{k}*N*(_{k}*p*) represents the*k*-nearest neighbors of observation*p*. You can specify the`IncludeTies`

name-value argument as`true`

to include all the neighbors whose distance values are equal to the*k*th smallest distance, or specify`false`

to include exactly*k*neighbors. The default`IncludeTies`

value of`lof`

is`false`

for more efficient performance. Note that the algorithm in [1] uses all the neighbors.|

*N*(_{k}*p*)| is the number of observations in*N*(_{k}*p*).

For normal observations, the local outlier factor values are less than or close to 1,
indicating that the local reachability density of an observation is higher than or similar
to its neighbors. A local outlier factor value greater than 1 can indicate an anomaly. The
`ContaminationFraction`

argument of `lof`

and the `ScoreThreshold`

argument of `isanomaly`

control the threshold for the local outlier
factor values.

The algorithm measures the density based on the reachability distance. The reachability distance of observation *p* with respect to observation *o* is defined as

$${\tilde{d}}_{k}(p,o)=\mathrm{max}({d}_{k}(o),d(p,o)),$$

where

*d*(_{k}*o*) is the*k*th smallest distance among the distances from observation*o*to its neighbors.*d*(*p*,*o*) is the distance between observation*p*and observation*o*.

The algorithm uses the reachability distance to reduce the statistical fluctuations of *d*(*p*,*o*) for the observations close to observation *o*.

The local reachability density of observation *p* is the reciprocal of the average reachability distance from observation *p* to its neighbors.

$$lr{d}_{k}(p)=1/\frac{{\displaystyle \sum _{o\in {N}_{k}(p)}{\tilde{d}}_{k}(p,o)}}{\left|{N}_{k}(p)\right|}.$$

The density value can be infinity if the number of duplicates is greater than the number of
neighbors (*k*). Therefore, if the training data contains duplicates, the
`lof`

and `isanomaly`

functions use the weighted
local outlier factor (WLOF) algorithm. This algorithm computes the weighted local outlier
factors using the weighted local reachability density (*wlrd*).

$$WLO{F}_{k}(p)=\frac{1}{{\displaystyle \sum _{o\in {N}_{k}(p)}w(o)}}{\displaystyle \sum _{o\in {N}_{k}(p)}\frac{wlr{d}_{k}(o)}{wlr{d}_{k}(p)}},$$

where

$$wlr{d}_{k}(p)=1/\frac{{\displaystyle \sum _{o\in {N}_{k}(p)}w(o){\tilde{d}}_{k}(p,o)}}{{\displaystyle \sum _{o\in {N}_{k}(p)}w(o)}},$$

and *w*(*o*) is the number of duplicates for observation *o* in the
training data. After computing the weight values, the algorithm treats each set of
duplicates as one observation.

### Distance Metrics

A distance metric is a function that defines a distance between two observations. `LocalOutlierFactor`

supports various distance metrics for continuous variables and categorical variables.

Given an *mx*-by-*n* data matrix *X*, which is treated as *mx* (1-by-*n*) row vectors *x _{1}*,

*x*, ...,

_{2}*x*, and an

_{mx}*my*-by-

*n*data matrix

*Y*, which is treated as

*my*(1-by-

*n*) row vectors

*y*,

_{1}*y*, ...,

_{2}*y*, the various distances between the vector

_{my}*x*and

_{s}*y*are defined as follows:

_{t}Distance metrics for continuous (numeric) variables

Euclidean distance

$${d}_{st}^{2}=({x}_{s}-{y}_{t})({x}_{s}-{y}_{t}{)}^{\prime}.$$

The Euclidean distance is a special case of the Minkowski distance, where

*p*= 2.Mahalanobis distance

$${d}_{st}^{2}=({x}_{s}-{y}_{t}){C}^{-1}({x}_{s}-{y}_{t}{)}^{\prime},$$

where

*C*is the covariance matrix.City block distance

$${d}_{st}={\displaystyle \sum _{j=1}^{n}\left|{x}_{sj}-{y}_{tj}\right|}.$$

The city block distance is a special case of the Minkowski distance, where

*p*= 1.Minkowski distance

$${d}_{st}=\sqrt[p]{{\displaystyle \sum _{j=1}^{n}{\left|{x}_{sj}-{y}_{tj}\right|}^{p}}}.$$

For the special case of

*p*= 1, the Minkowski distance gives the city block distance. For the special case of*p*= 2, the Minkowski distance gives the Euclidean distance. For the special case of*p*= ∞, the Minkowski distance gives the Chebychev distance.Chebychev distance

$${d}_{st}={\mathrm{max}}_{j}\left\{\left|{x}_{sj}-{y}_{tj}\right|\right\}.$$

The Chebychev distance is a special case of the Minkowski distance, where

*p*= ∞.Cosine distance

$${d}_{st}=\left(1-\frac{{x}_{s}{{y}^{\prime}}_{t}}{\sqrt{\left({x}_{s}{{x}^{\prime}}_{s}\right)\left({y}_{t}{{y}^{\prime}}_{t}\right)}}\right).$$

Correlation distance

$${d}_{st}=1-\frac{\left({x}_{s}-{\overline{x}}_{s}\right){\left({y}_{t}-{\overline{y}}_{t}\right)}^{\prime}}{\sqrt{\left({x}_{s}-{\overline{x}}_{s}\right){\left({x}_{s}-{\overline{x}}_{s}\right)}^{\prime}}\sqrt{\left({y}_{t}-{\overline{y}}_{t}\right){\left({y}_{t}-{\overline{y}}_{t}\right)}^{\prime}}},$$

where

$${\overline{x}}_{s}=\frac{1}{n}{\displaystyle \sum _{j}{x}_{sj}}$$

and

$${\overline{y}}_{t}=\frac{1}{n}{\displaystyle \sum _{j}{y}_{tj}}.$$

Spearman distance

$${d}_{st}=1-\frac{\left({r}_{s}-{\overline{r}}_{s}\right){\left({r}_{t}-{\overline{r}}_{t}\right)}^{\prime}}{\sqrt{\left({r}_{s}-{\overline{r}}_{s}\right){\left({r}_{s}-{\overline{r}}_{s}\right)}^{\prime}}\sqrt{\left({r}_{t}-{\overline{r}}_{t}\right){\left({r}_{t}-{\overline{r}}_{t}\right)}^{\prime}}},$$

where

*r*is the rank of_{sj}*x*taken over_{sj}*x*_{1j},*x*_{2j}, ...*x*, as computed by_{mx,j}`tiedrank`

.*r*is the rank of_{tj}*y*taken over_{tj}*y*_{1j},*y*_{2j}, ...*y*, as computed by_{my,j}`tiedrank`

.*r*and_{s}*r*are the coordinate-wise rank vectors of_{t}*x*and_{s}*y*, that is,_{t}*r*= (_{s}*r*_{s}_{1},*r*_{s}_{2}, ...*r*) and_{sn}*r*= (_{t}*r*_{t1},*r*_{t2}, ...*r*)._{tn}$${\overline{r}}_{s}=\frac{1}{n}{\displaystyle \sum _{j}{r}_{sj}}=\frac{\left(n+1\right)}{2}$$.

$${\overline{r}}_{t}=\frac{1}{n}{\displaystyle \sum _{j}{r}_{tj}}=\frac{\left(n+1\right)}{2}$$.

Distance metrics for categorical variables

Hamming distance

$${d}_{st}=(\#({x}_{sj}\ne {y}_{tj})/n).$$

Jaccard distance

$${d}_{st}=\frac{\#\left[\left({x}_{sj}\ne {y}_{tj}\right)\cap \left(\left({x}_{sj}\ne 0\right)\cup \left({y}_{tj}\ne 0\right)\right)\right]}{\#\left[\left({x}_{sj}\ne 0\right)\cup \left({y}_{tj}\ne 0\right)\right]}.$$

## Tips

You can use interpretability features, such as

`lime`

,`shapley`

,`partialDependence`

, and`plotPartialDependence`

, to interpret how predictors contribute to anomaly scores. Define a custom function that returns anomaly scores, and pass the custom function to the interpretability functions. For an example, see Specify Model Using Function Handle.

## References

[1] Breunig, Markus M., et al. “LOF: Identifying Density-Based Local Outliers.” *Proceedings of the 2000 ACM SIGMOD International Conference on Management of Data*, 2000, pp. 93–104.

## Version History

**Introduced in R2022b**

## Open Example

You have a modified version of this example. Do you want to open this example with your edits?

## MATLAB Command

You clicked a link that corresponds to this MATLAB command:

Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.

# Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list:

## How to Get Best Site Performance

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

### Americas

- América Latina (Español)
- Canada (English)
- United States (English)

### Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)