背景
在网络安全领域,对异常检测算法的效率要求很高,且输入数据往往非常大,这也是为什么半监督学习的异常检测算法往往采用直方图的原因。如果处理的是高维数据,单维度的直方图很容易计算。大多数直方图相关的算法中,常常固定直方图的宽度或者手动设置宽度。论文提出了一种基于直方图的无监督异常检测算法,并且提出了动态宽度的算法以适应不均衡的长尾分布。
HBOS
HBOS算法基于多维数据各个维度的独立性假设,对于单个数据维度,先做出数据直方图。对于categroy 值,统计每个值出现的次数,并计算相对频率。对于数值特征,可以用两种方法:
- 1.静态跨度的柱状图:将值域分成K个等宽的桶,落入每个桶的值的频数作为密度的估计(桶的高度)
- 2.动态宽度柱状图:先将所有值排序,然后将连续的N/k个值装进一个桶里,其中N是所有的样例数,k是桶的个数,是一个超参数;柱状图的面积对应桶中的样例数。因为桶的宽度是有桶中第一个值和最后一个值决定的,所有桶的面积都一样,所以,每一个桶的高度可以被计算出来。这意味着跨度大的桶的高度低,即密度小,只有一种情况例外,超过k个数相等,此时一个桶里允许超过N/k个值。
之所以HBOS提供上述两种方法是因为真实的数据分布种类繁多,尤其是值域跨度大的时候。我们更倾向于使用第二种方法,尤其是值得分布位置或者长尾的情形。
按照上面的方法,每一个维度的数据都声称一个柱状图,每个桶的高度代表数据的密度,使用归一化操作保证桶最高的高度是1.这样可以保证每个特征的权重相同。最终每一个样本的HBOS值按照下面的公示计算:
# 导入相关依赖模块
from pyod.utils.data import evaluate_print,generate_data
from pyod.models.hbos import HBOS
from pyod.utils.example import visualize
# pyod中用于生成toy数据的方法主要是:
# 1、pyod.utils.data.generate_data()
# 2、pyod.utils.data.generate_data_clusters()
# 于是....生成toy example:
contamination = 0.05 # percentage of outliers
n_train = 1000 # number of training points
n_test = 500 # number of testing points
X_train, y_train, X_test, y_test = generate_data(n_train=n_train, n_test=n_test, contamination=contamination)
# 初始化HBOS模型
clf_name = 'HBOS'
clf = HBOS()
clf.fit(X_train)
# get the prediction labels and outlier scores of the training data
y_train_pred = clf.labels_ # binary labels (0: inliers, 1: outliers)
y_train_scores = clf.decision_scores_ # raw outlier scores
# get the prediction on the test data
y_test_pred = clf.predict(X_test) # outlier labels (0 or 1)
y_test_scores = clf.decision_function(X_test) # outlier scores
# evaluate and print the results
print("\nOn Training Data:")
evaluate_print(clf_name, y_train, y_train_scores)
print("\nOn Test Data:")
evaluate_print(clf_name, y_test, y_test_scores)
# 可视化展示训练集、测试集异常检测结果
visualize(clf_name, X_train, y_train, X_test, y_test, y_train_pred,
y_test_pred, show_figure=False, save_figure=True)