如何循环遍历 (none, 256) 形状的张量数组?

How to loop through (none, 256) shape tensor array?

我正在尝试为 Keras 模型编写自定义损失函数。该损失函数接受预测并将除最高的预测之外的所有预测抑制为零。像这样:

  def loss_function(y_true, y_pred):
    s=tf.shape(y_pred)
    loop=tf.unstack(y_pred)   
    th=[tf.math.argmax(y_pred[i]) for i in loop]
    output=tf.zeros([len(loop),len(anchor_list)])
    y_pred_in=tf.tensor_scatter_nd_update(output,[[i,th[i]] for i in loop],[y_pred[i,th[i]] for i in loop])
    cce = tf.keras.losses.CategoricalCrossentropy()
    loss=cce(y_true,y_pred)
    return loss

我意识到在这样做的同时我还必须注意批量大小。为此,我想根据预测张量的形状创建列表和数组。我发现我们不能迭代张量。所以,我拆开了张量。但是,得到以下错误:

 shape=tf.unstack(y_pred)

    ValueError: Cannot infer argument `num` from the shape (None, None)

我该如何解决这个问题?

您可以使用

获得张量的列表表示
list_from_tensor = list(tenor.numpy())

您可以使用

将列表转换回张量
tensor = tf.convert_to_tensor(list_from_tensor, dtype=tf.float32) #  tensor of floats
tensor = tf.convert_to_tensor(list_from_tensor, dtype=tf.int32) # tensor of integers 

这里 link 一个网站,其中列出了所有可能的类型

This loss function takes in the prediction and suppresses all the predictions except the highest one to zero

我认为这可以很容易地用 tf.where 解决:

import tensorflow as tf

y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]

def loss_function(y_true, y_pred):    
    max_pred_value = tf.reduce_max(y_pred)
    y_pred_new = tf.where(tf.not_equal(y_pred, max_pred_value), tf.zeros_like(y_pred, dtype=tf.float32), max_pred_value)
    cce = tf.keras.losses.CategoricalCrossentropy()
    tf.print('y_pred_new -->', y_pred_new)
    return cce(y_true, y_pred_new)

tf.print('loss -->', loss_function(y_true, y_pred))
y_pred_new --> [[0 0.95 0]
                [0 0 0]]
loss --> nan

但如您所见,将几乎所有值转换为零将导致 nan 损失值。

更新 1: 如果您想要第二个维度的最大值,请尝试这样的事情:

import tensorflow as tf

y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]

def loss_function(y_true, y_pred):
    y_pred_shape = tf.shape(y_pred)   
    max_values = tf.reduce_max(y_pred, axis=1)
    max_values = tf.reshape(tf.repeat(max_values, repeats = y_pred_shape[1]), y_pred_shape)
    y_pred_new = tf.where(tf.not_equal(y_pred, max_values), tf.zeros_like(y_pred, dtype=tf.float32), max_values)
    cce = tf.keras.losses.CategoricalCrossentropy()
    tf.print('y_pred_new -->', y_pred_new)
    return cce(y_true, y_pred_new)

tf.print('loss -->', loss_function(y_true, y_pred))
y_pred_new --> [[0 0.95 0]
 [0 0.8 0]]
loss --> 8.0590477