Keras自定义损失函数报错:ValueError: None values not supported
解决Keras自定义函数中的
ValueError: None values not supported问题 首先,咱们来拆解下你遇到的错误:这个报错的核心原因是当trade_index里没有任何True值时,tf.boolean_mask会返回一个空张量(也就是None),而Keras的损失/指标函数无法处理这种空张量,所以抛出了这个错误。
你的需求是只计算神经网络选中样本的准确率,那咱们得先处理“没有选中样本”这种边界情况,下面给你两种可行的解决方案:
方案一:直接修改自定义函数,处理空张量情况
你可以在函数里先判断是否存在选中的样本,用分支逻辑来避免空张量的出现。修改后的代码如下:
import tensorflow as tf from tensorflow.keras import backend as K def getBalance(x_true, x_pred): # 将预测值四舍五入为二进制值 x_pred = K.round(x_pred) # 筛选出预测第二列不为0的样本索引 trade_index = K.not_equal(x_pred[:, 1], 0) # 检查当前批次是否有选中的样本 has_selected_samples = K.any(trade_index) # 定义有选中样本时的准确率计算逻辑 def calculate_accuracy(): # 提取选中样本的真实值和预测值(第一列) x_true_tradeable = K.boolean_mask(x_true[:, 0], trade_index) x_pred_tradeable = K.boolean_mask(x_pred[:, 0], trade_index) # 计算准确率:正确预测的比例 return K.mean(K.equal(x_true_tradeable, x_pred_tradeable)) # 没有选中样本时返回默认值(这里用0.0,你可以根据需求调整,比如返回1.0) def no_selected_case(): return K.constant(0.0) # 根据是否有选中样本选择执行对应的逻辑 return tf.cond(has_selected_samples, calculate_accuracy, no_selected_case)
关键说明:
- 用
K.any(trade_index)快速判断当前批次是否存在选中的样本 - 用
tf.cond实现分支逻辑,当没有选中样本时返回一个常量值,彻底避免空张量导致的None错误
方案二:用自定义Metric类实现(更适合作为评估指标)
如果你这个函数是用来评估模型准确率的(而非损失函数),更推荐用Keras的Metric类来实现,它能更好地处理跨批次的累计计算,比如某些批次没有选中样本时,不会影响整体的准确率统计。代码示例:
import tensorflow as tf from tensorflow.keras import backend as K class SelectedSampleAccuracy(tf.keras.metrics.Metric): def __init__(self, name='selected_sample_accuracy', **kwargs): super().__init__(name=name, **kwargs) # 初始化累计变量:正确预测的数量、选中样本的总数量 self.correct_predictions = self.add_weight(name='correct', initializer='zeros') self.total_selected = self.add_weight(name='total', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): y_pred = K.round(y_pred) # 筛选选中样本的索引 trade_index = K.not_equal(y_pred[:, 1], 0) # 提取选中样本的真实值和预测值 y_true_selected = K.boolean_mask(y_true[:, 0], trade_index) y_pred_selected = K.boolean_mask(y_pred[:, 0], trade_index) # 计算当前批次的正确数和选中样本数 correct = K.sum(K.cast(K.equal(y_true_selected, y_pred_selected), dtype=K.floatx())) total = K.cast(K.shape(y_true_selected)[0], dtype=K.floatx()) # 只有当有选中样本时才更新累计值 if total > 0: self.correct_predictions.assign_add(correct) self.total_selected.assign_add(total) def result(self): # 避免除以0的情况,当没有选中样本时返回0.0 return K.switch(K.equal(self.total_selected, 0), K.constant(0.0), self.correct_predictions / self.total_selected) def reset_state(self): # 重置累计变量,用于新一轮评估 self.correct_predictions.assign(0.0) self.total_selected.assign(0.0)
使用方式:
在模型编译时直接传入这个自定义指标:
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[SelectedSampleAccuracy()])
这样就能在训练/评估时,自动统计所有选中样本的准确率啦。
内容的提问来源于stack exchange,提问作者Aaron Isaac
相关产品推荐
相关产品推荐

