Диагностика ошибочных значений с 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
Вот с такими способами борьбы с выбросами я сталкивался, а какие методы применяете вы, делитесь в комментариях.
Еще больше статей можете прочитать на моем канале в Яндекс Дзен.