简体   繁体   English

基于错误百分位数的Keras中的自定义加权MSE损失函数

[英]Custom weighted MSE loss function in Keras based on error percentile

I'm new to Keras and neural networks in general. 我是Keras和神经网络的新手。 I'm trying to implement a custom loss function based on mean squared error for a multi-layer autoencoder to be used in anomaly detection. 我正在尝试针对要用于异常检测的多层自动编码器实现基于均方误差的自定义损失函数。 Basically the approach I'm going for is from here https://www.jstage.jst.go.jp/article/ipsjjip/27/0/27_335/_pdf 基本上我要使用的方法是从这里https://www.jstage.jst.go.jp/article/ipsjjip/27/0/27_335/_pdf

Unfortunately I don't have the reputation to post images as I'm also new to SO but the formula is on page 2, section 3 as Lprop 不幸的是,我没有发布图像的声誉,因为我也是SO的新手,但是该公式在第2页的第3节为Lprop

The intuition here is that I don't want the autoencoder to update weights for data points that return errors above the ap percentile of losses. 直觉是,我不希望自动编码器为返回错误的损耗百分比以上的数据点更新权重。 This way it learns to reconstruct the inliers in the dataset while struggling with the outliers, hence detecting them as anomalous. 通过这种方式,它学会了在与异常值作斗争的同时重建数据集中的异常值,从而将其检测为异常。

Here's some code I've tried and the compiled model 这是我尝试过的一些代码和编译后的模型

import keras.backend as K
c = 70.0
    def mean_squared_errorx(y_true, y_pred):
        es = K.square(y_pred - y_true)
        const = np.percentile(es, c)
        w = K.cast(K.less(const, K.mean(K.square(y_pred - y_true), axis=-1)), dtype = "float32")
        return w * K.mean(K.square(y_pred - y_true), axis=-1)

    #'mean_squared_error'
    autoencoder.compile(optimizer=adam, loss=mean_squared_errorx)
    autoencoder.fit(train, train,
                    epochs=num_epochs,
                    batch_size=round(len(train)/50),
                    shuffle=True,
                    validation_data=(train, train),
                    verbose = 0)
    encoded_d = encoder.predict(train)
    decoded_pred = decoder.predict(encoded_d)

The idea is to get the K.less to return a bool for each error, and then to convert it to a float to serve as a weight in the return statement. 这个想法是让K.less为每个错误返回布尔值,然后将其转换为浮点数,以作为return语句中的权重。 I know the np.percentile part probably won't work on a Tensor but don't know how else to accomplish the percentile ranking. 我知道np.percentile部分可能无法在Tensor上使用,但不知道如何通过其他方法来完成百分位排名。

With that code I'm getting this error message 使用该代码,我收到此错误消息

InvalidArgumentError: Incompatible shapes: [37,21] vs. [37]
     [[{{node loss_25/dense_104_loss/Less}}]]

where in this case the batch size is 37 and the number of features is 21. I appreciate any feedback on this or other parts of the code - thanks! 在这种情况下,批处理大小为37,功能数为21。感谢您对此代码或其他部分的反馈,谢谢!

Found a potential workaround if anybody is working on something similar 如果有人在做类似的事情,发现了一个潜在的解决方法

import keras.backend as K
    def mean_squared_error_w(y_true, y_pred):
        mses = K.mean(K.square(y_pred - y_true), axis = -1)
        std_of_mses = K.std(mses)
        const = K.mean(mses, axis = -1) + (std_of_mses * 0.5)
        mask = K.cast(K.less(K.mean(K.square(y_pred - y_true), axis=-1), const), dtype = "float32")
        return mask * K.mean(K.square(y_pred - y_true), axis=-1)

I believe this will create a tensor of bools for all of the values where the error is larger than a threshold value, defined by the mean of the batch MSEs plus half a standard deviation (if the errors were normally distributed this should correspond to about the 70th percentile of the data as the cutoff). 我相信这将为误差大于阈值的所有值创建一个布尔张量,该阈值由批MSE的平均值加标准偏差的一半定义(如果误差呈正态分布,则该值应对应于数据的第70个百分位数作为截止值)。 It converts the bools to the weights 0 or 1 as a mask which is then applied to the output MSE loss 它将布尔值转换为权重0或1作为掩码,然后将其应用于输出MSE损失

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM