一. 介绍
异常检测(Anomaly detection)是目前时序数据分析最成熟的应用之一,定义是从正常的时间序列中识别不正常的事件或行为的过程。有效的异常检测被广泛用于现实世界的很多领域,例如量化交易,网络安全检测、自动驾驶汽车和大型工业设备的日常维护。
本文在上一篇学习笔记
VoidOc:时间序列异常检测(一)—— 算法综述zhuanlan.zhihu.com的基础上,将会呈现之前提及的一些深度/传统机器学习算法模型基于KDD99以及NSL_KDD数据集的性能表现,并结合具体数据情况给出各个模型的评估结果,并做一个总结。
那么让我们开始吧~
二. KDD数据集
- KDDCup99
介绍:https://blog.csdn.net/abrohambaby/article/details/78702512
下载链接:KDD Cup 1999 Data
全集很大有约500w数据,建议使用10%的这个data files 大约50w数据量,用于检验模型性能比较合理。
- NSL_KDD
介绍: https://www.unb.ca/cic/datasets/nsl.html
下载链接:https://github.com/defcom17/NSL_KDD
NSL_KDD在KDDCup99数据集的基础上进行了一下改进:
通常选择这两个数据集作为Training data 和 Testing data:
三. 数据预处理
对于连续数值,我们使用scikit-learn库提供的MinMaxScaler来对数值进行归一化
至于离散数值,我们使用一种One-Hot编码。 encode_text函数可实现此目的。
# Helper function for scaling continous values
def minmax_scale_values(training_df,testing_df, col_name):
scaler = MinMaxScaler()
scaler = scaler.fit(training_df[col_name].values.reshape(-1, 1))
train_values_standardized = scaler.transform(training_df[col_name].values.reshape(-1, 1))
training_df[col_name] = train_values_standardized
test_values_standardized = scaler.transform(testing_df[col_name].values.reshape(-1, 1))
testing_df[col_name] = test_values_standardized
#Helper function for one hot encoding
def encode_text(training_df,testing_df, name):
training_set_dummies = pd.get_dummies(training_df[name]) # get_dummies 是利用pandas实现one hot 编码的方式
testing_set_dummies = pd.get_dummies(testing_df[name])
for x in training_set_dummies.columns:
dummy_name = "{}_{}".format(name, x)
training_df[dummy_name] = training_set_dummies[x]
if x in testing_set_dummies.columns :
testing_df[dummy_name]=testing_set_dummies[x]
else :
testing_df[dummy_name]=np.zeros(len(testing_df))
training_df.drop(name, axis=1, inplace=True)
testing_df.drop(name, axis=1, inplace=True)
sympolic_columns=["protocol_type","service","flag"]
label_column="Class"
for column in df.columns :
if column in sympolic_columns:
encode_text(training_df,testing_df, column)
elif not column == label_column:
minmax_scale_values(training_df,testing_df, column)
四.建模
4.1 基于 AE 自编码器的时间序列异常检测代码实现(Tensorflow,Keras前端接口)
- 模型介绍
为了避免训练数据中代表每种攻击类型的样本不平衡,并避免模型无法通过观察现有攻击类型来学习新的攻击类型,我们提出一种利用AE自动编码器和重构误差来检测异常的方法。
在这种方法中,我们实现了带有输入缺失的稀疏自动编码器,它由122个神经元的输入层组成,这是因为每个样本的特征数量为122,然后是缺失层和8个神经元单元的隐藏层.因此,自动编码器的隐藏表示形式具有122/8的压缩比,迫使其学习有趣的模式和特征之间的关系,最后有122个单元的输出层,隐藏层和输出层的激活函数是relu。
对自动编码器进行了训练以重建其输入,换言之,它学习了身份函数,仅使用训练数据集中标有“正常”的样本对模型进行了训练,从而可以捕获正常行为的性质,这是通过训练模型以最小化其输出和输入之间的均方误差 MSE (mean squared error)。
在自动编码器上施加的正则化约束阻止了它简单地将输入复制到输出并过度拟合数据,此外,输入上出现的缺失使自动编码器成为去噪自动编码器的特殊情况,这种自动编码器经过训练可以重建输入从本身已失真的损坏版本中删除,迫使自动编码器学习更多数据属性。
有关算法细节我觉得张老师这篇讲的挺好的,大家可以拓展看看。
张戎:基于自编码器的时间序列异常检测算法zhuanlan.zhihu.com- 训练
使用Adam优化器(batch大小为100)对模型进行了10个epoch的训练,此外,我们保留了10%的正常训练样本作为 validation data 来验证模型的效果。
def getModel():
input_layer = Input(shape=(x.shape[1],))
encoded = Dense(8, activation='relu', activity_regularizer=regularizers.l2(10e-5))(input_layer) # l2正则化约束
decoded = Dense(x.shape[1], activation='relu')(encoded)
autoencoder = Model(input_layer, decoded)
autoencoder.compile(optimizer='adam', loss='mean_squared_error')
return autoencoder
autoencoder = getModel()
history = autoencoder.fit(
x[np.where(y0==0)],x[np.where(y0==0)],
epochs=