可能的解决方案
我认为您应该使用几乎标准的,并从网络输出logits,这将使用argmax
操作将其映射到值[0,1,2,3,4]
中的损失函数(同样的过程将应用于one-hot-encoded
标签,有关示例,请参见本答案的最后部分)。
使用加权crossentropy
,您可以根据预测值与正确值
不同地处理不正确性,就像您在评论中所说的那样。
您需要做的就是取正确和预测值相减的绝对值,并将其乘以损失,请参见以下示例:
让我们将每个编码映射到其一元值(可以使用argmax
来完成,如下所示):
[0, 0, 0, 0] -> 0
[1, 0, 0, 0] -> 1
[1, 1, 0, 0] -> 2
[1, 1, 1, 0] -> 3
[1, 1, 1, 1] -> 4
让我们使用模型对一些随机目标和预测进行分析,以展现其本质:
Original Answer翻译成"最初的回答"
correct predicted with Softmax
0 0 4
1 4 3
2 3 3
3 1 4
4 3 1
5 1 0
现在,当你从正确的
和预测的
中相减并取绝对值时,你基本上得到了如下的加权列:
最初的回答:
weights
0 4
1 1
2 0
3 3
4 2
5 1
你可以看到,当真实目标是4时,预测为0的情况将比预测为3的情况被加权4倍,这正是你想要的结果。因此,建议按照
Daniel Möller提供的方法创建一个简单的自定义损失函数。
import tensorflow as tf
def weighted_crossentropy(labels, logits):
return tf.losses.softmax_cross_entropy(
labels,
logits,
weights=tf.abs(tf.argmax(logits, axis=1) - tf.argmax(labels, axis=1)),
)
你应该在
model.compile
中使用这个损失函数,我认为没有必要重复已经讲过的内容。
这种解决方案的缺点有:
- 对于正确的预测,梯度将等于零,这意味着网络加强连接的难度更大(将logits最大化/最小化到
+inf/-inf
)。
- 可以通过向每个加权损失添加随机噪声(额外的正则化)来缓解上述问题。也可以作为一种正则化,可能会有所帮助。
- 更好的解决方案可能是从加权情况中排除预测相等的情况(或使其为1),这不会向网络优化添加随机性。
这种解决方案的优点有:
- 您可以轻松地为不平衡的数据集添加加权(例如,某些类别出现得更频繁)。
- 映射到现有API。
- 在分类领域中概念简单。
- 您的模型无法预测不存在的分类值,例如,在多目标情况下,它可以预测
[1, 0, 1, 0]
,但是使用以上方法不会出现这种情况。较少的自由度将有助于训练并消除荒谬的(如果我正确理解您的问题描述)预测机会。
在评论中提供了额外的讨论。
以下是使用自定义损失函数的示例网络。您的标签必须进行
one-hot编码
才能正确工作。
import keras
import numpy as np
import tensorflow as tf
def weighted_crossentropy(labels, logits):
return tf.losses.softmax_cross_entropy(
labels,
logits,
weights=tf.abs(tf.argmax(logits, axis=1) - tf.argmax(labels, axis=1)),
)
model = keras.models.Sequential(
[
keras.layers.Dense(32, input_shape=(10,)),
keras.layers.Activation("relu"),
keras.layers.Dense(10),
keras.layers.Activation("relu"),
keras.layers.Dense(5),
]
)
data = np.random.random((32, 10))
labels = keras.utils.to_categorical(np.random.randint(5, size=(32, 1)))
model.compile(optimizer="rmsprop", loss=weighted_crossentropy)
model.fit(data, labels, batch_size=32)
[1, 1, 1, 0]
更接近于[1, 1, 1, 1]
而不是[0, 0, 0, 0]
。 - Shamoonclass_weights
呢? - Shamoon