python - 如何使用 keras 计算具有 4 个神经元的输出的类权重?

标签 python tensorflow keras

我已经了解了如何对单个分类进行类权重不平衡校正。但就我而言,我的输出层是:

model.add(Dense(4, activation='sigmoid'))

我的 target 是一个 DataFrame,它有:

       0  1  2  3
0      1  1  0  0
1      0  0  0  0
2      1  1  1  0
3      1  1  0  0
4      1  1  0  0
5      1  1  0  0
6      1  0  0  0
...   .. .. .. ..
14989  1  1  1  1
14990  1  1  1  0
14991  1  1  1  1
14992  1  1  1  0

[14993 rows x 4 columns]

我的预测可以采用 5 个可能值之一的形式:

[[0, 0, 0, 0],
[1, 0, 0, 0],
[1, 1, 0, 0],
[1, 1, 1, 0],
[1, 1, 1, 1]]

但是,这些类肯定是不平衡的。我已经看到如何计算 class weights if I have 1 target output使用 softmax,但这略有不同。

具体来说,

model.fit(..., class_weights=weights)

在这种情况下如何定义权重

最佳答案

可能的解决方案

IMO 你应该使用几乎标准的 categorical_crossentropy 并从网络输出 logits,它将在损失函数中映射到值 [0,1,2,3,4]使用 argmax 操作(相同的过程将应用于 one-hot-encoded 标签,请参阅本答案的最后一部分以获取示例)。

使用加权交叉熵,您可以根据您在评论中指出的预测值与正确值 不同地处理不正确性。

您所要做的就是取减去正确值和预测值的绝对值并将其乘以损失,请参见下面的示例:

让我们将每个编码映射到它的一元值(可以使用 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

然后让我们通过模型进行一些随机目标和预测以查看本质:

   correct  predicted with Softmax
0        0                       4
1        4                       3
2        3                       3
3        1                       4
4        3                       1
5        1                       0

现在,当您减去 correctpredicted 并取绝对值时,您基本上会得到这样的权重列:

   weights
0        4
1        1
2        0
3        3
4        2
5        1

如您所见,当真实目标为 4 时,0 的预测权重将是 3 的预测权重的 4 倍4 目标,这就是您本质上想要的 IIUC。

作为Daniel Möller在他的回答中指出,我建议您也创建一个自定义损失函数,但要简单一些:

import tensorflow as tf

# Output logits from your network, not the values after softmax activation
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 中使用这个损失,我认为没有必要重申已经提出的观点。

该方案的缺点:

  • 对于正确的预测,梯度将等于零,这意味着网络将更难加强连接(最大化/最小化朝向 +inf/-inf 的 logits)
  • 可以通过向每个加权损失添加随机噪声(附加正则化)来缓解上述问题。也可以作为正则化,可能会有所帮助。
  • 更好的解决方案可能是排除预测值相等(或使其为 1)的加权情况,这样不会为网络优化添加随机化。

该方案的优点:

  • 您可以轻松地为不平衡的数据集添加权重(例如,某些类出现的频率更高)
  • 干净地映射到现有 API
  • 概念上简单并保持在分类领域
  • 您的模型无法预测不存在的分类值,例如对于你的多目标案例,它可以预测 [1, 0, 1, 0],上面的方法没有这样的。较低的自由度将有助于它训练和消除无意义(如果我对你的问题描述正确)预测的机会。

评论中聊天室提供的额外讨论

具有自定义损失的示例网络

这是一个带有上面定义的自定义损失函数的示例网络。 您的标签必须是 one-hot-encoded 才能正常工作。

import keras    
import numpy as np
import tensorflow as tf

# You could actually make it a lambda function as well
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)

关于python - 如何使用 keras 计算具有 4 个神经元的输出的类权重?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55010794/

相关文章:

python - 有条件地设置 Pandas 数据框列值

python - 无法获得新的 tf.Operation 在 Tensorflow 的 Python shell 中工作

tensorflow - 将字典提供给 tensorflow 函数时,我得到为什么我得到 TypeError : unhashable type: 'numpy.ndarray'

tensorflow - API 序列上的 Word2Vec + LSTM

python - Keras 模型永远用 dask 数据框进行训练

tensorflow - 基于AUC的提前停止

machine-learning - 使用 Keras 进行迁移学习,验证准确性不会从一开始就提高(超出原始基线),而训练准确性会提高

python - 在 PostgreSQL 上使用 CTE() 进行 SQLAlchemy 查询

python - Scrapy Python For 语句

python - 返回满足特定条件的多维数组的子集?