Рубрики
Без рубрики

Обнаружение выбросов с нуля (своего рода) в Python

Примечание: это перекрестная пост, изначально написанная в моем блоге вытягивании вытяжений, обнаружение … Tagged с Python, Machineleasning.

ПРИМЕЧАНИЕ: это перекрестная пост, изначально написанная на мой блог

Обнаружение выбросов может быть достигнуто с помощью некоторых очень простых, но мощных алгоритмов. Все примеры здесь либо плотность или расстояние измерения. Код здесь не оптимизирован как чаще, чем нет, оптимизированный код трудно читать код. Кроме того, эти измерения широко используют k-nearest-neighbors. Следовательно, они не столь полезны в более высоких измерениях.

Во -первых, давайте генерируем некоторые данные с некоторыми случайными выбросами.

%matplotlib inline
# Generate some fake data clusters
from sklearn.datasets import make_blobs
from matplotlib import pyplot
from pandas import DataFrame
import random
import numpy as np

r_seed = 42

# Generate three 2D clusters totalling 1000 points 
X, y = make_blobs(n_samples=1000, centers=3, n_features=2, random_state=r_seed)
random.seed(r_seed)
random_pts = []

# Generate random noise points that could be or could not be close to the clustered neighborhoods
for i in range(50):
    random_pts.append([random.randint(-10, 10), random.randint(-10, 10)])

X = np.append(X, random_pts, axis=0)

df = DataFrame(dict(x=X[:,0], y=X[:,1]))
df.plot(kind='scatter', x='x', y='y')
pyplot.show()

Алгоритмы

Четыре отдельных алгоритма показаны ниже:

  • Локальный фактор выброса (LOF): Это метрика плотности, которая определяет, насколько плотный находится точки местного района. Соседство определяется через ближайшие соседи K
  • Локальный дистанционный фактор выброса (LDOF): это алгоритм расстояния плотности +, который похож на LOF, но вместо того, чтобы беспокоиться о плотности соседства, он смотрит на то, как далеко находится точка от воспринимаемого центра района.
  • K th Ближайшие соседские расстояния (K th NN): метрика расстояния, которая смотрит на то, как далеко находится точка от ближайшего соседа KTH
  • K Ближайшие соседи Общее расстояние (TNN): метрика расстояния, которая является усредненным расстоянием до ближайших соседей.

Это очень интуитивно понятная мера. Как далеко вы от своего K th сосед? Чем дальше, тем больше вероятность того, что вы будете выбросом из набора.

from sklearn.neighbors import NearestNeighbors

k = 10

knn = NearestNeighbors(n_neighbors=k)

knn.fit(X)
# Gather the kth nearest neighbor distance
neighbors_and_distances = knn.kneighbors(X)
knn_distances = neighbors_and_distances[0]
neighbors = neighbors_and_distances[1]
kth_distance = [x[-1] for x in sk_knn_distances]

Очень похож на K th NN, но мы в среднем составляем все расстояния до ближайших соседей. С тех пор k th NN учитывает только одного соседа, он может пропустить определенные выбросы, которые находит TNN.

# Gather the average distance to each points nearest neighbor 
tnn_distance = np.mean(knn_distances, axis=1)

Обратите внимание на точку в правом верхнем углу, TNN определяет, что это, скорее всего, выброс из-за того, насколько это далеко от всех его соседей.

Этот алгоритм немного сложнее, хотя и не много.

Бумага, объясняющая это глубиной, является Здесь Анкет

Вот упрощенная версия.

Мы уже рассчитали одну часть этого алгоритма через TNN. Давайте вызовут это значение как TNN (x) , для какой -то точки x.

Другая часть – это то, что бумага называет «внутренним расстоянием KNN». Это среднее из всех расстояний между всеми точками в наборе k ближайших соседей, называемых здесь как Knn (x) Анкет

Итак, Ldof (x) (x)/knn_inner_distance (knn (x))

Эта комбинация делает этот метод плотностью и измерением расстояния. Идея в том, что точка с оценкой LDOF >> 1.0 находится далеко за пределами облака k ближайших соседей. Любая точка с оценкой LDOF меньше или «около» 1,0, можно считать «окруженной» через облако соседей.

# Gather the inner distance for pts
def knn_inner_distance(pts):
    summation = 0
    for i in range(len(pts)):
        pt = pts[i]
        for other_pt in pts[i:]:
            summation = summation + np.linalg.norm(pt - other_pt)
    return summation / (k * (k - 1))

inner_distances = [knn_inner_distance(X[ns]) for ns in neighbors]

ldofs = [x/y for x,y in zip(tnn_distance, inner_distances)]

Вы можете заметить влияние идеи «облака». Все точки между кластерами отмечены гораздо более низкой вероятностью быть выбросом, в то время как те, кто за пределами облака, имеют гораздо более высокую вероятность.

LOF – это измерение, ориентированное на плотность. Основная концепция этого алгоритма – Достигаемость_дистанция . Это определяется как Достижимость Другими словами, это истинное расстояние между A и B, но оно должно быть Хотя бы Расстояние между B и это k th ближайший сосед.

Это делает Достижимость_дистансия асимметричный. Поскольку у A и B есть другой набор k ближайших соседей, их собственные расстояния до их K th Сосед будет отличаться.

Используя Достижимость_дистансия Мы можем рассчитать local_reach_density к плотности соседства Пойнт.

Для какой -то точки x это local_reach_density 1 разделен на среднее значение всех Достижимость для всех y в Knn (x) , то есть набор ближайших соседей X.

Вооружены этим, мы можем затем сравнить точку x local_reach_density к такому соседям, чтобы получить LOF (x) Анкет

Статья Википедии о LOF дает превосходное, краткое математическое и визуальное объяснение.

local_reach_density = []
for i in range(X.shape[0]):
    pt = X[i]
    sum_reachability = 0
    neighbor_distances = knn_distances[i]
    pt_neighbors = neighbors[i]
    for neighbor_distance, neighbor_index in zip(neighbor_distances, pt_neighbors):
        neighbors_kth_distance = kth_distance[neighbor_index]
        sum_reachability = sum_reachability + max([neighbor_distance, neighbors_kth_distance])

    avg_reachability = sum_reachability / k
    local_reach_density.append(1/avg_reachability)

local_reach_density = np.array(local_reach_density)
lofs = []
for i in range(X.shape[0]):
    pt = X[i]
    avg_lrd = np.mean(local_reach_density[neighbors[i]])
    lofs.append(avg_lrd/local_reach_density[i])

# Or just use
# from sklearn.neighbors import LocalOutlierFactor

Оригинал: “https://dev.to/benwtrent/outlier-detection-from-scratch-sort-of-in-python-30p8”