【问题标题】:Keras custom loss function for binary encoded (not one-hot encoded) categorical data二进制编码(非单热编码)分类数据的 Keras 自定义损失函数
【发布时间】:2019-09-08 22:42:08
【问题描述】:

我需要帮助为 Keras 编写自定义损失/度量函数。我的类别是二进制编码的(不是一次性的)。我想在真实类和预测类之间进行逐位比较。

例如, 真实标签:0x1111111111 预测标签:0x1011101111

预测标签的 10 位中有 8 位是正确的,因此该匹配的准确度应该是 0.8 而不是 0.0。我不知道如何支持使用 Keras 命令执行此操作。

编辑 1: 目前我正在使用这样的东西,但它还没有工作:

def custom_binary_error(y_true, y_pred, n=11):
    diff_dec = K.tf.bitwise.bitwise_xor(K.tf.cast(y_true, K.tf.int32), K.tf.cast(y_pred, K.tf.int32))
    diff_bin = K.tf.mod(K.tf.bitwise.right_shift(K.tf.expand_dims(diff_dec,1), K.tf.range(n)), 2)
    diff_sum = K.tf.math.reduce_sum(diff_bin, 1)
    diff_percent = K.tf.math.divide(diff_sum, 11)
    return K.tf.math.reduce_mean(diff_percent, 0)

我收到此错误:

ValueError: Dimensions must be equal, but are 2048 and 11 for 'loss/activation_1_loss/RightShift' (op: 'RightShift') with input shapes: [?,1,2048], [11].

【问题讨论】:

  • 您的预测结果如何?是整数值还是别的什么?
  • 对我来说真是个奇怪的编码!请问您为什么选择以输出实数的方式设计模型(稍后需要将其转换为整数)?相反,您可以将其建模为一个多标签分类任务,最后一层是 sigmoid 层。
  • 所以我的最后一层将是一个密集层,其节点数与我的类编码中的位数一样多,并使用 sigmoid 激活将输出映射到 0-1。那么我的损失/准确性度量是什么?
  • @RyanHope 没错。您需要使用binary_crossentropy 作为损失,使用accuracy 作为指标(它会自动切换到binary_accuracy)。

标签: keras deep-learning categorical-data loss-function multiclass-classification


【解决方案1】:

我正在尝试假设y_true, y_pred 是正整数。

def custom_binary_error(y_true, y_pred):
    width = y_true.bit_length() if y_true.bit_length() > y_pred.bit_length() else y_pred.bit_length()       # finds the greater width of bit sequence, not sure if needed
    diff = np.bitwise_xor(y_true, y_pred)       # 1 when different, 0 when same
    error = np.binary_repr(diff, width=width).count('1')/width       # calculate % of '1's
    return K.variable(error)

使用1-error 以获得准确性。我没有测试过;这只是提供一个想法。

【讨论】:

  • 是的 y_true 和 t_pred 都是正整数,我试试看
  • 是的,试试看,让我知道。这个想法适用于 Python。还没有签入 Keras。希望我没有错过任何特定于 Keras 的内容。
  • 在 Keras 中不起作用,我应该更具体地了解 y_true 和 y_pred...它们都是 Keras 张量(但一旦评估它们应该是整数)。
  • Tensorflow 有一个 bitwise_xor,如果有办法解包位然后求和,我可以除以最大位得到百分比
  • 是的,我期待这样的问题。必须检查 TF 是否提供任何类似的功能。
【解决方案2】:

你可以这样定义你的错误:

import tensorflow as tf

def custom_binary_error(y_true, y_pred):
    y_true = tf.cast(y_true, tf.bool)
    y_pred = tf.cast(y_pred, tf.bool)
    xored = tf.logical_xor(y_true, y_pred)
    notxored = tf.logical_not(xored)
    sum_xored = tf.reduce_sum(tf.cast(xored, tf.float32))
    sum_notxored = tf.reduce_sum(tf.cast(notxored, tf.float32))
    return sum_xored / (sum_xored + sum_notxored)

用 2 个大小为 6 的标签对其进行测试:

import tensorflow as tf

y_train_size = 6

y_train = [[1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0]]
y_pred = tf.convert_to_tensor([[1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 0]])
y = tf.placeholder(tf.int32, shape=(None, y_train_size))
error = custom_binary_error(y, y_pred)
with tf.Session() as sess:
    res = sess.run(error, feed_dict={y:y_train})
    print(res) # 0.25

在Keras中使用它:

import tensorflow as tf
import numpy as np

y_train_size = 6

def custom_binary_error(y_true, y_pred):
    y_true = tf.cast(y_true, tf.bool)
    y_pred = tf.cast(y_pred, tf.bool)
    xored = tf.logical_xor(y_true, y_pred)
    notxored = tf.logical_not(xored)
    sum_xored = tf.reduce_sum(tf.cast(xored, tf.float32))
    sum_notxored = tf.reduce_sum(tf.cast(notxored, tf.float32))
    return sum_xored / (sum_xored + sum_notxored)

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(y_train_size))

model.compile(optimizer=tf.keras.optimizers.SGD(0.01),
              loss=[tf.keras.losses.MeanAbsoluteError()],
              metrics=[custom_binary_error])

y_train = np.array([[1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0]])
x_train = np.random.normal(size=(2, 2))

model.fit(x_train, y_train, epochs=2)

将导致:

Epoch 1/2
2/2 [==============================] - 0s 23ms/sample - loss: 1.4097 - custom_binary_error: 0.5000
Epoch 2/2
2/2 [==============================] - 0s 328us/sample - loss: 1.4017 - custom_binary_error: 0.5000

注意

如果你想要 accuracy 而不是 error,custom_binary_error() 函数应该返回

sum_notxored / (sum_xored + sum_notxored)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 2021-10-07
    • 1970-01-01
    • 2018-12-12
    • 2018-09-13
    相关资源
    最近更新 更多