You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R的tabnet包中将自定义损失设为平衡准确率?

在TabNet中自定义多分类平衡准确率损失函数

直接用yardstick::bal_accuracy_vec报错的原因很明确:它是模型评估指标,不是训练用的可微分损失函数。TabNet训练需要的是能计算梯度、支持反向传播的张量操作函数,而bal_accuracy_vec处理的是普通R向量,无法参与梯度更新,所以必然报错。

平衡准确率的核心是「各类别召回率的平均值」,我们可以把它转换成损失——用1 - 平衡准确率作为损失(训练的目标是最小化损失,平衡准确率越高,损失就越小)。下面是适配TabNet的完整实现方案:

步骤1:编写自定义损失函数

TabNet的自定义损失函数必须接收两个张量参数:y_true(真实标签的one-hot编码张量)和y_pred(模型输出的概率张量),返回一个标量损失值。我们用tensorflow的张量操作实现:

library(tabnet)
library(recipes)
library(tensorflow)
library(modeldata)

# 自定义平衡准确率损失函数
bal_acc_loss <- function(y_true, y_pred) {
  # 从one-hot标签中提取真实类别索引
  y_true_class <- tf$argmax(y_true, axis = 1L)
  # 从预测概率中提取预测类别索引
  y_pred_class <- tf$argmax(y_pred, axis = 1L)
  
  # 获取数据中的所有类别
  classes <- tf$unique(y_true_class)$y
  num_classes <- tf$size(classes)
  
  # 计算每个类别的召回率
  recall_per_class <- tf$map_fn(
    function(cls) {
      # 统计该类别的真实正例数
      true_positives <- tf$reduce_sum(tf$cast(tf$logical_and(tf$equal(y_true_class, cls), tf$equal(y_pred_class, cls)), tf$float32))
      # 统计该类别的总真实样本数
      total_true <- tf$reduce_sum(tf$cast(tf$equal(y_true_class, cls), tf$float32))
      # 避免除以0,添加极小值偏移
      recall <- true_positives / (total_true + tf$keras$backend$epsilon())
      recall
    },
    classes,
    dtype = tf$float32
  )
  
  # 计算平衡准确率,转成损失(1 - 平衡准确率)
  bal_acc <- tf$reduce_mean(recall_per_class)
  loss <- 1 - bal_acc
  loss
}

步骤2:使用自定义损失训练TabNet

注意确保多分类结果变量是因子类型,TabNet会自动处理为one-hot编码。完整训练代码如下:

data("attrition", package = "modeldata")
ids <- sample(nrow(attrition), 256)

# 将多分类结果转成因子
attrition$JobSatisfaction <- as.factor(attrition$JobSatisfaction)

# 构建预处理配方
rec <-
  recipe(Attrition + JobSatisfaction ~ ., data = attrition[ids, ]) %>%
  step_normalize(all_numeric(), -all_outcomes())

# 传入自定义损失训练模型
attrition_fit <-
  tabnet_fit(rec,
             data = attrition[ids, ],
             epochs = 2,
             valid_split = 0.2,
             loss = bal_acc_loss
             )

关键细节说明

  • 必须用张量操作实现:TabNet底层依赖TensorFlow,只有张量运算才能支持梯度计算和反向传播,普通R向量函数无法满足训练需求。
  • 防除以0处理:添加tf$keras$backend$epsilon()避免某类别无样本时出现计算错误。
  • 通用性:这个函数同时支持二分类和多分类任务,二分类场景下平衡准确率等价于召回率。

内容的提问来源于stack exchange,提问作者Comevussor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:12:24