我试着用Keras实现加权二进制交叉熵,但我不确定代码是否正确。训练输出似乎有点混乱。几个时期后,我只得到了~0.15的精度。我认为这太少了(即使是随机猜测)。
通常在输出中有大约11%的1和89%的0,因此权重是w_zero=0.89和w_one=0.11。
我的代码:
def create_weighted_binary_crossentropy(zero_weight, one_weight):
def weighted_binary_crossentropy(y_true, y_pred):
# Original binary crossentropy (see losses.py):
# K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
# Calculate the binary crossentropy
b_ce = K.binary_crossentropy(y_true, y_pred)
# Apply the weights
weight_vector = y_true * one_weight + (1. - y_true) * zero_weight
weighted_b_ce = weight_vector * b_ce
# Return the mean error
return K.mean(weighted_b_ce)
return weighted_binary_crossentropy
也许有人看出了什么问题?
谢谢
7条答案
按热度按时间lh80um4z1#
通常情况下,少数类的类权重较高,最好使用
one_weight=0.89, zero_weight=0.11
(顺便说一句,你可以使用class_weight={0: 0.11, 1: 0.89}
,就像评论中建议的那样)。在类不平衡的情况下,模型看到的0比1多得多。它还将学习预测更多的0,因为这样做可以最大限度地减少训练损失。这也是为什么你看到的准确率接近比例0.11。如果你对模型预测取平均值,它应该非常接近零。
使用类权重的目的是改变损失函数,使训练损失不能通过“简单解决方案”(即预测0)最小化,这就是为什么对1使用更高的权重会更好。
请注意,最佳权重不一定是0.89和0.11。有时,您可能需要尝试一些方法,如取对数或平方根(或满足
one_weight > zero_weight
的任何权重)才能使其工作。rqcrx0a62#
您可以使用sklearn module自动计算每个类的权重,如下所示:
注意,
class_weight.compute_class_weight()
的输出是一个numpy数组,如下所示:[2.57569845 0.68250928]
.yvt65v4c3#
我认为在www.example.com中使用类权重model.fit是不正确的。{0:0.11,1:0.89},这里的0是索引,而不是0类。Keras文档:https://keras.io/models/sequential/类_权重:将类索引(整数)Map到权重(浮点)值的可选字典,用于加权损失函数(仅在训练期间)。这对于告知模型“更多关注”来自表示不足的类的样本非常有用。
flseospp4#
在
model.fit
中使用class_weights
略有不同:它实际上更新样本而不是计算加权损失。我还发现当
x
作为TFDataset或生成器发送到www.example.com时,class_weights
和sample_weights
在TF 2.0.0中被model.fit忽略。这是我的加权二进制交叉熵函数的多热点编码标签。
vawmfj5a5#
你可以像这样计算权重,并得到像这样的二进制交叉熵,它将编程地把one_weight设置为0.11,把one_weight设置为0.89:
bprjcwpo6#
对我来说,最好的方法是这样做的:
zqry0prt7#
如果您需要一个权重与训练损失不同的加权验证损失,您可以使用www.example.com()的参数validation_datatensorflow.keras.model.fit,方法是将验证数据集作为Numpy数组的元组,其中包含验证数据、标签和每个样本的权重。
请注意,您必须使用此技术将每个样本Map到其权重(此处按类)。
点击此处链接:https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit
tensorflow documentation