我正在尝试使用 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')```
在您的代码中,Dataset.map() 函数返回的结果存在问题。错误提示表明 preprocess 函数返回了不被支持的数据类型。在 TensorFlow 数据管道中,Dataset.map() 应返回一个元组 (features, labels),并且这些返回值需要是 TensorFlow 张量或支持的类型。
Dataset.map()
preprocess
(features, labels)
以下是问题的根源及解决方法:
numeric_column 和 categorical_column 的误用 tf.feature_column.numeric_column 和类似的 feature columns 通常用于高级 API,例如 tf.estimator,而不是直接用在 tf.data.Dataset.map() 的返回值中。在您的代码中,f 和 l 返回的是 feature columns,而不是张量。
numeric_column
categorical_column
tf.feature_column.numeric_column
tf.estimator
tf.data.Dataset.map()
f
l
预处理函数应返回张量 preprocess 函数需要直接返回特征张量和标签张量,而不是 tf.feature_column。
tf.feature_column
将特征和标签转换为 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
在 data.map(preprocess) 中使用新的 preprocess 函数,并确保管道能够正确工作。
data.map(preprocess)
tf.keras.layers.DenseFeatures 不适用于 tf.data.Dataset。您可以直接定义一个模型,不需要 DenseFeatures。
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')
features["features"]
float32
features["label"] 转换为 one-hot 编码的张量。
features["label"]
模型构建
使用标准的 Keras 层,如 Dense 和 InputLayer。
Dense
InputLayer
数据管道 使用 .map(preprocess) 对数据集进行预处理,并使用 .batch(10) 进行批处理。
.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
希望这能解决您的问题!如果还有其他问题,请随时提问。