在自定义损失函数中迭代张量

时间:2019-04-02 09:28:09

标签: python keras conv-neural-network

对于CNN,我需要使用此损失函数,list_distance和list_residual是隐藏层的输出张量,这对于计算损失非常重要,但是当我执行代码时,它会给我返回此错误

TypeError:仅在启用急切执行后,张量对象才可迭代。要遍历此张量,请使用tf.map_fn。

还有另一种方法可以在不使用构造函数的情况下遍历张量 在X中使用x还是将其转换为numpy数组或使用keras的后端函数?


def DBL(y_true, y_pred, list_distances, list_residual, l=0.65):
    prob_dist = []
    Li = []

    # mean of the images power spectrum
    S = np.sum([np.power(np.abs(fp.fft2(residual)), 2)
                for residual in list_residual], axis=0) / K.shape(list_residual)[0]
    # log-ratio between the geometric and arithmetic of S
    R = np.log10((scistats.gmean(S) / np.mean(S)))

    for c_i, dis_i in enumerate(list_distances):
        prob_dist.append([
            np.exp(-dis_i) / sum([np.exp(-dis_j) if c_j != c_i else 0 for c_j, dis_j in enumerate(list_distances)])
        ])
    for count, _ in enumerate(prob_dist):
        Li.append(
            -1 * np.log10(sum([p_j for c_j, p_j in enumerate(prob_dist[count])
                               if y_pred[count] == 1 and count != c_j])))

    L0 = np.sum(Li)

    return L0 - l * R

1 个答案:

答案 0 :(得分:1)

您需要定义一个自定义函数以填充到tf.map_fn()-Tensorflow dox

映射器函数使用您定义的函数将(有趣的)现有对象(张量)映射为一个新对象。

它们将自定义函数应用于对象中的每个元素,而不会引起for循环的麻烦。

例如(未经测试的代码,可能无法在我的手机atm上运行):

def custom(a):
    b = a + 1
    return b

original = np.array([2,2,2])
mapped = tf.map_fn(custom, original)
# mapped == [3, 3, 3] ... hopefully

Tensorflow示例全部使用lambda函数,因此如果上述方法不起作用,则可能需要像这样定义函数。 Tensorflow示例:

elems = np.array([1, 2, 3, 4, 5, 6])
squares = map_fn(lambda x: x * x, elems)
# squares == [1, 4, 9, 16, 25, 36]

编辑:

顺便说一句,map函数比for循环更容易并行化-假定对象的每个元素都是唯一处理的-因此您可以通过使用它们来提高性能。

编辑2:

对于“减少总和,但不在此索引上”部分,我强烈建议您开始回顾矩阵运算...如上所述,map函数以元素为单位工作-他们不知道其他元素。 reduce函数是您想要的,但是当您尝试执行“ not this index”求和时,即使它们很狡猾... tensorflow还是围绕矩阵操作构建的...不是MapReduce范式。

遵循这些思路可能会有所帮助:

sess = tf.Session()
var = np.ones([3, 3, 3]) * 5

zero_identity = tf.linalg.set_diag(
    var, tf.zeros(var.shape[0:-1], dtype=tf.float64)
)
exp_one = tf.exp(var)
exp_two = tf.exp(zero_identity)
summed = tf.reduce_sum(exp_two, axis = [0,1])
final = exp_one / summed

print("input matrix: \n", var, "\n")
print("Identities of the matrix to Zero: \n", zero_identity.eval(session=sess), "\n")
print("Exponential Values numerator: \n", exp_one.eval(session=sess), "\n")
print("Exponential Values to Sum: \n", exp_two.eval(session=sess), "\n")
print("Summed values for zero identity matrix\n ... along axis [0,1]: \n", summed.eval(session=sess), "\n")
print("Output:\n", final.eval(session=sess), "\n")
相关问题