February 8, 2021

Диагностика ошибочных значений с Python

Как определять ошибочные значения? В этой статье я поделюсь готовыми функциями для диагностики и фильтрации выбросов.

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

Единственного  подхода к выявлению выбросов нет, однако распространены несколько  методов, каждый из которых может дать достаточно хороший результат.  Реализуем все варианты в виде функций Python, принимающих столбец  значений (объект Series библиотеки Pandas) и возвращающих наименьшую и  наибольшую величины, за пределами которых располагаются выбросы.

Для  демонстрационных целей будем использовать следующий искусственно  сгенерированный набор 100 оценок за некие упражнения (каждая должна быть  целым от 1 до 10). Как видим на рисунке ниже, у нас три выброса:

Код для генерации набора:

y = np.random.randint(1,11,100)
y[23] = 23
y[43] = 28
y[88] = -2
y = pd.Series(y)

Определение на основе стандартных отклонений

Его  суть заключается в пометке в качестве выбросов значений, отклоняющихся  более чем на два стандартных отклонения в меньшую или большую сторону от  медианы. Данная аналогия взята из нормального распределения, в  соответствующих пределах которого располагаются свыше 95% всех значений  случайной величины. Если сведений мало,  предпочтительнее задать три  стандартных отклонения (свыше 99% значений нормально распределенной  случайной величины):

def get_anom_bounds_std(col, num_stds=2):
   mean = col.mean()
   std = col.std()
   return mean - num_stds*std, mean + num_stds*std

Определение на основе вероятностного интервала

Зададим границы интервала, в котором находится определенная доля наблюдаемых значений величины (например, 0.95):

def get_anom_bounds_perc(col,p=0.95):
   out_p_h = (1-p)/2
   return col.quantile(out_p_h), col.quantile(1-out_p_h)

Определение на основе интер-квартильного размаха

Определяем  величину, покрывающую заданную долю распределения значений  (интер-квартильный размах) и на ее основе - искомые границы, как  значения, отклоняющиеся на этот размах от медианы:

def get_anom_bounds_ipr(col, p=0.5):
   mu = col.quantile(0.5)
   out_ipr_h = (1-p)/2
   ipr = col.quantile(1-out_ipr_h) - col.quantile(out_ipr_h)        
   return mu - ipr, mu + ipr

Определение на основе сигма-отсечения

Об  этом методе прочитал в книге "Python для сложных задач", Дж. Вандер  Плас (стр. 215). Реализация подхода похожа на предыдущие методы с  добавлением некоторых коэффициентов.

def get_anom_bounds_sigma_clip(col):
   mu = col.quantile(0.5)
   sig = 0.74* (col.quantile(0.75) - col.quantile(0.25))
   return mu - 5*sig, mu + 5*sig

Вот с такими способами борьбы с выбросами я сталкивался, а какие методы применяете вы, делитесь в комментариях.

Еще больше статей можете прочитать на моем канале в Яндекс Дзен.