使用 Keras 进行异常检测 - 低预测率

Posted

技术标签:

【中文标题】使用 Keras 进行异常检测 - 低预测率【英文标题】:Anomaly Detection Using Keras - Low Prediction Rate 【发布时间】:2021-03-24 07:26:39 【问题描述】:

我使用自动编码器构建了一个异常检测系统,在 keras 中实现。 我的输入是一个长度为 13 的归一化向量。 我的数据集包含大约 25,000 个非异常输入,专门用于学习。 在学习了 1-3 个 epoch 后,我得到了大约 10^-5 MSE。 问题是,虽然我得到了一个小的 MSE,但我的 AE 无法检测到足够好的异常...... 模型类:

class AutoEncoder:
    def __init__(self, inputLen, modelName,Batch,epochs):
        self.modelName       = modelName
        self.DL_BATCH_SIZE   = Batch
        self.DL_EPOCHS       = epochs
        self.DL_LAYER1       = 200
        self.DL_LAYER2       = 150
        self.DL_LAYER3       = 100
        self.DL_LAYEROUT     = 13
        self.DL_LOADMODEL    = None
        #self.DL_SAVEMODEL    = fileConfig.getConfigParam(DL_SAVEMODEL)
        #print(tensorflow.version.VERSION)
        
        
        if self.DL_LOADMODEL == None or self.DL_LOADMODEL == 0:
            my_init = keras.initializers.glorot_uniform(seed=1)
            self.dlModel = keras.models.Sequential()
            
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYER1, activation='tanh', input_dim=inputLen,kernel_initializer=my_init))
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYER2, activation='tanh',kernel_initializer=my_init))
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYER3, activation='tanh',kernel_initializer=my_init))
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYER2, activation='tanh',kernel_initializer=my_init))
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYER1, activation='tanh',kernel_initializer=my_init))
            self.dlModel.add(keras.layers.Dense(units=self.DL_LAYEROUT, activation='tanh',kernel_initializer=my_init))
            #sgd = keras.optimizers.SGD(lr=0.0001, decay=0.0005, momentum=0, nesterov=True)
            #adam = keras.optimizers.Adam(learning_rate=0.005,decay=0.005)
            simple_adam=keras.optimizers.Adam()
            self.dlModel.compile(loss='mse', optimizer=simple_adam, metrics=['accuracy'])
        else:
            self.dlModel = keras.models.load_model(self.DL_LOADMODEL + ".h5")

训练后,我在 2500 个非异常的特定数据集上找到了最大重建 MSE。 然后我测试我的异常检测器并将其重建的每个输入都标记为异常,该输入超过最大 MSE*0.9 值。 找到最大误差:

N = len(non_anomaly)
max_se = 0.0;
max_ix = 0
second_max=0
predicteds = kerasNN.predict(non_anomaly)
for i in range(N):
  curr_se = np.square(np.subtract(non_anomaly[i],predicteds[i])).mean()
  if curr_se > max_se:
    second_max=max_se
    max_se = curr_se; 
    max_ix = i

测试模型:

    predicteds=kerasNN.predict(x_train_temp)

#errors vector generation
anomaly_binary_vector = []
i=0
anomalies=0
for x_original,x_reconstructed in zip(x_train_temp,predicteds):
    MSE=np.square(np.subtract(x_original,x_reconstructed)).mean()
    if(MSE>=0.95*max_se):
        anomaly_binary_vector.append(1)
    else:
        anomaly_binary_vector.append(0)
    i+=1

输出:

anomalies 2419
not detected anomalies   2031
non anomaly but marked as anomaly   2383
percentage of non anomaly instructions that marked as anomalies out of non anomalies : 0.3143384777733808
percentage of  anomaly instructions that wasn't detected out of anomalies: 0.8396031417941298

如何改进我的异常检测?

【问题讨论】:

您是否也使用正常数据训练了您的模型,还是只看到了异常? 您应该绘制异常分数的直方图,标记的异常和非异常的颜色不同。然后你会看到你的模型能够区分两者 【参考方案1】:

一个问题可能是你正在“炸毁”你是自动编码器。您的输入为 13,然后再次将其映射到 200、150、100 和 13。网络中没有瓶颈,它必须学习输入的压缩表示。

也许尝试 13 -> 6 -> 4 -> 6 -> 13 或类似的东西。比它学习压缩表示和重建输入的任务不再是微不足道的。

另外使用其他超参数,如激活函数。也许在中间模型中将其更改为“relu”。

【讨论】:

首先,感谢您的回答。通过将层的宽度更改为 13->6>4>6>13,我没有得到改进。并通过将“中间”层更改为 relu ... 10^-5 MSE 不够准确以检测异常吗? 不看数据很难说。您是否尝试过其他一些分类器来检测异常值,例如“隔离森林”或“Oneclass SVM”?如果是这样,他们的表现如何?也许数据只是不适合这种任务 没有。我会尝试 。不适合这种任务是指一般的异常检测或特别是 AE? 是的,我指的是一般的异常检测。但我想如果它至少在某种程度上适用于其他技术,那么可能有办法让它也适用于 AE。

以上是关于使用 Keras 进行异常检测 - 低预测率的主要内容,如果未能解决你的问题,请参考以下文章

CNN autoencoder 进行异常检测——TODO,使用keras进行测试

用于时间序列异常检测的 Keras LSTM-VAE(变分自动编码器)

系统检测到异常流量,请问这个该如何解决

功能异常强大,推荐这款 Python 时序异常检测神器

# URL异常检测

openGauss数据库源码解析系列文章—— AI技术之“指标采集预测与异常检测”