Как определить выбросы с плотностью - PullRequest
4 голосов
/ 18 апреля 2019

Я пытаюсь идентифицировать выбросы с помощью моего графика плотности.В настоящее время я использую библиотеку Seaborn для печати своих данных.Как бы я узнал о выбросах?Я смотрел на реализацию Z-показателя с помощью библиотеки статистики, это единственный способ, которым это может быть достигнуто, если бы это не было сделано в графике плотности?

1 Ответ

1 голос
/ 19 апреля 2019

Оценка плотности ядра - это оценка гипотетической вероятности функция плотности (pdf) по заданным данным. Теперь у нас есть вопрос: какие точки данных следует рассматривать как выбросы. Выбросы - это редкие точки данных, то есть те точки, где PDF очень низкий. Мы не знаем PDF, но знаем его оценку. Таким образом, мы можем использовать эту оценку для выявления выбросов.

Итак, основная идея состоит в том, чтобы: 1) вычислить оценку плотности ядра во всех точках данных; 2) найти те точки, где эта оценка ниже некоторого предопределенного порога. Последний будет выбросами.

Давайте напишем некоторый код, чтобы проиллюстрировать это.

import numpy as np
# import seaborn as sns # you probably can use seaborn to get pdf-estimation values, I would use scikit-learn package for this.
from matplotlib import pyplot as plt
from sklearn.neighbors import KernelDensity

# 100 normally distributed data points and approximately 10 outliers in the end of the array.
data = np.r_[np.random.randn(100), np.random.rand(10)*100][:, np.newaxis]

# you an use kernel='gaussian' instead
kde = KernelDensity(kernel='tophat', bandwidth=0.75).fit(data)

yvals = kde.score_samples(data)  # yvals are logs of pdf-values
yvals[np.isinf(yvals)] = np.nan # some values are -inf, set them to nan

# approx. 10 percent of smallest pdf-values: lets treat them as outliers 
outlier_inds = np.where(yvals < np.percentile(yvals, 10))[0]
print(outlier_inds)
non_outlier_inds = np.where(yvals >= np.percentile(yvals, 10))[0]
print(non_outlier_inds)

[ 33  49 100 101 102 103 105 106 107 108 109]
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  34  35  36
  37  38  39  40  41  42  43  44  45  46  47  48  50  51  52  53  54  55
  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73
  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91
  92  93  94  95  96  97  98  99 104]

# I applied log to data points because we need to visualize small (0,1) and large (up to 100) values on the same plot.
plt.plot(non_outlier_inds, np.log(data[non_outlier_inds]), 'ro',
         outlier_inds, np.log(data[outlier_inds]), 'bo')
plt.gca().set_xlabel('Index')
plt.gca().set_ylabel('log(data)')
plt.show()

enter image description here

...