model.compile添加多指标时出现ValueError形状不兼容问题求助
问题描述
在TensorFlow中,model.compile原本支持传入多个评估指标,示例如下:
model.compile(loss='mean_squared_error', optimizer='sgd', metrics=[metrics.mae, metrics.categorical_accuracy]) # 或者写成 metrics=['mae', 'categorical_accuracy']
但在使用DistilBERT进行二分类序列任务时,仅指定metrics=['accuracy']时代码可正常运行,添加AUC、精确率、召回率等指标或多个指标时,会触发以下错误:
ValueError: Shapes (None, 2) and (None, 1) are incompatible
完整代码如下:
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 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','AUC']) print("Evaluate Base model on test data") results = model.evaluate(test_dataset2) print("test loss, test acc:", results)
解决方法
错误原因
你使用的是SparseCategoricalCrossentropy损失函数,对应标签是稀疏格式(即单值整数,比如0、1),模型输出是(None, 2)维度的logits(二分类任务)。单独用accuracy时TensorFlow会自动适配为SparseCategoricalAccuracy,能处理稀疏标签和多维度logits的匹配;但AUC、精确率等指标默认期望输入是与标签维度一致的格式(比如one-hot编码),因此出现维度不兼容的错误。
提供两种可行的解决方式:
方案一:修改指标,适配稀疏标签
直接使用TensorFlow提供的稀疏标签专用指标类,或给通用指标指定适配参数:
- 对于AUC:设置
from_logits=True(匹配模型输出的logits)和num_labels=2(二分类) - 对于精确率、召回率:使用
SparseCategoricalPrecision和SparseCategoricalRecall,指定num_classes=2 - 替换
model.compile中的metrics参数:
model.compile( optimizer=optimizerr, loss=losss, metrics=[ tf.keras.metrics.SparseCategoricalAccuracy(name="accuracy"), tf.keras.metrics.AUC(from_logits=True, num_labels=2, name="auc"), tf.keras.metrics.SparseCategoricalPrecision(num_classes=2, name="precision"), tf.keras.metrics.SparseCategoricalRecall(num_classes=2, name="recall") ] )
方案二:转换标签为one-hot编码,使用分类交叉熵损失
将稀疏标签转换为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))
- 修改损失函数为
CategoricalCrossentropy:
losss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
- 此时
model.compile的metrics可以直接使用字符串形式:
model.compile(optimizer=optimizerr, loss=losss, metrics=['accuracy','AUC', 'Precision', 'Recall'])
内容的提问来源于stack exchange,提问作者Injarapu Sri Sharanya
相关产品推荐
相关产品推荐

