【问题标题】:doing some math in custom loss function in keras在 keras 的自定义损失函数中做一些数学运算
【发布时间】:2017-11-16 14:46:42
【问题描述】:

我创建了一个具有三个密集层的 keras 序列模型,我只是创建了一个自定义损失函数,如下所示:

def lossFunctionality(y_t, y_p):
    # 'y_t' shape is (bach_size, 500)
    # 'y_p' shape is (bach_size, 256) (output of last layer)
    # 'v' is np array of shape (500, 256)

    p = K.exp(K.dot(y_p, K.transpose(v)))
    sp = K.sum(p,axis=1)
    sp = K.expand_dims(sp, axis=1)
    sp = K.tile(sp,(1, len(v)))

    soft = p/sp
    soft=K.clip(soft, 0.0000001, 0.9999999)
    obj = K.categorical_crossentropy(soft, y_t)
    return obj

有了这个损失函数,一切都很好。

但现在假设我为 'y_p' 中的每条记录都有特定的 'v' 数组,并且我想做代码的第 5 行,以使 'y_p' 的点积与记录特定的 'v' 数组。换句话说,我有 'v' 向量的 bach_size 数量,我想将 'y_p' 中的每条记录乘积到那个特定的 'v' 数组中。我想要的显示如下:

def lossFunctionality(y_t, y_p):
    tempArray=[]
    for record in y_p:
        tempArray.append(K.exp(K.dot(record, K.transpose(v))))
    p=np.array(tempArray)
    sp = K.sum(p,axis=1)
    sp = K.expand_dims(sp, axis=1)
    sp = K.tile(sp,(1, len(v)))

    soft = p/sp
    soft=K.clip(soft, 0.0000001, 0.9999999)
    obj = K.categorical_crossentropy(soft, y_t)
    return obj

但我收到错误“张量”对象不可迭代。 我怎样才能以正确的方式实现我的损失函数 非常感谢您的帮助

【问题讨论】:

  • 我认为错误出现在代码的第 3 行。“记录在 y_p”
  • 你是对的,我知道错误来自那一行。我想知道如何以正确的方式实现这个逻辑
  • 我的意思是如何遍历 Tensor 对象

标签: python tensorflow deep-learning keras tensor


【解决方案1】:

您不应该真正迭代张量或在损失函数中使用列表、numpy 数组等。

理想情况下,您必须使用backend 函数完成所有操作,这些函数可以与张量一起正常工作。

如果我没有正确理解它,您需要的是一个 batch_dot 函数,如果您确实需要转置“v”,则可能与 permute_dimensions 相关联。

我假设您有一个“v”向量列表,对吧?我会回答它,就好像我的代码中的“v”是一个形状为(batch_size, 500, 256)的numpy数组。

import keras.backend as K

--------------

#transform v in a tensor
vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)   

#transposing v without changing the batch dimension
vTrans = K.permute_dimensions(vTens,(0,2,1)) 

#doing a batch dot
dotResult = K.batch_dot(y_p,vTrans,axes=[1,2])

batch_dot 中,考虑了轴 1 和轴 2,而轴 0 是批量大小,将保持不变。

关于您的功能的重要说明:

您将无法拥有不同尺寸的 y_py_t。这简直不能接受。您的模型预测必须与您的真实值具有完全相同的形状。

fit 方法(或任何其他训练方法)中肯定会出现错误,告诉您您的尺寸不匹配。

您确实需要有一个层来到达损失函数之前转换您的输出,因此y_py_t 具有相同的维度。

为此,请使用LambdaLayer

model.add(LambdaLayer(transformOutput, output_shape=(500,))

transformOutput 是您之前描述的函数,也适用于张量。

def transformOutput(x):
    #transform v in a tensor
    vTens = K.variable(v) #maybe having vTens already instanced and transposed outside the loss function would result in better performance (if it's constant)   

    #transposing v without changing the batch dimension
    vTrans = K.permute_dimensions(vTens,(0,2,1)) 

    #doing a batch dot
    return K.batch_dot(x,vTrans,axes=[1,2])

【讨论】:

  • 我运行了您的解决方案。假设我有 bach_size=2,那么我得到了这个错误:'形状必须是 2 级,但对于 'MatMul'(操作:'MatMul')是 3 级,输入形状:[?,256],[2,256,500]。'跨度>
  • 我只是通过添加这一行使其工作: x = tf.expand_dims(x, axis=K.ndim(x) if 1 == K.ndim(x) - 1 else K.ndim (x)) 并删除转置线。
猜你喜欢
  • 2019-03-13
  • 2020-12-19
  • 2017-12-18
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
  • 2017-12-29
  • 2018-11-12
相关资源
最近更新 更多