ResNet50二分类训练报错:期望avg_pool为4维但得到(100,2)数组
ValueError in Your Binary Classification ResNet50 Code Hey there, let's break down why you're hitting this ValueError: Error when checking target: expected avg_pool to have 4 dimensions, but got array with shape (100, 2) error and fix it step by step.
Root Cause
The core issue is a mismatch between your model's output shape and the label shape generated by your data pipeline. Let's walk through the specific problems in your code and how to fix them.
1. Broken Model Construction Logic
Looking at your model code, you're accidentally discarding your custom classification layer:
model = ResNet50(include_top=True, weights='imagenet') x = model.get_layer('avg_pool').output predictions = Dense(1, activation='sigmoid')(x) model = Model(input = model.input, output = predictions) print(model.summary()) model.layers.pop() # ❌ This removes your new Dense layer! model = Model(input=model.input,output=model.layers[-1].output)
After adding a Dense(1, sigmoid) layer for binary classification, you immediately pop it off. This leaves your model outputting the raw avg_pool layer results from ResNet50, which has a shape that doesn't align with your training labels.
Fixed Model Code
Let's rebuild the model properly, using a pre-trained ResNet50 without the ImageNet top layer, then add our own binary classification head:
# Load ResNet50 without the pre-trained top classification layer model = ResNet50(include_top=False, weights=resnet_weights_path, input_shape=(IMAGE_RESIZE, IMAGE_RESIZE, CHANNELS)) # Freeze pre-trained layers (unfreeze later if you want to fine-tune) for layer in model.layers: layer.trainable = False # Add custom classification layers x = model.output x = GlobalAveragePooling2D()(x) # Ensures we get a 2D tensor (batch_size, 2048) predictions = Dense(1, activation='sigmoid')(x) # Binary classification output # Final model model = Model(inputs=model.input, outputs=predictions)
- Using
include_top=Falseavoids loading the 1000-class ImageNet head, so we can build our own - Freezing layers prevents overwriting pre-trained weights during initial training
GlobalAveragePooling2Densures our output is compatible with the dense classification layer
2. Mismatched class_mode in Data Generators
You're using class_mode='categorical' in your flow_from_directory calls, which generates 2D one-hot encoded labels (shape (batch_size, 2)). But your model uses sigmoid activation, which expects 1D binary labels (shape (batch_size,)).
Fixed Data Generator Code
Change class_mode to 'binary' for both generators:
train_generator = train_datagenerator.flow_from_directory( train_data_dir, target_size=(image_size, image_size), batch_size=BATCH_SIZE_TRAINING, class_mode='binary', # ✅ Match sigmoid output shuffle=False, subset='training') validation_generator = train_datagenerator.flow_from_directory( train_data_dir, target_size=(image_size, image_size), batch_size=BATCH_SIZE_VALIDATION, class_mode='binary', # ✅ Same here shuffle=False, subset='validation')
3. Other Minor Cleanup
- You have unused code for building a custom label list
t—sinceflow_from_directoryautomatically generates labels from your folder structure, you can delete this section to avoid confusion - Define
STEPS_PER_EPOCH_TRAININGproperly (uselen(train_generator)instead of an undefined variable) - Ensure your callbacks (
cb_checkpointer,cb_early_stopper) are defined before training
Final Core Working Code Snippet
Here's the streamlined, fixed version of your core training code:
# Model Setup NUM_CLASSES = 2 CHANNELS = 3 IMAGE_RESIZE = 224 resnet_weights_path = '../input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5' NUM_EPOCHS = 10 model = ResNet50(include_top=False, weights=resnet_weights_path, input_shape=(IMAGE_RESIZE, IMAGE_RESIZE, CHANNELS)) for layer in model.layers: layer.trainable = False x = model.output x = GlobalAveragePooling2D()(x) predictions = Dense(1, activation='sigmoid')(x) model = Model(inputs=model.input, outputs=predictions) # Compile Model from keras.optimizers import SGD model.compile(loss='binary_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9), metrics=['binary_accuracy']) # Data Pipeline from keras.applications.resnet50 import preprocess_input from keras.preprocessing.image import ImageDataGenerator train_datagenerator = ImageDataGenerator( preprocessing_function=preprocess_input, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, validation_split=0.2 ) train_generator = train_datagenerator.flow_from_directory( train_data_dir, target_size=(IMAGE_RESIZE, IMAGE_RESIZE), batch_size=100, class_mode='binary', subset='training' ) validation_generator = train_datagenerator.flow_from_directory( train_data_dir, target_size=(IMAGE_RESIZE, IMAGE_RESIZE), batch_size=100, class_mode='binary', subset='validation' ) # Train fit_history = model.fit_generator( train_generator, steps_per_epoch=len(train_generator), epochs=NUM_EPOCHS, validation_data=validation_generator, validation_steps=len(validation_generator), callbacks=[cb_checkpointer, cb_early_stopper] )
This should resolve the shape mismatch error and let your binary classification model train properly.
内容的提问来源于stack exchange,提问作者SpEm1822

