TensorFlow训练图像分类模型时Dense层输入维度不兼容报错求助
问题描述
熟悉神经网络但刚接触TensorFlow,尝试用全连接层对25×25像素的RGB图像进行分类。将图像转换为1D NumPy数组作为输入,训练模型时触发报错:dense层的输入0与该层不兼容:期望最小维度为2,实际维度为1。
完整代码
import tensorflow as tf from PIL import Image, ImageFilter, ImageEnhance from os import listdir, mkdir, remove, rmdir from os.path import isfile, join, isdir import numpy as np import matplotlib.pyplot as plt items = ["Coke_Zero", "Fanta2"] sourcePath = "./generated" resolution = 25 validationRatio = 0.9 (x_train_data, y_train_data), (x_val_data, y_val_data) = tf.keras.datasets.fashion_mnist.load_data() print(type(x_train_data)) #Transforms an image's Pixeldata to a 1dimensional list def imageToArray1(image): dataArray = [] for pixel in list(image.getdata()): dataArray.append(pixel[0]/255) dataArray.append(pixel[1]/255) dataArray.append(pixel[2]/255) return dataArray #Other way of transforming an image's Pixeldata to a 1-Dimensional list def imageToArray2(image): redChannel = [] greenChannel = [] blueChannel = [] for pixel in list(image.getdata()): redChannel.append(pixel[0]/255) greenChannel.append(pixel[1]/255) blueChannel.append(pixel[2]/255) return redChannel + greenChannel + blueChannel #format the Pixel and label values def preprocessing_function(x_new, y_new): x_new = tf.cast(x_new, tf.float32) / 255.0 y_new = tf.cast(y_new, tf.int64) return x_new, y_new #generating the traning data by opnening the images and reading their pixel data and putting a label on them def generateTrainingData(): trainingDataX = [] trainingDataY = [] valDataX = [] valDataY = [] for j, item in enumerate(items): path = join(join(sourcePath,str(resolution)),item) images = listdir(path) threshhold = (int) (len(images) * validationRatio) for i, imagePath in enumerate(images): if(i%100==0): print(str(i)+ " of "+ str(len(images))) image = Image.open(join(path,imagePath)) labeled = imageToArray1(image) output = items.index(item) if(i>threshhold): valDataX.append(labeled) valDataY.append(output) else: trainingDataX.append(labeled) trainingDataY.append(output) #2D Numpy Array (Array of the 1D Input Arrays) trainingDataX = np.array(trainingDataX) #2D Numpy Array (Array of the 1D Labels for example: [1, 0]) trainingDataY = tf.one_hot(np.array(trainingDataY),depth=len(items)) #same as above for the validation data valDataX = np.array(valDataX) valDataY = tf.one_hot(np.array(valDataY),depth=len(items)) #create and returning the dataset return (tf.data.Dataset.from_tensor_slices((trainingDataX,trainingDataY)),tf.data.Dataset.from_tensor_slices((valDataX,valDataY))) # Tensorflow Magic below #layer setup model = tf.keras.Sequential([ tf.keras.layers.Dense(units=256, activation='relu', input_dim = resolution * resolution), #tf.keras.layers.Dense(units=192, activation='relu'), #tf.keras.layers.Dense(units=128, activation='relu'), tf.keras.layers.Dense(units=len(items), activation='sigmoid'), ]) model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(), metrics=['accuracy']) dataset_training, dataset_val = generateTrainingData() print(dataset_training) history = model.fit( dataset_training.repeat(), epochs=10, steps_per_epoch=500, validation_data=dataset_val.repeat(), validation_steps=2 )
报错信息
Traceback (most recent call last): File "c:\Users\User\Desktop\projects\Uni\Projekt\trainNeuralNet.py", line 102, in history = model.fit( ^^^^^^^^^^ File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler raise e.with_traceback(filtered_tb) from None File "C:\Users\User\AppData\Local\Temp_autograph_generated_filedxbn7ku9.py", line 15, in tf__train_function retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) ^^^^^ ValueError: in user code: File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\engine\training.py", line 1284, in train_function * return step_function(self, iterator) File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\engine\training.py", line 1268, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\engine\training.py", line 1249, in run_step ** outputs = model.train_step(data) File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\engine\training.py", line 1050, in train_step y_pred = self(x, training=True) File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler raise e.with_traceback(filtered_tb) from None File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\keras\engine\input_spec.py", line 253, in assert_input_compatibility raise ValueError( ValueError: Exception encountered when calling layer 'sequential' (type Sequential). dense层的输入0与该层不兼容:期望最小维度为2,实际维度为1。接收的完整形状:(1875,) 调用sequential层(类型为Sequential)时收到的参数: • inputs=tf.Tensor(shape=(1875,), dtype=float64) • training=True • mask=None
问题原因
- 输入维度不匹配:25×25的RGB图像展开后是
25*25*3=1875个元素的1D数组,但TensorFlow的Dense层要求输入为2D张量(形状为(样本数, 特征数))。当前tf.data.Dataset输出的单个样本是1D张量(1875,),不符合层的输入要求。 - 模型输入维度配置错误:第一个
Dense层设置input_dim = resolution * resolution,仅计算了灰度图的特征数(625),未考虑RGB的3个通道,导致模型期望的输入特征数与实际输入不匹配。
解决方案
1. 修正模型输入特征数
将第一个Dense层的input_dim改为RGB图像的总特征数:
model = tf.keras.Sequential([ tf.keras.layers.Dense(units=256, activation='relu', input_dim = resolution * resolution * 3), tf.keras.layers.Dense(units=len(items), activation='sigmoid'), ])
2. 为数据集添加批次处理(推荐方式)
tf.data.Dataset默认输出单个样本(1D),添加batch操作后,每个训练步会输出形状为(batch_size, 1875)的2D张量,符合Dense层的输入要求:
dataset_training, dataset_val = generateTrainingData() # 设置合适的batch大小,例如32 dataset_training = dataset_training.batch(32) dataset_val = dataset_val.batch(32)
同时建议调整steps_per_epoch为实际训练样本数除以batch大小,避免超出样本总量。
3. 修复重复归一化问题
imageToArray1中已经对像素值做了/255归一化,而preprocessing_function中又重复执行了一次,会导致数据被错误缩放。需要去掉其中一处,例如修改预处理函数:
def preprocessing_function(x_new, y_new): x_new = tf.cast(x_new, tf.float32) y_new = tf.cast(y_new, tf.int64) return x_new, y_new
然后将预处理应用到数据集上:
dataset_training = dataset_training.map(preprocessing_function).batch(32) dataset_val = dataset_val.map(preprocessing_function).batch(32)
内容的提问来源于stack exchange,提问作者Joshua Schicht
相关产品推荐
相关产品推荐

