неверные результаты IsolationForest

Меня вдохновил этот блокнот , и я экспериментирую IsolationForestалгоритм для контекста обнаружения аномалий в SF-версии набора данных KDDCUP99, включая 4 атрибута. Данные берутся напрямую из sklearn и после предварительной обработки (метка, кодирующая категориальный признак) передается алгоритму IF с настройкой по умолчанию (за исключением n_estimator, количество деревьев, которые я использовал GridsearchCV найти оптимальное количество деревьев.).

Проблема основана на KDDCUP99 наборе данных документации и ее руководство пользователя и мой расчет скорость аномалии 0,5% , и это означает , что если я набор contamination=0.005, это должно дать мне лучшие результаты, но, что удивительно, это не так!

Полный код выглядит следующим образом:

      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 classification_report, ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix
from sklearn.metrics import recall_score, silhouette_score, roc_curve, roc_auc_score, f1_score, precision_recall_curve, auc
from sklearn.model_selection import GridSearchCV
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')
def plot_confusion_matrix(cm, title, classes=["Normal", "Anomaly"],
                          cmap=plt.cm.Blues, save=False, saveas="MyFigure.png"):
    
    # print Confusion matrix with blue gradient colours
    
    cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
    
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=90)
    plt.yticks(tick_marks, classes)

    fmt = '.1%'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                horizontalalignment="center",
                color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    
    if save:
        plt.savefig(saveas, dpi=100)

#Load Dataset KDDCUP99 from sklearn
target = 'target'
sf = datasets.fetch_kddcup99(subset='SF', percent10=False)
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())



#train & 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'])

clfIF = IsolationForest(max_samples="auto", random_state=11, contamination = "auto", n_estimators=100, n_jobs=-1)

clfIF.fit(X_train_sf,y_train_sf)
y_pred_train = clfIF.predict(X_train_sf)

#Results on SF training set:
print(classification_report(y_train_sf, y_pred_train, target_names=["Anomaly", "Normal"]))
print("AUC: ", "{:.1%}".format(roc_auc_score(y_train_sf, y_pred_train)))
#AUC is about 93%.

#Results on SF training set:
clfIF = IsolationForest(max_samples="auto", random_state=11, contamination = "auto", n_estimators=100, n_jobs=-1)

clfIF.fit(X_train_sf, y_train_sf)
y_pred_test = clfIF.predict(X_test_sf)
#AUC is about 93%.


scoring = {'AUC': 'roc_auc', 'Recall': make_scorer(recall_score, pos_label=-1)}
gs = GridSearchCV(IsolationForest(max_samples="auto", random_state=11, n_jobs=-1),
                  param_grid={'n_estimators': range(1, 110, 5)},
                  scoring=scoring, refit='Recall', return_train_score=True, cv=3, verbose=1, n_jobs=-1)
gs.fit(X_train_sf, y_train_sf)
results = gs.cv_results_
gs.best_estimator_
max_recall_n_estimators = pd.DataFrame(results).iloc[np.argmax(pd.DataFrame(results)["mean_test_Recall"])]["param_n_estimators"]
print(max_recall_n_estimators)



fig, ax = plt.subplots(figsize=(8, 20))
# fig.tight_layout()

for idx, cont in zip(range(1, 4), [0.005, 0.1, 0.2]):
    iso_for_ = IsolationForest(random_state=11, 
                             n_estimators=max_recall_n_estimators,  
                             max_samples="auto",  
                             contamination=cont, 
                             n_jobs=-1)
    iso_for_.fit(X_train_sf, y_train_sf)
  
    y_pred_ = iso_for_.predict(X_test_sf)

    ax = plt.subplot(1, 3, idx)
    cm = confusion_matrix(y_test_sf, y_pred_)
    cm = np.round(cm / cm.sum(axis=1)[:, np.newaxis], decimals=2)
    cmd = ConfusionMatrixDisplay(cm, display_labels=["Anomaly", "Normal"])
    cmd.plot(ax=ax, xticks_rotation=45, cmap=plt.cm.Blues, values_format=".2%")
    cmd.ax_.set_title(f"IF (contamination = {cont}) \nconfusion matrix - SF")
    cmd.im_.colorbar.remove()
    cmd.ax_.set_xlabel('')
    cmd.ax_.set_ylabel('')

fig.text(0, 0.5, "True Label", rotation=90, va='center')
fig.text(0.4, 0.4, 'Predicted Label', ha='left')
plt.subplots_adjust(wspace=0.9)
plt.suptitle("Confusion matrix of sklearn IF for various contaminations (SF)", y=0.63)
plt.show()

Это результаты матрицы путаницы:img

Вероятно, мне здесь чего-то не хватает, и любая помощь будет принята с благодарностью.

0 ответов

Другие вопросы по тегам