我正在使用 Keras 训练神经网络,并尝试使用
RandomCrop
层。我正在使用动态大小的数据集(不同的分辨率),但我发现它目前不是此问题的原因。
当我运行
model.fit()
时,不久之后,我收到上述错误|| |。我能够获得模型的摘要,因此那里不存在一些不匹配。
INVALID_ARGUMENT: required broadcastable shapes
当我删除该层时,我的模型工作正常,但我需要它来减少输入的大小(因此使用
)。
RandomCrop
完整回溯+张量流状态
如何重现
2022-03-23 13:27:28.772937: W tensorflow/core/framework/op_kernel.cc:1733] INVALID_ARGUMENT: required broadcastable shapes
Traceback (most recent call last):
File "c:\Users\samue\Desktop\rcrop\main.py", line 37, in <module>
conv_model.fit(
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\tensorflow\python\eager\execute.py", line 54, in quick_execute
tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
tensorflow.python.framework.errors_impl.InvalidArgumentError: Graph execution error:
Detected at node 'mean_squared_error/SquaredDifference' defined at (most recent call last):
File "C:\Program Files\Python310\lib\threading.py", line 966, in _bootstrap
self._bootstrap_inner()
File "C:\Program Files\Python310\lib\threading.py", line 1009, in _bootstrap_inner
self.run()
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 1000, in run_step
outputs = model.train_step(data)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 860, in train_step
loss = self.compute_loss(x, y, y_pred, sample_weight)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 918, in compute_loss
return self.compiled_loss(
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\compile_utils.py", line 201, in __call__
loss_value = loss_obj(y_t, y_p, sample_weight=sw)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 141, in __call__
losses = call_fn(y_true, y_pred)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 245, in call
return ag_fn(y_true, y_pred, **self._fn_kwargs)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 1329, in mean_squared_error
return backend.mean(tf.math.squared_difference(y_pred, y_true), axis=-1)
Node: 'mean_squared_error/SquaredDifference'
Detected at node 'mean_squared_error/SquaredDifference' defined at (most recent call last):
File "C:\Program Files\Python310\lib\threading.py", line 966, in _bootstrap
self._bootstrap_inner()
File "C:\Program Files\Python310\lib\threading.py", line 1009, in _bootstrap_inner
self.run()
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 1000, in run_step
outputs = model.train_step(data)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 860, in train_step
loss = self.compute_loss(x, y, y_pred, sample_weight)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\training.py", line 918, in compute_loss
return self.compiled_loss(
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\engine\compile_utils.py", line 201, in __call__
loss_value = loss_obj(y_t, y_p, sample_weight=sw)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 141, in __call__
losses = call_fn(y_true, y_pred)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 245, in call
return ag_fn(y_true, y_pred, **self._fn_kwargs)
File "C:\Users\samue\AppData\Roaming\Python\Python310\site-packages\keras\losses.py", line 1329, in mean_squared_error
return backend.mean(tf.math.squared_difference(y_pred, y_true), axis=-1)
Node: 'mean_squared_error/SquaredDifference'
2 root error(s) found.
(0) INVALID_ARGUMENT: required broadcastable shapes
[[{{node mean_squared_error/SquaredDifference}}]]
[[div_no_nan/ReadVariableOp/_84]]
(1) INVALID_ARGUMENT: required broadcastable shapes
[[{{node mean_squared_error/SquaredDifference}}]]
0 successful operations.
0 derived errors ignored. [Op:__inference_train_function_1308]
我创建了一个最小的可重现示例,只有两个分辨率为
的图像都保存为
[10, 10]
和rgb色彩空间。
.png
运行main.py 加载这些图像并尝试开始训练(因错误而失败)。
当我排除
层时,它工作得很好。
RandomCrop
文件夹结构
main.py
/main_folder
--main.py
--/data
--001.png
--002.png
main.py
import cv2, os
import keras
import tensorflow as tf
from keras import layers
strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
input_layer = keras.Input(shape=(None, None, 3))
cropped = layers.RandomCrop(32, 32)(input_layer)
out = layers.Conv2D(3, (3, 3), activation='sigmoid', padding='same')(cropped)
conv_model = keras.Model(input_layer, out)
conv_model.compile(
optimizer='adam',
loss=tf.keras.losses.MeanSquaredError()
)
conv_model.summary()
path = "data"
data = [cv2.imread(os.path.join(path, f)) / 255 for f in os.listdir(os.path.join(path))]
def data_generator():
for i in range(len(data)):
yield data[i], data[i]
dataset = tf.data.Dataset.from_generator(
data_generator,
output_types=(tf.float32, tf.float32),
output_shapes=((None, None, 3), (None, None, 3))
).batch(1)
conv_model.fit(
dataset,
epochs=1,
validation_data=dataset
)
错误“INVALID_ARGUMENT:需要可广播的形状”是由如何使用
tf.data.Dataset.from_generator
定义
dataset
引起的。尽管在
output_shapes
中指定了动态形状,但在迭代
data
列表时,它不会将实际批次形状传递给模型。因此,
RandomCrop
层无法确定输出形状,并且在计算损失时会发生形状不匹配。
以下是修复代码的方法:
-
不要在
output_shapes
中指定批次维度: 从output_shapes
中删除批次维度 (1),因为它由.batch(1)
处理。 -
在生成器中调整图像大小: 由于
RandomCrop
需要一个固定的输入大小,因此在生成器函数中使用cv2.resize
将每个图像调整为所需的大小 (32x32)。
以下是更新后的代码:
import cv2, os
import keras
import tensorflow as tf
from keras import layers
strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
input_layer = keras.Input(shape=(32, 32, 3)) # 定义固定大小的输入
cropped = layers.RandomCrop(32, 32)(input_layer)
out = layers.Conv2D(3, (3, 3), activation='sigmoid', padding='same')(cropped)
conv_model = keras.Model(input_layer, out)
conv_model.compile(
optimizer='adam',
loss=tf.keras.losses.MeanSquaredError()
)
conv_model.summary()
path = "data"
data = [cv2.imread(os.path.join(path, f)) / 255 for f in os.listdir(os.path.join(path))]
def data_generator():
for img in data:
# 调整图像大小以匹配 RandomCrop 输入
resized_img = cv2.resize(img, (32, 32))
yield resized_img, resized_img
dataset = tf.data.Dataset.from_generator(
data_generator,
output_types=(tf.float32, tf.float32),
output_shapes=((32, 32, 3), (32, 32, 3)) # 定义固定大小的输出形状
).batch(1)
conv_model.fit(
dataset,
epochs=1,
validation_data=dataset
)
通过这些更改,
RandomCrop
层将接收到具有固定大小的图像,并且该模型应该可以正确训练而不会出现任何错误。