训练前必须确认三件事:文本已转为固定长度tf.Tensor并统一padding;模型输入层声明input_shape;tf.data.Dataset使用.batch()和.prefetch()。

训练前必须确认的三件事
TensorFlow 训练大型文本分类模型不是“调个 fit() 就完事”,它卡在数据、显存和梯度更新三个环节。如果你没提前处理好,大概率会遇到 ResourceExhaustedError: OOM when allocating tensor 或训练中途 NaN loss 爆掉。
- 确认你的文本已转为固定长度的
tf.Tensor(不是 Python list 或 pandas Series),且 batch 内所有样本长度一致(或使用padding+mask) - 确认模型输入层明确声明了
input_shape(如(None,)表示变长序列,但实际训练时仍需统一截断) - 确认
tf.data.Dataset构建时用了.batch()+.prefetch(tf.data.AUTOTUNE),否则 CPU 预处理会拖垮 GPU 利用率
用 tf.keras.layers.TextVectorization 做词表 + 向量化
别手写分词 + fit_on_texts + texts_to_sequences —— 这套 Keras 原生流程在 TF 2.10+ 中已被 TextVectorization 完全替代,且支持直接导出 SavedModel。
- 先用小样本
adapt():只传几千条文本,避免内存爆掉;vocab_size设为 50000 比设 500000 更稳 - 输出模式选
'int'(非'multi_hot'),否则后续接Embedding层会报维度不匹配 - 如果文本含 URL/邮箱等噪声,
standardize参数可传自定义函数,比如lambda x: tf.strings.regex_replace(x, r'https?://\S+', '[URL]')
vectorizer = tf.keras.layers.TextVectorization(
max_tokens=50000,
output_mode='int',
output_sequence_length=256
)
vectorizer.adapt(train_texts[:5000]) # 小样本适配
Embedding 层必须设 trainable=False 初期
大型文本分类(尤其新闻、评论类)的预训练词向量(如 GloVe、fastText)本身已有语义结构,直接微调 Embedding 层极易让 loss 振荡甚至发散。先冻结,等模型其他部分收敛后再解冻。
- 加载预训练权重后,务必检查
embedding_layer.get_weights()[0].shape[0]是否等于vocab_size,否则会静默截断或补零 - 若用 Hugging Face 的
transformers模型(如BertTokenizer),别混用TextVectorization—— 二者 tokenizer 规则不一致,会导致 label 错位 -
Embedding的input_dim必须 ≥ vectorizer 的实际词表大小(可通过vectorizer.vocabulary_size()获取)
Batch size 和 learning rate 要联合调
显存不够时,不能只减 batch_size。TF 的梯度累积没 PyTorch 那么直观,强行用 tf.GradientTape 手写累积反而易出错。更可靠的做法是按比例缩放 learning_rate。
立即学习“Python免费学习笔记(深入)”;
- 原始 batch_size=32、lr=2e-5 → 改成 batch_size=8 时,lr 应设为 5e-6(即 ×0.25)
- 用
tf.keras.optimizers.AdamW替代Adam,它内置 weight decay,对大型 embedding 层更稳定 - 加
tf.keras.callbacks.ReduceLROnPlateau监控val_loss,但patience别设太小(≥3),否则小波动就降 lr,后期难收敛
真正棘手的是长尾类别——哪怕加了 class_weight,F1-score 在少数类上仍可能低于 0.3。这时候得切回数据端:重采样不如用 tf.nn.weighted_cross_entropy_with_logits 自定义 loss,或者换用 focal loss 实现。


















