You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零构建的DenseNet-121图像分类模型过拟合,如何正确在网络层中使用Dropout优化?

Fixing Overfitting in Your DenseNet-121 Implementation with Targeted Dropout Use

Hey there! Let's work through fixing the overfitting issue in your DenseNet-121 by refining how Dropout is integrated into your model. First, let's spot the gaps in your current code and then implement a more robust solution.

Key Issues in Your Current Code

  1. Undefined Variables: The filters parameter in dense_block isn't passed in (this is the growth rate k in DenseNet terminology, typically 32 for DenseNet-121).
  2. Rigid Dropout Placement: Your current Dropout is hardcoded in bn_r1_conv without flexibility, and we can optimize its position and type for image data.
  3. Missing Classification Head Dropout: The final fully connected layer is a common spot to add Dropout to curb overfitting, which isn't included in your snippet.

Revised Implementation with Optimized Dropout

Let's rewrite your blocks with these fixes, plus add a complete model build step to tie everything together:

import tensorflow as tf
from tensorflow.keras.layers import (
    BatchNormalization, ReLU, Conv2D, concatenate, AvgPool2D,
    Dense, GlobalAveragePooling2D, SpatialDropout2D
)
from tensorflow.keras import backend as K

def bn_r1_conv(x, filters, kernel=1, strides=1, dropout_rate=0.2, use_spatial_dropout=True):
    x = BatchNormalization()(x)
    x = ReLU()(x)
    # Use SpatialDropout2D for image tasks (drops entire channels, reduces spatial correlation)
    if use_spatial_dropout:
        x = SpatialDropout2D(dropout_rate)(x)
    else:
        x = tf.keras.layers.Dropout(dropout_rate)(x)
    x = Conv2D(filters, kernel, strides=strides, padding='same', kernel_regularizer=tf.keras.regularizers.l2(1e-4))(x)
    return x

def dense_block(x, repetition, growth_rate=32, dropout_rate=0.2):
    # Growth rate (k) is the number of filters added per dense layer
    for _ in range(repetition):
        # Bottleneck layer: 1x1 conv to reduce channel count before 3x3 conv
        y = bn_r1_conv(x, 4 * growth_rate, dropout_rate=dropout_rate)
        # 3x3 conv to produce new feature maps
        y = bn_r1_conv(y, growth_rate, kernel=3, dropout_rate=dropout_rate)
        # Concatenate new features with input
        x = concatenate([y, x])
    return x

def transition_layer(x, dropout_rate=0.2):
    # Compress channel count by half
    num_filters = K.int_shape(x)[-1] // 2
    x = bn_r1_conv(x, num_filters, dropout_rate=dropout_rate)
    # Use 2x2 average pooling (standard in DenseNet) instead of 3x3
    x = AvgPool2D(2, strides=2, padding='same')(x)
    return x

def build_densenet121(input_shape=(224,224,3), num_classes=10, dropout_rate=0.2):
    inputs = tf.keras.Input(shape=input_shape)
    
    # Initial convolution layer
    x = Conv2D(64, 7, strides=2, padding='same', kernel_regularizer=tf.keras.regularizers.l2(1e-4))(inputs)
    x = BatchNormalization()(x)
    x = ReLU()(x)
    x = AvgPool2D(3, strides=2, padding='same')(x)
    
    # Dense blocks and transition layers (DenseNet-121 structure: 6,12,24,16 repetitions)
    x = dense_block(x, 6, dropout_rate=dropout_rate)
    x = transition_layer(x, dropout_rate=dropout_rate)
    
    x = dense_block(x, 12, dropout_rate=dropout_rate)
    x = transition_layer(x, dropout_rate=dropout_rate)
    
    x = dense_block(x, 24, dropout_rate=dropout_rate)
    x = transition_layer(x, dropout_rate=dropout_rate)
    
    x = dense_block(x, 16, dropout_rate=dropout_rate)
    
    # Classification head with Dropout
    x = GlobalAveragePooling2D()(x)
    x = tf.keras.layers.Dropout(0.5)(x)  # Heavier dropout here to reduce overfitting
    outputs = Dense(num_classes, activation='softmax')(x)
    
    model = tf.keras.Model(inputs=inputs, outputs=outputs)
    return model

Key Improvements Explained

  • SpatialDropout2D: Replaced standard Dropout with SpatialDropout2D in convolutional blocks. This drops entire feature channels instead of individual pixels, which is better for image data (avoids exploiting spatial correlation between adjacent pixels).
  • Adjustable Dropout Rates: Made dropout rates a parameter so you can tune them for different blocks (e.g., lower rates in early dense blocks, higher in later ones or the classification head).
  • L2 Regularization: Added kernel regularization to Conv2D layers, which works alongside Dropout to reduce overfitting by penalizing large weights.
  • Standard DenseNet Structure: Fixed the transition layer's pooling to 2x2 (matches official DenseNet specs) and used the correct repetition counts for DenseNet-121 (6,12,24,16).
  • Classification Head Dropout: Added a heavier Dropout (0.5) before the final Dense layer, a common and effective spot to prevent overfitting to training-specific patterns.

Extra Tips to Fight Overfitting

  • Data Augmentation: Add random flips, rotations, zooms, and brightness adjustments to your training data. For example:
    data_augmentation = tf.keras.Sequential([
        tf.keras.layers.RandomFlip("horizontal"),
        tf.keras.layers.RandomRotation(0.1),
        tf.keras.layers.RandomZoom(0.1)
    ])
    
  • Early Stopping: Stop training when validation loss stops improving to avoid overfitting to the training set:
    early_stopping = tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True)
    
  • Reduce Learning Rate: Use a learning rate scheduler to lower the LR as training progresses, helping the model generalize better.

内容的提问来源于stack exchange,提问作者sandep_gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:02:28