你能帮我用系统调用序列进行异常检测吗?

问题描述

这就是我要回答的问题。我正在尝试自己开发一个端到端框架来处理序列,以便使用 Tensorflow 和 Keras 获得异常检测框架。

我在 OpenReview 的这篇论文中发现了一个想法:LSTM-Based System-Call Language Modeling and Ensemble Method for Host-Based Intrusion Detection。 这是完整文本的链接https://openreview.net/pdf?id=rksfwnFxl

Picture of the key idea

本文的主要思想是构建 N 个语言模型,将它们组合成一个集成分类器,该分类器也是一个神经网络。

使用的数据集是 ADFA-LD,位于:https://www.unsw.adfa.edu.au/unsw-canberra-cyber/cybersecurity/ADFA-IDS-Datasets/ 它有 3 个文件夹:正常、验证和攻击数据。正常和验证分别是833和4300个文件,它们没有异常序列,它们很相似。系统调用是从 1 到 340 的数字,每个文件都有不同长度的系统调用

根据论文,每种语言模型都具有以下特征:

在输入层,每个时间步xi的调用 以 one-hot 编码的形式输入模型,换句话说,一个 K 维向量,除了位置 xi 之外,所有元素都为零。在嵌入层,通过乘以嵌入矩阵 W 将传入呼叫嵌入到连续空间中,这应该是学习的。在隐藏层,LSTM 单元有一个内部状态,这个状态在每个时间步都被循环更新。在输出层,使用 softmax 激活函数来估计序列中下一个可能调用的归一化概率值

我已尝试将其转换为代码。 X_train 是从 AFDA 的正常训练文件夹中单热编码的所有序列,但没有最后一个系统调用,即 y_train。 因此,这两个张量的形状为:X_train (833,75,341) 和 y_train (833,341)

model_1 = Sequential() 

model_1.add(Dense(units = 200,input_shape=X_train[0].shape,kernel_initializer=tf.keras.initializers.Randomnormal(mean=0.,stddev=0.1),kernel_constraint = Maxnorm(max_value=5,axis=0),name="dense-embedding"))

model_1.add(LSTM(units=200,dropout=0.5,name="LSTM"))

model_1.add(Dense(units=feature_dimension,activation='softmax',name="output"))

opt = keras.optimizers.Adam(learning_rate=0.0001)

# Compile
start = time.time()
model_1.compile(loss="categorical_crossentropy",optimizer=opt,metrics=['accuracy'])
print("Compilation time for language model 1 (1 x 200 LSTM) : ",time.time() - start)
model_1.summary()

#Training
print("Training neural network...")
model_1.fit(X_train,y_train,epochs=epochs,batch_size=batch_size)

# Save as file
model_1.save('language_model_1.h5')
return model_1

论文的第 3.2 节描述了每一个的超参数和模型:

我们使用 ADFA-LD 并通过更改 LSTM 层的超参数构建了三个独立的系统调用语言模型:(1)一层有 200 个单元,(2)一层有 400 个单元,以及(3 ) 两层有 400 个单元格。我们匹配了单元格的数量和嵌入向量的维度。我们的参数在 [−0.1,0.1] 中统一初始化。为了计算效率,我们将小批量中的所有系统调用序列调整为相似的长度。我们使用 Adam 优化器 (Kingma & Ba,2014) 进行随机梯度下降,学习率为 0.0001。归一化梯度在其范数超过 5 时重新缩放(Pascanu 等,2013),我们使用概率为 0.5 的 dropout(Srivastava 等,2014)。

因此,要构建剩余的两个模型,代码将完全相同,但是将第二个模型的 LSTM 层中的单元从 200 修改为 400,并添加一个具有 400 的 LSTM 层(2 层,每层 400 个单元)对于第三个模型。

然后,我开始了下一步:构建阈值分类器和最终集成。

Key idea for the threshold classifiers and ensemble

我的阈值分类器的代码用于每个语言模型:

def threshold_classificator(model,X_train,y_train):

threshold = 0.01
anomaly = []
avg_nll_values = []
probabilities = model.predict(X_train)
y_train = np.array(y_train)

#Iterate over all sequences
for i in range(0,X_train.shape[0]):
    #Calculate avg neg-log-likelihood
    avg_nll = -np.log(y_train[i] @ probabilities[i])/(sequence_length+1)

    avg_nll_values.append(avg_nll)
    if avg_nll <= threshold:
        anomaly.append(0)
    else:
        anomaly.append(1)

return anomaly,avg_nll_values,probabilities

我的合奏代码是:

def build_ensemble_classifier(probabilities_avg,y_train):

    ensemble_network = Sequential()

    initializer_bias = tf.keras.initializers.Constant(np.median(probabilities_avg[0]))
    initializer_weights = tf.keras.initializers.Constant(1/3)
    ensemble_network.add(Dense(units = 3,bias_initializer=initializer_bias,kernel_initializer=initializer_weights,name="input"))
    ensemble_network.add(LeakyReLU(alpha=0.001,name="hidden-RELU"))
    ensemble_network.add(Dense(feature_dimension,activation="softmax",name='output'))

    #Compile
    start = time.time()
    ensemble_network.compile(loss="categorical_crossentropy",optimizer='adam',metrics=['accuracy'])
    print("Compilation time for ensemble classifier : ",time.time() - start)

    #Train
    print("Training neural network...")
    ensemble_network.fit(probabilities_avg,epochs=epochs)

    ensemble_network.summary()

    # Save as file
    ensemble_network.save('ensemble_network.h5')

    return ensemble_network

我从三种语言模型中得到的准确率分别为 60%、83% 和 70%。但我无法得到与论文相同的结果。摘自论文:

ROC curves

我没有包括 KNN 和 KMeans 算法,因为论文说这会降低其性能

我不知道如何管理阈值。我不确定 ensemble 网络是否正常。 根据论文,我应该如何结合来自三个模型的预测? 我应该如何对最终输出进行编码?

我想知道我做错了什么。如果您需要更多信息,我很乐意与您分享

先谢谢大家!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)