微调microsoft/deberta-v3-base遇ValueError:无变量梯度可用求助
问题分析与解决方案
核心问题
你遇到的ValueError: No gradients provided for any variable本质是模型编译时未指定损失函数,导致反向传播无法计算梯度,同时代码中还有几处模型加载和训练流程的错误放大了这个问题。
关键错误点
- 未指定损失函数:
model.compile(optimizer=optimizer)仅传入优化器,没有定义损失函数,TensorFlow无法计算参数梯度。 - 错误加载基础模型:用
TFAutoModelForSequenceClassification加载模型是带分类头的,你需要的是纯Transformer编码器(取隐藏状态),应该用TFAutoModel。 - 冗余模型定义:初始定义的
model = TFAutoModelForSequenceClassification.from_pretrained(...)完全未被使用,属于无效代码。 - 训练步数未正确定义:
num_steps未赋值,导致create_optimizer的参数错误。 - 标签处理冗余:
class_encode_column已经将标签转为整数编码,无需再用to_categorical,用SparseCategoricalCrossentropy更高效。
修正后的完整代码
import tensorflow as tf from transformers import TFAutoModel, create_optimizer from datasets import Dataset import numpy as np # 数据集处理 train_dataset = Dataset.from_pandas(df_tr[['text', 'label']]).class_encode_column("label") val_dataset = Dataset.from_pandas(df_tes[['text', 'label']]).class_encode_column("label") train_tok_dataset = train_dataset.map(tokenizer_func, batched=True, remove_columns=('text')) val_tok_dataset = val_dataset.map(tokenizer_func, batched=True, remove_columns=('text')) # 加载纯Transformer编码器模型,输出隐藏状态 transformer_model = TFAutoModel.from_pretrained(config.model_name, output_hidden_states=True) # 构建自定义模型结构 input_ids = tf.keras.Input(shape=(config.max_len, ), dtype='int32') attention_mask = tf.keras.Input(shape=(config.max_len, ), dtype='int32') # 获取Transformer输出的隐藏状态(TFAutoModel输出顺序:last_hidden_state, pooler_output, hidden_states) transformer_outputs = transformer_model([input_ids, attention_mask]) hidden_states = transformer_outputs[2] # 拼接最后4层隐藏状态 hidden_states_size = 4 selected_hidden_states = tf.keras.layers.concatenate([hidden_states[i] for i in range(-hidden_states_size, 0)]) # 自定义分类头 output = tf.keras.layers.Dense(128, activation='relu')(selected_hidden_states) output = tf.keras.layers.Flatten()(output) output = tf.keras.layers.Dense(3, activation='softmax')(output) model = tf.keras.models.Model(inputs=[input_ids, attention_mask], outputs=output) # 计算训练步数 batch_size = 8 num_epochs = config.epochs batches_per_epoch = len(train_tok_dataset) // batch_size total_train_steps = batches_per_epoch * num_epochs # 创建优化器 optimizer, schedule = create_optimizer(init_lr=2e-5, num_warmup_steps=0, num_train_steps=total_train_steps) # 编译模型:添加损失函数与评估指标 model.compile( optimizer=optimizer, loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy'] ) # 启动训练 with tf.device('GPU:0'): model.fit( x=[np.array(train_tok_dataset["input_ids"]), np.array(train_tok_dataset["attention_mask"])], y=tf.keras.utils.to_categorical(train_dataset["label"], num_classes=3), validation_data=( [np.array(val_tok_dataset["input_ids"]), np.array(val_tok_dataset["attention_mask"])], tf.keras.utils.to_categorical(val_dataset["label"], num_classes=3) ), epochs=config.epochs, class_weight={0:0.57, 1:0.18, 2:0.39} )
关键修改说明
- 模型加载:用
TFAutoModel替代TFAutoModelForSequenceClassification,确保拿到纯Transformer编码器的隐藏状态,而非带分类头的输出。 - 隐藏状态索引:
TFAutoModel的输出元组中,隐藏状态是第3个元素(索引2),修正原代码的索引错误。 - 损失函数:添加
CategoricalCrossentropy(对应独热标签),让TensorFlow能计算参数梯度。若想简化标签处理,可替换为SparseCategoricalCrossentropy(from_logits=False),此时无需调用to_categorical,直接传入整数标签即可。 - 训练步数:基于训练集大小和批次大小计算正确的总训练步数,保证优化器调度逻辑正常。
- 标签一致性:直接使用数据集内置的标签列,避免
y_train/y_test可能存在的不匹配问题。
内容的提问来源于stack exchange,提问作者Sardar Arslan
相关产品推荐
相关产品推荐

