小能豆

传递给 Dataset.map() 的函数的返回值不受支持

py

我正在尝试使用 tensorflow piplines 对 iris 数据集进行预处理和分类,但在预处理之后出现此错误:传递给 Dataset.map() 的函数不支持的返回值:(,NumericColumn(key=’features’, shape=(4,), default_value=None, dtype=tf.float32, normalizer_fn=None)),我被困在那里,我会很高兴得到任何帮助这是 DNN 的完整代码

import tensorflow_datasets as tfds
from tensorflow.keras.optimizers import Adam


data = tfds.load("iris", split=tfds.Split.TRAIN)


def preprocess(features):

    # should return features and one-hot encoded labels
    #l  = tf.feature_column.categorical_column_with_identity("label", 3, default_value=None)
    l = tf.one_hot(features["label"], 3)
    f = tf.feature_column.numeric_column("features", shape=(4,), dtype=tf.dtypes.float32)
    return l, f

def solution_model():
    train_dataset = data.map(preprocess).batch(10)

    dataset_layer = tf.keras.layers.DenseFeatures(train_dataset)


    # YOUR CODE TO TRAIN A MODEL
    model = tf.keras.Sequential([
        dataset_layer,
        tf.keras.layers.Dense(32, input_shape=(None,4)),
        tf.keras.layers.Dense(64, activation=tf.nn.relu),
        tf.keras.layers.Dense(3, activation=tf.nn.softmax)
    ])
    print(model.summary)
    #model.compile(optimizer="sgd", loss="mean_squared_error")
    model.compile(loss=tf.keras.losses.categorical_crossentropy,
              optimizer=tf.keras.optimizers.SGD(
              learning_rate=0.01, momentum=0.0, nesterov=False, name='SGD'),
              metrics=['accuracy'])
    model.fit(train_dataset, epochs=100)
    return model

if __name__ == '__main__':
    model = solution_model()
    model.save('mymodel.h5')``` 

阅读 14

收藏
2025-01-05

共1个答案

小能豆

在您的代码中,Dataset.map() 函数返回的结果存在问题。错误提示表明 preprocess 函数返回了不被支持的数据类型。在 TensorFlow 数据管道中,Dataset.map() 应返回一个元组 (features, labels),并且这些返回值需要是 TensorFlow 张量或支持的类型。

以下是问题的根源及解决方法:

问题所在

  1. numeric_columncategorical_column 的误用
    tf.feature_column.numeric_column 和类似的 feature columns 通常用于高级 API,例如 tf.estimator,而不是直接用在 tf.data.Dataset.map() 的返回值中。在您的代码中,fl 返回的是 feature columns,而不是张量。

  2. 预处理函数应返回张量
    preprocess 函数需要直接返回特征张量和标签张量,而不是 tf.feature_column


修正代码

修改 preprocess 函数

将特征和标签转换为 TensorFlow 张量并返回:

def preprocess(features):
    # 将特征转换为张量
    feature_tensor = tf.cast(features["features"], tf.float32)
    # 将标签进行 one-hot 编码
    label_tensor = tf.one_hot(features["label"], depth=3)
    return feature_tensor, label_tensor

使用修正的 preprocess 函数

data.map(preprocess) 中使用新的 preprocess 函数,并确保管道能够正确工作。

修改模型构建代码

tf.keras.layers.DenseFeatures 不适用于 tf.data.Dataset。您可以直接定义一个模型,不需要 DenseFeatures

完整修正后的代码如下:

import tensorflow_datasets as tfds
import tensorflow as tf

# 加载数据集
data = tfds.load("iris", split=tfds.Split.TRAIN)

# 预处理函数
def preprocess(features):
    feature_tensor = tf.cast(features["features"], tf.float32)
    label_tensor = tf.one_hot(features["label"], depth=3)
    return feature_tensor, label_tensor

# 构建模型
def solution_model():
    # 预处理数据
    train_dataset = data.map(preprocess).batch(10)

    # 构建模型
    model = tf.keras.Sequential([
        tf.keras.layers.InputLayer(input_shape=(4,)),
        tf.keras.layers.Dense(32, activation='relu'),
        tf.keras.layers.Dense(64, activation='relu'),
        tf.keras.layers.Dense(3, activation='softmax')
    ])

    # 编译模型
    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
        loss='categorical_crossentropy',
        metrics=['accuracy']
    )

    # 训练模型
    model.fit(train_dataset, epochs=100)
    return model

if __name__ == '__main__':
    model = solution_model()
    model.save('mymodel.h5')

代码说明

  1. preprocess 函数
  2. 将特征和标签直接转换为张量。
  3. features["features"] 转换为 float32 张量。
  4. features["label"] 转换为 one-hot 编码的张量。

  5. 模型构建

  6. 移除了 tf.keras.layers.DenseFeatures
  7. 使用标准的 Keras 层,如 DenseInputLayer

  8. 数据管道
    使用 .map(preprocess) 对数据集进行预处理,并使用 .batch(10) 进行批处理。


输出示例

修正后的代码应成功运行,并输出类似以下内容:

Epoch 1/100
15/15 [==============================] - 1s 2ms/step - loss: 1.0942 - accuracy: 0.4000
...
Epoch 100/100
15/15 [==============================] - 0s 1ms/step - loss: 0.0201 - accuracy: 1.0000

希望这能解决您的问题!如果还有其他问题,请随时提问。

2025-01-05