如何解决TensorFlow中网络输入数组尺寸不匹配问题?
咱们先拆解一下你遇到的错误:
ValueError: Cannot feed value of shape (4575, 28, 28, 3) for Tensor 'Placeholder_189:0', which has shape '(?, 28, 28)'
问题很清晰:你喂给网络的是3通道的RGB图像(最后一维的3代表红、绿、蓝三个通道),但你定义的输入占位符x只预留了(?,28,28)的形状——也就是单通道(灰度)图像的尺寸,两者完全不匹配,所以报错了。
下面给你两种可行的解决思路,按需选择:
方案1:用单通道灰度图输入(推荐,因为你代码里已经有转灰度的逻辑)
你代码里已经写了转灰度的代码:
gray_images = skimage.color.rgb2gray(images28_array)
skimage.color.rgb2gray会自动把(4575,28,28,3)的RGB图像转换成(4575,28,28)的单通道灰度图,刚好匹配你占位符x的形状。
你可以在转灰度后加一行代码验证形状是否正确:
gray_images = skimage.color.rgb2gray(images28_array) print(gray_images.shape) # 正常应该输出 (4575, 28, 28)
然后保持你训练循环里的feed_dict={x: gray_images, y: labels}就可以了,这部分你已经写对了。
方案2:修改占位符支持RGB三通道输入
如果你想保留RGB彩色图像作为网络输入,只需要修改占位符x的定义,把通道数加上:
# 原来的定义 # x = tf.placeholder(dtype=tf.float32, shape =[None, 28,28]) # 修改后 x = tf.placeholder(dtype=tf.float32, shape=[None, 28, 28, 3])
后续的tf.layers.flatten会自动把(28,28,3)的图像展开成28*28*3=2352维的向量,不需要改动其他层的代码,非常方便。
额外的重要提醒
除了形状问题,你代码里还有一个容易踩坑的点:
你用了tf.nn.softmax_cross_entropy_with_logits_v2作为损失函数,这个函数要求标签是one-hot编码格式,但你现在传入的是原始的整数标签(比如0到61的类别编号),这会导致损失计算错误,甚至训练完全不收敛。
解决方法是把整数标签转换成one-hot向量:
# 用numpy转换(推荐在喂数据前处理) one_hot_labels = np.eye(62)[labels]
然后修改占位符y的定义,并在训练时传入转换后的标签:
# 修改占位符y的定义 y = tf.placeholder(dtype= tf.float32, shape=[None, 62]) # 训练时喂数据 _, loss_value = sess.run([optimizer, loss], feed_dict={x: gray_images, y: one_hot_labels})
另外,tf.arg_max已经是TensorFlow 1.x里的过时函数,建议换成tf.argmax(小写的max),避免运行时警告:
correct_prediction = tf.argmax(logits, 1)
内容的提问来源于stack exchange,提问作者Raed

