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

使用DistilBert二分类时Recall等指标报形状不兼容错误求解

解决DistilBert二分类中Recall、AUC等指标的形状不兼容问题

问题描述

基于DistilBert开展二分类项目(垃圾短信/IMDB数据集均可复现),使用accuracy和sparse_categorical_accuracy指标时代码正常运行,但使用tf.keras.metrics.Recall()或tf.keras.metrics.AUC()时触发以下错误:

ValueError: Shapes (None, 2) and (None, 1) are incompatible

当前使用SparseCategoricalCrossentropy损失函数与Adam优化器,若更换为BinaryCrossentropy损失函数,会出现新的形状不匹配错误:

ValueError: logits and labels must have the same shape ((None, 2) vs (None, 1))

相关代码如下:

import pandas as pd
import tensorflow as tf
import transformers
from transformers import DistilBertTokenizer
from transformers import TFAutoModelForSequenceClassification
pd.set_option('display.max_colwidth', None)
MODEL_NAME = 'distilbert-base-uncased'
BATCH_SIZE = 8
N_EPOCHS = 3

train = pd.read_csv("train_set.csv", error_bad_lines=False)
test = pd.read_csv("test_set.csv", error_bad_lines=False)

X_train = train.text
X_test = test.text
y_train = train.label
y_test = test.label

tokenizer = DistilBertTokenizer.from_pretrained(MODEL_NAME)

train_encodings = tokenizer(list(X_train.values),
                        truncation=True, 
                        padding=True)
test_encodings = tokenizer(list(X_test.values),
                       truncation=True, 
                       padding=True)

train_dataset = tf.data.Dataset.from_tensor_slices((dict(train_encodings),list(y_train.values)))

test_dataset = tf.data.Dataset.from_tensor_slices((dict(test_encodings),list(y_test.values)))
test_dataset2 = test_dataset.shuffle(buffer_size=1024).take(1000).batch(16)

model = TFAutoModelForSequenceClassification.from_pretrained(MODEL_NAME)

optimizerr = tf.keras.optimizers.Adam(learning_rate=5e-5)

losss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

model.compile(optimizer=optimizerr,
          loss=losss,
          metrics= ['accuracy','sparse_categorical_accuracy',tf.keras.metrics.Recall()])

print("Evaluate Base model on test data")
results = model.evaluate(test_dataset2)
print("test loss, test acc:", results)

核心原因

TFAutoModelForSequenceClassification.from_pretrained(MODEL_NAME)默认输出2维logits((batch_size, 2)),而你的标签是1维稀疏格式((batch_size, 1))。accuracy和sparse_categorical_accuracy专门适配稀疏标签与多类输出的组合,但Recall、AUC等指标默认需要输入与标签形状一致,或需显式配置参数适配该场景。

解决方案

方案1:保留稀疏标签,调整指标参数

继续使用SparseCategoricalCrossentropy损失,为Recall、AUC指定适配参数,让它们兼容2维logits和1维稀疏标签:

修改模型编译部分的metrics参数:

# 定义适配稀疏标签的指标:指定正类ID,或明确类别数
recall = tf.keras.metrics.Recall(class_id=1)  # 计算类别1的召回率(根据你的正类标签调整)
auc = tf.keras.metrics.AUC(num_classes=2, from_logits=True)  # 基于logits计算二分类AUC

model.compile(optimizer=optimizerr,
              loss=losss,
              metrics=['accuracy', 'sparse_categorical_accuracy', recall, auc])

方案2:转换标签为One-Hot格式,匹配模型输出形状

将1维稀疏标签转为2维one-hot编码,使标签形状与模型输出((batch_size,2))一致,可搭配CategoricalCrossentropy损失使用:

步骤1:转换标签格式

# 将标签转为one-hot编码
y_train_onehot = tf.one_hot(y_train.values, depth=2)
y_test_onehot = tf.one_hot(y_test.values, depth=2)

# 更新数据集
train_dataset = tf.data.Dataset.from_tensor_slices((dict(train_encodings), y_train_onehot))
test_dataset = tf.data.Dataset.from_tensor_slices((dict(test_encodings), y_test_onehot))
test_dataset2 = test_dataset.shuffle(buffer_size=1024).take(1000).batch(16)

步骤2:调整损失与指标

losss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)

model.compile(optimizer=optimizerr,
              loss=losss,
              metrics=['accuracy', 
                       tf.keras.metrics.Recall(), 
                       tf.keras.metrics.Precision(), 
                       tf.keras.metrics.AUC(from_logits=True)])

方案3:改用二分类专属模型输出,搭配BinaryCrossentropy

加载模型时指定num_labels=1,让模型输出1维logits((batch_size,1)),此时可使用BinaryCrossentropy损失,标签保持原始1维格式即可:

# 加载模型时指定num_labels=1,输出1维logits
model = TFAutoModelForSequenceClassification.from_pretrained(MODEL_NAME, num_labels=1)

losss = tf.keras.losses.BinaryCrossentropy(from_logits=True)

# 将标签转为float32类型(BinaryCrossentropy要求标签为浮点型)
y_train = tf.cast(y_train.values, tf.float32)
y_test = tf.cast(y_test.values, tf.float32)

# 更新数据集
train_dataset = tf.data.Dataset.from_tensor_slices((dict(train_encodings), y_train))
test_dataset = tf.data.Dataset.from_tensor_slices((dict(test_encodings), y_test))
test_dataset2 = test_dataset.shuffle(buffer_size=1024).take(1000).batch(16)

model.compile(optimizer=optimizerr,
              loss=losss,
              metrics=['accuracy', 
                       tf.keras.metrics.Recall(), 
                       tf.keras.metrics.Precision(), 
                       tf.keras.metrics.AUC(from_logits=True)])

内容的提问来源于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.21 07:03:31