我在使用class_weight处理多标签问题时遇到了麻烦。也就是说,每个标签要么是0要么是1,但每个输入样本有多个标签。
代码(使用随机数据作为MWE目的):
我得到的错误是:
ValueError: `class_weight` must contain all classes in the data. The classes set([330]) exist in the data but not in `class_weight`.
每次运行时’set([…])’中的值都会变化。但正如我所说,数据中只有0和1两个类别;只是每个样本有多个标签。所以例如,一个响应(y_train)看起来像这样:
print y_train[0,:]#[ 0. 0. 1. ..., 0. 1. 0.]
如何在Keras中对多标签问题使用class_weights
?
回答:
是的。这是Keras中的一个已知bug(问题#8011)。基本上,Keras代码假设使用的是独热编码,而非多标签序数编码来确定类别数量。
# 如果第二维度大于1,则必须是独热编码,# 因此我们只需获取最大索引...if y.shape[1] > 1: y_classes = y.argmax(axis=1)
目前我想不到更好的解决方法,只能设置y_true[:, 1] = 1
,即在y
中“保留”1
的位置始终为1。这样会导致y_classes = 1
(这在二元分类中是正确的值)。
为什么有效? 当y_true[i]
的值为类似[0, 0, ..., 0, 1, ...]
时,代码会失败,其中有一些前导零。Keras实现(错误地)通过最大元素的索引来估计类别数量,结果发现对于y[i][j] = 1
的某个j > 1
。这让Keras引擎认为有超过2个类别,因此提供的class_weights
是错误的。设置y_true[i][1] = 1
确保j <= 1
(因为np.argmax
选择最小的最大索引),这使得可以绕过Keras的检查。