machinelearningmastery.ru

Машинное обучение, нейронные сети, искусственный интеллект
Header decor

Home

Обнаружение аномалий: изоляционный лес со статистическими правилами

Дата публикации Aug 24, 2019

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

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

Теперь давайте начнем с непосредственной реализации изолированного леса в наборе данных, который имеет метку времени и cpu_utilization в качестве значения:

Ссылка на набор данных (https://github.com/numenta/NAB/tree/master/data/realAWSCloudwatch)

import pandas as pd
import numpy as np
full_df=pd.read_csv('ec2_cpu_utilization_5f5533.csv')
full_df.head()

У нас есть около 4000 точек данных на 5-минутном уровне от 14 до 28 февраля.

print(full_df['timestamp'].min())print(full_df['timestamp'].max())
print(len(full_df['timestamp']))
Минимальная и максимальная отметки времени с количеством точек данных

Визуализируйте точки, чтобы получить обзор данных временных рядов:

# Using graph_objects
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.plotly as py
import matplotlib.pyplot as plt
from matplotlib import pyplot
import plotly.graph_objs as go
init_notebook_mode(connected=True)
import plotly.graph_objs as go
fig = go.Figure(data=[go.Scatter(x=full_df['timestamp'], y=full_df['value'])])
iplot(fig)

Я фильтрую данные за определенный день, чтобы иметь простую визуализацию. 24 февраля, кажется, хороший вариант, поскольку в данных наблюдается резкий спад.

df=full_df.loc[(full_df[‘timestamp’]>’2014–02–24 00:00:00')&(full_df[‘timestamp’]<’2014–02–24 23:59:59')]
df.head()
plot_data=go.Scatter(x=df['timestamp'], y=df['value'])
fig=go.Figure(data=[plot_data])
iplot(fig)

Теперь давайте начнем приспосабливать это к модели изолированного леса спараметр загрязненияустановить как 4% на основе моей интуиции от визуализации.

from sklearn.ensemble import IsolationForest
#to_model_column='value'
clf=IsolationForest(n_estimators=10, max_samples='auto', contamination=float(.04), \
max_features=1.0, bootstrap=False, n_jobs=-1, random_state=42, verbose=0,behaviour='new')
clf.fit(df[['value']])
df['scores']=clf.decision_function(df[['value']])
df['anomaly']=clf.predict(df[['value']])
df.head()df.loc[df['anomaly'] == 1,'anomaly'] = 0
df.loc[df['anomaly'] == -1,'anomaly'] = 1
df.value_counts()
def plot_anomaly(df,metric_name):
df.timestamp = pd.to_datetime(df['timestamp'].astype(str), format="%Y-%m-%d %H:%M:%S")
dates = df.timestamp
#identify the anomaly points and create a array of its values for plot
bool_array = (abs(df['anomaly']) > 0)
actuals = df["value"][-len(bool_array):]
anomaly_points = bool_array * actuals
anomaly_points[anomaly_points == 0] = np.nan
#A dictionary for conditional format table based on anomaly
color_map = {0: "'rgba(228, 222, 249, 0.65)'", 1: "red"}#Table which includes Date,Actuals,Change occured from previous point
table = go.Table(
domain=dict(x=[0, 1],
y=[0, 0.3]),
columnwidth=[1, 2],
# columnorder=[0, 1, 2,],
header=dict(height=20,
values=[['<b>Date</b>'], ['<b>Actual Values </b>'],
],
font=dict(color=['rgb(45, 45, 45)'] * 5, size=14),
fill=dict(color='#d562be')),
cells=dict(values=[df.round(3)[k].tolist() for k in ['timestamp', 'value']],
line=dict(color='#506784'),
align=['center'] * 5,
font=dict(color=['rgb(40, 40, 40)'] * 5, size=12),
# format = [None] + [",.4f"] + [',.4f'],
# suffix=[None] * 4,
suffix=[None] + [''] + [''] + ['%'] + [''],
height=27,
fill=dict(color=[df['anomaly'].map(color_map)],#map based on anomaly level from dictionary
)
))
#Plot the actuals points
Actuals = go.Scatter(name='Actuals',
x=dates,
y=df['value'],
xaxis='x1', yaxis='y1',
mode='line',
marker=dict(size=12,
line=dict(width=1),
color="blue"))
#Highlight the anomaly points
anomalies_map = go.Scatter(name="Anomaly",
showlegend=True,
x=dates,
y=anomaly_points,
mode='markers',
xaxis='x1',
yaxis='y1',
marker=dict(color="red",
size=11,
line=dict(
color="red",
width=2)))
axis = dict(
showline=True,
zeroline=False,
showgrid=True,
mirror=True,
ticklen=4,
gridcolor='#ffffff',
tickfont=dict(size=10))
layout = dict(
width=1000,
height=865,
autosize=False,
title=metric_name,
margin=dict(t=75),
showlegend=True,
xaxis1=dict(axis, **dict(domain=[0, 1], anchor='y1', showticklabels=True)),
yaxis1=dict(axis, **dict(domain=[2 * 0.21 + 0.20, 1], anchor='x1', hoverformat='.2f')))
fig = go.Figure(data=[table, anomalies_map, Actuals], layout=layout)
iplot(fig)
pyplot.show()plot_anomaly(df,'anomalies')
print("Percentage of anomalies in data: {:.2f}".format((len(df.loc[df['anomaly']==1])/len(df))*100))

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

Обломки встречаются вместе, для разделения x (i) требуется около 2 разбиений, тогда как выброс x (0) разделяется на 4 разбиения

Изоляция леса отделяет каждую точкуслучайным образом выделяется из других точек и строит дерево на основе количества разбиений, причем каждая точка представляет узел в дереве.Выбросы появляются ближе к корнюв дереве и вкладыши появляются в большей глубине. В случае изолированного леса, лес деревьев создается на основеn_estimators и max_sampleпараметры и оценка выводится из него.

Можно использоватьscore_samples / decision_fuctionчтобы получить нормализованный anomaly_score каждой точки здесь более отрицательно, это аномально на основе вычисления sklearn.

До этого шагаФактор загрязнения не влияет на баллы, Отсюда, когда мы применяем прогнозирование для того, чтобы вернуть аномалию, загрязнение 1/0 действует как порог / процентиль на баллах и возвращает отрицательные баллы по верхнему х процентилю как аномалии. (Например: если загрязнение установлено как 0,05 / 5%, то баллы с 5% лучших отрицательных баллов помечаются как аномалии)

df['scores'].hist()

Инлеры с положительными баллами забиты справа с положительными баллами, Очки с отрицательными оценками являются аномалиями. Это распределение баллов по этим конкретным входным баллам. После того, как мы доработаем нашу модель на основе этого и предскажем будущие баллы, тогда наше предельное количество баллов за загрязнение может измениться, чтобы получить 4% баллов как аномальные, но распределение баллов может измениться. Чтобы преодолеть вместо жестко закодированного процента точек, всегда помеченных как аномалии, независимо от изменения в баллах, мы можем использовать некоторый статистический алгоритм, такой какZ-Score или IQR на счетахвыявить эти изменения в баллах и лучше классифицировать аномалии.

def iqr_bounds(scores,k=1.5):
q1 = scores.quantile(0.25)
q3 = scores.quantile(0.75)
iqr = q3 - q1
lower_bound=(q1 - k * iqr)
upper_bound=(q3 + k * iqr)
print("Lower bound:{} \nUpper bound:{}".format(lower_bound,upper_bound))
return lower_bound,upper_bound
lower_bound,upper_bound=iqr_bounds(df['scores'],k=2)
df['anomaly']=0
df['anomaly']=(df['scores'] < lower_bound) |(df['scores'] > upper_bound)
df['anomaly']=df['anomaly'].astype(int)
plot_anomaly(df,'iqr based')

Процент точек, помеченных как аномалии, составляет около 2%, при этом в IQR значение k равно 2.

print("Percentage of anomalies in data: {:.2f}".format((len(df.loc[df['anomaly']==1])/len(df))*100))

Теперь давайте проверим это с помощью других данных с учетом того же загрязнения, а также с тем же k в IQR по баллам:

df=full_df.loc[(full_df['timestamp']>'2014-02-17 00:00:00')&(full_df['timestamp']<'2014-02-17 23:59:59')]
# Using graph_objects
plot_data=go.Scatter(x=df['timestamp'], y=df['value'])
fig=go.Figure(data=[plot_data])
iplot(fig)

Если посмотреть на график в этот день, то данные выглядят иначе с меньшим количеством аномалий.

from sklearn.ensemble import IsolationForest
#to_model_column='value'
clf=IsolationForest(n_estimators=10, max_samples='auto', contamination=float(.04), \
max_features=1.0, bootstrap=False, n_jobs=-1, random_state=42, verbose=0,behaviour='new')
clf.fit(df[['value']])
df['scores']=clf.decision_function(df[['value']])
df['anomaly']=clf.predict(df[['value']])
df.loc[df['anomaly'] == 1,'anomaly'] = 0
df.loc[df['anomaly'] == -1,'anomaly'] = 1
plot_anomaly(df,'anomalies')
print("Percentage of anomalies in data: {:.2f}".format((len(df.loc[df['anomaly']==1])/len(df))*100))

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

df['scores'].hist()
lower_bound,upper_bound=iqr_bounds(df['scores'],k=2)
df['anomaly']=0
df['anomaly']=(df['scores'] < lower_bound) |(df['scores'] > upper_bound)
df['anomaly']=df['anomaly'].astype(int)
plot_anomaly(df,'iqr second case')
print("Percentage of anomalies in data: {:.2f}".format((len(df.loc[df['anomaly']==1])/len(df))*100))

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

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

Также этоПараметр k в IQR можно настроить на основе обратной связи по обнаруженным аномалиям. Если есть ложные срабатывания, то следует уменьшить k, а если есть ложные отрицания, то k следует уменьшить, чтобы найти больше аномалий.

Далее мы рассмотрим некоторые детали алгоритма изолированного леса, добавим теплое начало и интерпретируем результаты из изолированного леса.

добавить: Ниже многомерныйаномалия 3d визуализацияс помощьюсюжетно выражатькоторый я нашел, чтобы быть крутым. Поиграйте с ним во всех трех измерениях, чтобы взглянуть на аномалии.

Оригинальная статья

Footer decor

© machinelearningmastery.ru | Ссылки на оригиналы и авторов сохранены. | map