使用Keras自定义损失函数时出现Tensor对象无numpy属性报错如何解决
自定义DCA校准损失函数运行报错修复方法
问题背景
我阅读了标题为《IMPROVED TRAINABLE CALIBRATION METHOD FOR NEURAL NETWORKS ON MEDICAL IMAGING CLASSIFICATION》的公开论文,该研究提出了一种将校准能力融入模型训练流程的自定义损失函数,通过在分类交叉熵损失中加入校准模块构造得到该自定义函数。
我最初基于Keras实现该损失函数的代码如下:
def dca_loss(y_true, y_pred, beta=1): # y_true: one-hot encoding # y_pred: predicted probability (i.e., softmax(logits)) ## calculating cross-entropy loss ## loss_ce = K.mean(keras.losses.categorical_crossentropy(y_true, y_pred)) ## calculating the DCA term ## # get gt labels gt_labels = tf.argmax(y_true, axis=1).numpy() # get pred labels pred_labels = tf.argmax(y_pred, axis=1).numpy() # get accuracy acc = np.sum(gt_labels==pred_labels)/len(gt_labels) # get pred mean prob temp_prop = 0 for i in range(len(y_true)): temp_prop+=y_pred[i, pred_labels[i]] prob = temp_prop/len(y_true) # calculating dca dca = np.abs(acc-prob) loss = loss_ce + beta*dca return loss
模型编译代码如下:
model.compile(optimizer='sgd', loss=[dca_loss], metrics=['accuracy'])
运行时抛出如下错误:
c:\users\appdata\local\continuum\anaconda3\envs\tf_2.4\lib\site-packages\tensorflow\python\keras\engine\training.py:805 train_function * return step_function(self, iterator) C:\Users\codes\custom_loss_final.py:560 dca_loss * gt_labels = tf.argmax(y_true, axis=1).numpy() AttributeError: 'Tensor' object has no attribute 'numpy'
问题原因
TensorFlow训练时会将损失函数封装进静态计算图执行,此时张量还没有实际数值,无法调用.numpy()方法转换为numpy数组,同时也不支持numpy函数、Python原生循环这类脱离计算图的操作。
修复方案
将所有numpy操作、Python原生逻辑替换为TensorFlow原生张量操作,修复后的损失函数代码如下:
import tensorflow as tf from tensorflow import keras import tensorflow.keras.backend as K def dca_loss(y_true, y_pred, beta=1): # y_true: one-hot encoding # y_pred: predicted probability (i.e., softmax(logits)) # 计算交叉熵损失 loss_ce = K.mean(keras.losses.categorical_crossentropy(y_true, y_pred)) # 计算DCA校准项 # 获取真实标签与预测标签(无需转numpy,直接使用张量) gt_labels = tf.argmax(y_true, axis=1) pred_labels = tf.argmax(y_pred, axis=1) # 计算分类准确率 correct = tf.cast(tf.equal(gt_labels, pred_labels), tf.float32) acc = tf.reduce_mean(correct) # 批量获取所有样本预测类别的置信度,替换原生for循环 pred_one_hot = tf.one_hot(pred_labels, depth=tf.shape(y_pred)[1]) pred_probs = tf.reduce_sum(y_pred * pred_one_hot, axis=1) prob = tf.reduce_mean(pred_probs) # 计算DCA项 dca = tf.abs(acc - prob) return loss_ce + beta * dca
修复后直接使用原有代码编译模型即可正常运行。
内容的提问来源于stack exchange,提问作者shiva
相关产品推荐
相关产品推荐

