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

DistilBert二分类预测出现负值及指标计算报错求助

问题原因及修复方案

核心原因解析

  1. 输入格式不匹配:Recall、Precision等指标要求输入是离散的类别标签(0/1),而你直接传入了模型输出的未归一化logits(包含负值、连续值),指标函数无法正确解析这些值,触发InvalidArgumentError。
  2. 模型输出与损失函数不兼容:你的模型输出是双logits(每个样本对应两个类的得分,如[[8.45632,-8.409305],...]),但使用了针对单输出二分类的BinaryCrossentropy(from_logits=True),这种不匹配会导致输出体系和标签体系的混淆,进一步加剧指标计算的错误。
  3. AUC指标的输入要求未满足:AUC需要正类的连续得分(概率或logits),但直接传入双logits时,指标函数无法自动识别正类对应的维度,导致解析失败。

修复方案

根据你的模型输出结构,分两种场景处理:

场景1:保留模型双logits输出(最后一层为Dense(2, activation=None))

步骤1:修正损失函数

将BinaryCrossentropy替换为适用于整数标签的多分类损失函数:

import tensorflow as tf

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]
)

步骤2:正确转换输出以计算指标

import numpy as np
from sklearn.metrics import recall_score, precision_score, roc_auc_score

# 获取模型输出的logits
y_pred_logits = model.predict(X_test)
y_true = test_labels  # 你的0/1整数标签

# 计算Recall、Precision:转换为类别预测(取logits最大值对应的索引)
y_pred_labels = np.argmax(y_pred_logits, axis=1)
recall = recall_score(y_true, y_pred_labels)
precision = precision_score(y_true, y_pred_labels)

# 计算AUC:直接使用正类(类别1)的logits作为得分(无需softmax,AUC只关心排序)
auc = roc_auc_score(y_true, y_pred_logits[:, 1])

print(f"Recall: {recall:.4f}, Precision: {precision:.4f}, AUC: {auc:.4f}")

场景2:改为单logits输出(更适配BinaryCrossentropy)

步骤1:修改模型最后一层

将最后一层从Dense(2)改为Dense(1, activation=None),输出单个logits值:

from transformers import TFDistilBertModel
import tensorflow as tf

def build_model(max_len):
    input_ids = tf.keras.layers.Input(shape=(max_len,), dtype=tf.int32)
    attention_mask = tf.keras.layers.Input(shape=(max_len,), dtype=tf.int32)
    
    distilbert = TFDistilBertModel.from_pretrained('distilbert-base-uncased')
    outputs = distilbert(input_ids=input_ids, attention_mask=attention_mask)
    cls_token = outputs.last_hidden_state[:, 0, :]
    
    # 改为单输出适配BinaryCrossentropy
    logits = tf.keras.layers.Dense(1, activation=None)(cls_token)
    
    model = tf.keras.Model(inputs=[input_ids, attention_mask], outputs=logits)
    return model

步骤2:保留BinaryCrossentropy并计算指标

import numpy as np
from sklearn.metrics import recall_score, precision_score, roc_auc_score
import tensorflow as tf

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True)
)

# 获取模型输出的单logits
y_pred_logits = model.predict(X_test).flatten()
y_true = test_labels

# 计算Recall、Precision:转换为0/1标签(logits>0对应类别1)
y_pred_labels = (y_pred_logits > 0).astype(int)
recall = recall_score(y_true, y_pred_labels)
precision = precision_score(y_true, y_pred_labels)

# 计算AUC:使用sigmoid转换为正类概率,或直接用logits
y_pred_prob = tf.sigmoid(y_pred_logits).numpy()
auc = roc_auc_score(y_true, y_pred_prob)
# 或直接用logits:auc = roc_auc_score(y_true, y_pred_logits)

print(f"Recall: {recall:.4f}, Precision: {precision:.4f}, AUC: {auc:.4f}")

额外注意事项

  • 如果使用TensorFlow内置的评估指标(如Recall、Precision),需要在指标内部完成logits到标签/概率的转换,避免直接传入原始logits。
  • 无论哪种输出结构,都要确保训练时的损失函数与输出形状、标签格式完全匹配,否则不仅会影响指标计算,还可能导致模型训练效果不佳。

内容的提问来源于stack exchange,提问作者Injarapu Sri Sharanya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:55:24