如何解决Python训练孟加拉手语识别模型时出现的负维度尺寸错误
孟加拉手语识别模型训练报错排查
问题描述
我正在尝试构建用于孟加拉手语识别的模型,但在拟合模型时触发报错,相关代码如下:
import numpy as np import matplotlib.pyplot as plt import os import cv2 from tqdm import tqdm import tensorflow as tf DATADIR = '/content/drive/MyDrive/Dataset/BSL Alphabet' CATEGORIES =['1','2','3','4','5','6','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','Z1','Z2','Z3',] for category in CATEGORIES: path = os.path.join(DATADIR, category) for img in os.listdir(path): img_array = cv2.imread(os.path.join(path, img), cv2.IMREAD_GRAYSCALE) plt.imshow(img_array, cmap='gray') plt.show() break break batch_size = 32 img_height = 100 img_width = 100 train_ds = tf.keras.preprocessing.image_dataset_from_directory( DATADIR,validation_split=0.2,subset='training',seed=123, image_size=(img_height, img_width), batch_size=batch_size, ) val_ds = tf.keras.preprocessing.image_dataset_from_directory( DATADIR,validation_split=0.2,subset='validation',seed=123, image_size=(img_height, img_width), batch_size=batch_size, ) AUTOTUNE = tf.data.AUTOTUNE train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE) val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE) num_classes = 36 model = tf.keras.Sequential([ tf.keras.layers.experimental.preprocessing.Rescaling(1.0 / 255), tf.keras.layers.Conv2D(16, 3, activation='relu', input_shape=(100,100, 3)), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D(32, 3, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D(64, 3, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D(128, 3, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D(256, 3, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D(512, 3, activation='relu'), tf.keras.layers.BatchNormalization(), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(84, activation='relu'), tf.keras.layers.Dropout(0.5), tf.keras.layers.Dense(num_classes, activation='softmax'), ]) model.compile(optimizer='adam', loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(train_ds, validation_data=val_ds, epochs=3)
运行代码后报错信息如下:
Epoch 1/3 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () 2 train_ds, 3 validation_data=val_ds, ----> 4 epochs=3 5 ) 9 frames /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs) 992 except Exception as e: # pylint:disable=broad-except 993 if hasattr(e, "ag_error_metadata"): --> 994 raise e.ag_error_metadata.to_exception(e) 995 else: 996 raise ValueError: in user code: /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:853 train_function * return step_function(self, iterator) /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:842 step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:1286 run return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs) /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:2849 call_for_each_replica return self._call_for_each_replica(fn, args, kwargs) /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:3632 _call_for_each_replica return fn(*args, **kwargs) /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:835 run_step ** outputs = model.train_step(data) /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:787 train_step y_pred = self(x, training=True) /usr/local/lib/python3.7/dist-packages/keras/engine/base_layer.py:1037 __call__ outputs = call_fn(inputs, *args, **kwargs) /usr/local/lib/python3.7/dist-packages/keras/engine/sequential.py:383 call outputs = layer(inputs, **kwargs) /usr/local/lib/python3.7/dist-packages/keras/engine/base_layer.py:1037 __call__ outputs = call_fn(inputs, *args, **kwargs) /usr/local/lib/python3.7/dist-packages/keras/layers/pooling.py:360 call data_format=conv_utils.convert_data_format(self.data_format, 4)) /usr/local/lib/python3.7/dist-packages/tensorflow/python/util/dispatch.py:206 wrapper return target(*args, **kwargs) /usr/local/lib/python3.7/dist-packages/tensorflow/python/ops/nn_ops.py:4783 max_pool name=name) /usr/local/lib/python3.7/dist-packages/tensorflow/python/ops/gen_nn_ops.py:5344 max_pool data_format=data_format, name=name) /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/op_def_library.py:750 _apply_op_helper attrs=attr_protos, op_def=op_def) /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py:601 _create_op_internal compute_device) /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/ops.py:3569 _create_op_internal op_def=op_def) /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/ops.py:2042 __init__ control_input_ops, op_def) /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/ops.py:1883 _create_c_op raise ValueError(str(e)) ValueError: Negative dimension size caused by subtracting 2 from 1 for '{{node sequential_3/max_pooling2d_22/MaxPool}} = MaxPool[T=DT_FLOAT, data_format="NHWC", explicit_paddings=[], ksize=[1, 2, 2, 1], padding="VALID", strides=[1, 2, 2, 1]](sequential_3/batch_normalization_22/FusedBatchNormV3)' with input shapes: [?,1,1,256].
报错原因
核心问题是堆叠的卷积+池化层数过多,输入的100x100尺寸图像经过多次卷积和2倍下采样后,特征图尺寸被压缩到1x1,此时再执行2x2的最大池化操作,就会出现维度为负的错误。
附带存在参数冲突问题:损失函数设置了from_logits=True,但输出层使用了softmax激活,二者逻辑冲突,会导致模型收敛异常。
解决方案
可任选以下一种方案解决维度报错问题:
- 减少网络层数:删除最后一组
Conv2D(512, 3)、BatchNormalization、MaxPooling2D三层结构,保留前5组卷积池化即可。 - 调整卷积填充方式:给所有Conv2D层增加
padding='same'参数,保证卷积操作不会缩小特征图尺寸,仅池化时进行下采样。 - 增大输入尺寸:将
img_height和img_width从100调整为224,足够支撑6次下采样的尺寸需求。
同时修正损失函数参数冲突,可二选一调整:
- 将损失函数的
from_logits=True改为from_logits=False - 删除输出层Dense的
activation='softmax'参数
内容的提问来源于stack exchange,提问作者Sadia Sultana
相关产品推荐
相关产品推荐

