несоответствие между настройкой загрязнения и прогнозом количества выбросов в изолированном лесу Sklearn
Меня вдохновил этот блокнот , и я экспериментирую
IsolationForest
алгоритм с использованием
scikit-learn==0.22.2.post1
для контекста обнаружения аномалий в SF- версии набора данных KDDCUP99 , включая 4 атрибута. Данные берутся напрямую из
sklearn
и после предварительной обработки (метка, кодирующая категориальный признак) передается алгоритму IF с настройкой по умолчанию.
Полный код выглядит следующим образом:
from sklearn import datasets
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import IsolationForest
from sklearn.metrics import confusion_matrix
from sklearn.metrics import recall_score, roc_curve, roc_auc_score, f1_score, precision_recall_curve, auc
from sklearn.metrics import make_scorer
from sklearn.metrics import accuracy_score
import pandas as pd
import numpy as np
import seaborn as sns
import itertools
import matplotlib.pyplot as plt
import datetime
%matplotlib inline
def byte_decoder(val):
# decodes byte literals to strings
return val.decode('utf-8')
#Load Dataset KDDCUP99 from sklearn
target = 'target'
sf = datasets.fetch_kddcup99(subset='SF', percent10=False) # you can use percent10=True for convenience sake
dfSF=pd.DataFrame(sf.data,
columns=["duration", "service", "src_bytes", "dst_bytes"])
assert len(dfSF)>0, "SF dataset no loaded."
dfSF[target]=sf.target
anomaly_rateSF = 1.0 - len(dfSF.loc[dfSF[target]==b'normal.'])/len(dfSF)
"SF Anomaly Rate is:"+"{:.1%}".format(anomaly_rateSF)
#'SF Anomaly Rate is: 0.5%'
#Data Processing
toDecodeSF = ['service']
# apply hot encoding to fields of type string
# convert all abnormal target types to a single anomaly class
dfSF['binary_target'] = [1 if x==b'normal.' else -1 for x in dfSF[target]]
leSF = preprocessing.LabelEncoder()
for f in toDecodeSF:
dfSF[f + " (encoded)"] = list(map(byte_decoder, dfSF[f]))
dfSF[f + " (encoded)"] = leSF.fit_transform(dfSF[f])
for f in toDecodeSF:
dfSF.drop(f, axis=1, inplace=True)
dfSF.drop(target, axis=1, inplace=True)
#check rate of Anomaly for setting contamination parameter in IF
dfSF["binary_target"].value_counts() / np.sum(dfSF["binary_target"].value_counts())
#data split
X_train_sf, X_test_sf, y_train_sf, y_test_sf = train_test_split(dfSF.drop('binary_target', axis=1),
dfSF['binary_target'],
test_size=0.33,
random_state=11,
stratify=dfSF['binary_target'])
#print(y_test_sf.value_counts())
#1 230899
#-1 1114
#Name: binary_target, dtype: int64
#training IF and predict the outliers/anomalies on test set with 10% contamination:
clfIF = IsolationForest(max_samples="auto",
random_state=11,
contamination = 0.1,
n_estimators=100,
n_jobs=-1)
clfIF.fit(X_train_sf, y_train_sf)
y_pred_test = clfIF.predict(X_test_sf)
#print(X_test_sf.shape)
#(232013, 4)
#print(np.unique(y_pred_test, return_counts=True))
#(array([-1, 1]), array([ 23248, 208765])) # instead of labeling 10% of 232013, which is 23201 data outliers/anomalies, It is 23248 !!
на основе документации в двоичном случае мы можем извлечь истинные положительные результаты и т. д. следующим образом:
tn, fp, fn, tp = confusion_matrix(y_test_sf, y_pred_test).ravel()
print("TN: ",tn,"FP: ", fp,"FN: " ,fn,"TP: ", tp)
#TN: 1089 FP: 25 FN: 22159 TP: 208740
Проблемы :
- Проблема 1: Мне интересно, почему ЕСЛИ предсказывают загрязнение более 10%, которое уже установлено на тестовом наборе, путем маркировки выброса / аномалии? 23248 вместо 23201 !!
- Проблема 2: нормально
TN
+FP
должно быть inlier / normal 230899 иFN
+TP
должно быть равно 1114, как мы посчитали после разделения данных. Я думаю, что в моей реализации наоборот, но я не мог понять и отладить. - Проблема 3: основано на KDDCUP99 наборе данных документов , а его руководство пользователя и мой расчет в следующей реализации скорость аномалии 0,5% , и это означает , что если я набор
contamination=0.005
, это должно дать мне
Возможно, мне здесь чего-то не хватает, и любая помощь будет принята с благодарностью.
1 ответ
Дело в том, что параметр загрязнения просто контролирует порог для функции принятия решения, когда оцененная точка данных должна считаться выбросом. На саму модель это не влияет. Может иметь смысл использовать некоторый статистический анализ, чтобы получить приблизительную оценку загрязнения.
Если вы ожидаете определенного количества выбросов в вашем наборе данных, вы можете использовать необработанные оценки, чтобы найти порог, который дает вам это число, и ретроспективно установить параметр загрязнения при применении модели к новым данным.