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

使用SentencePieceTokenizer与HuggingFace数据集时目标输出不匹配

问题:数据集目标形状与模型输出形状不匹配

我尝试基于HuggingFace数据集,使用keras_nlp.tokenizers.SentencePieceTokenizer层构建简单模型,但无法让数据集的目标形状与模型输出形状匹配。

数据加载代码

将HF数据集转换为TensorFlow版本数据集,适配keras.Model.fit():

trainDS = LH_dataset_HF['train'].to_tf_dataset(
        columns=["text"],
        label_cols=["answer"],
        batch_size=batch_size,
        shuffle=False,
        )

数据加载及Tokenizer状态

数据加载和SentencePieceTokenizer工作正常,输出如下:

trainTF shape=(6, 3) answer shape=(6,)
all answers=[b'Yes' b'Yes' b'Yes' b'No' b'No' b'No']
echo1:  b'My roommate and I were feeling unwell in our basement apartment for a long ...

模型结构

Model: "functional_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type)                    ┃ Output Shape           ┃       Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ input_layer (InputLayer)        │ (None)                 │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ sentence_piece_tokenizer        │ (None, 32)             │             0 │
│ (SentencePieceTokenizer)        │                        │               │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ embed (Embedding)               │ (None, 32, 100)        │     1,000,000 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ predictions (Dense)             │ (None, 32, 1)          │           101 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 1,000,101 (3.82 MB)
Trainable params: 1,000,101 (3.82 MB)
Non-trainable params: 0 (0.00 B)

训练时的错误

调用model.fit(trainDS)时触发错误:

ValueError: Arguments target and output must have the same rank (ndim). Received: target.shape=(None,), output.shape=(None, 32, 1)

尝试的标签转换

我用map将字符串标签转为整数:

def binaryLbl(txt,tlbl):
    return(txt,1 if tlbl=='Yes' else 0)

trainDS2 = trainDS.map(binaryLbl)

但trainDS2.element_spec()显示标签无形状:

(TensorSpec(shape=(None,), dtype=tf.string, name=None), TensorSpec(shape=(), dtype=tf.int32, name=None))

疑问

  1. 为什么target.shape=(None,)?
  2. 如何让目标形状匹配模型的单个预测输出节点?

包版本信息

torch=2.1.0.post100
torchtext=0.16.1
tensorflow=2.15.0
tensorflow_text=2.15.0
keras=3.0.5
keras_nlp=0.7.0

解决方案

问题根源分析

  1. 目标形状(None,)的原因:每个样本对应一个"Yes/No"单标签,所以批次标签形状为(batch_size,),即(None,)(None代表批次维度)。而模型最后一层输出(None, 32, 1),是因为Embedding层输出保留了序列长度维度32,直接接Dense层时仅作用于最后一维,导致输出为3维,和标签的2维不匹配。
  2. 模型输出与目标不匹配的核心:任务是单标签二分类,但模型却输出了序列中每个token的预测,不符合任务需求。

具体修复步骤

1. 修改模型结构,压缩序列维度输出单值预测

在Embedding层后添加全局池化层,把序列特征压缩为全局特征,再接Dense层输出单值:

from keras.layers import GlobalAveragePooling1D

model = keras.Sequential([
    keras.Input(shape=(), dtype=tf.string),
    SentencePieceTokenizer(...),  # 你的Tokenizer层
    keras.layers.Embedding(vocab_size, 100),
    GlobalAveragePooling1D(),  # 压缩序列维度,输出形状(None,100)
    keras.layers.Dense(1, activation='sigmoid')  # 二分类输出单值,形状(None,1)
])

修改后模型输出形状为(None,1),可与标签的(None,)兼容(Keras会自动广播匹配)。

2. 修正标签形状,对齐模型输出

将标量标签转为(1,)形状的张量,确保批次后标签形状为(batch_size,1):

def binaryLbl(txt, tlbl):
    label = tf.constant(1, dtype=tf.int32) if tlbl == b'Yes' else tf.constant(0, dtype=tf.int32)
    return txt, tf.expand_dims(label, axis=-1)

trainDS2 = trainDS.map(binaryLbl)

此时trainDS2.element_spec()的标签部分会变为TensorSpec(shape=(1,), dtype=tf.int32, name=None),批次后为(None,1),与模型输出形状完全一致。

3. 验证匹配性

修改后检查:

  • 模型输出形状:(None,1)
  • 数据集标签形状:(None,1)
    此时调用model.fit(trainDS2)即可解决形状不匹配的问题。

内容的提问来源于stack exchange,提问作者rikb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:37:06