""" Model Architecture Module Defines the Convolutional Autoencoder architecture """ from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D def build_autoencoder(): """ Build Convolutional Autoencoder model for image denoising Autoencoder: Neural network that learns to compress (encode) and reconstruct (decode) data. Used here to learn clean image representation. Architecture: - Encoder: Compresses noisy image to latent representation - Latent Space: Compressed representation capturing essential features - Decoder: Reconstructs clean image from latent representation Returns: Compiled Keras model """ # Input layer: 28x28 grayscale images input_img = Input(shape=(28, 28, 1)) # ========== ENCODER ========== # Encoder compresses input image to lower-dimensional latent space # This forces model to learn essential features while removing noise # Conv2D: Convolutional layer extracts spatial features using filters # - 32 filters learn different patterns (edges, textures) # - 3x3 kernel size for local feature detection # - ReLU activation introduces non-linearity # - padding='same' maintains spatial dimensions x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img) # MaxPooling2D: Downsamples by taking maximum value in 2x2 window # Reduces spatial dimensions from 28x28 to 14x14 x = MaxPooling2D((2, 2), padding='same')(x) # Second convolutional block with fewer filters (16) x = Conv2D(16, (3, 3), activation='relu', padding='same')(x) # Further downsample from 14x14 to 7x7 encoded = MaxPooling2D((2, 2), padding='same')(x) # ========== LATENT SPACE ========== # At this point: 7x7x16 = 784 values (compressed from 28x28 = 784 pixels) # Latent space captures essential image features without noise # ========== DECODER ========== # Decoder reconstructs clean image from compressed representation # Convolutional layer to process latent features x = Conv2D(16, (3, 3), activation='relu', padding='same')(encoded) # UpSampling2D: Increases spatial dimensions by repeating values # Upsamples from 7x7 to 14x14 x = UpSampling2D((2, 2))(x) # Expand feature maps back to 32 filters x = Conv2D(32, (3, 3), activation='relu', padding='same')(x) # Upsample from 14x14 to 28x28 (original size) x = UpSampling2D((2, 2))(x) # Final layer: 1 filter to produce single-channel grayscale output # Sigmoid activation ensures output values in range [0, 1] decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x) # Create model mapping input to decoded output autoencoder = Model(input_img, decoded) return autoencoder def compile_model(model): """ Compile the autoencoder model Args: model: Keras model to compile Returns: Compiled model """ # Adam optimizer: Adaptive learning rate optimization algorithm # binary_crossentropy: Measures difference between predicted and actual pixel values # accuracy: Tracks how close predictions are to targets model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) return model