Back to Repositories

Testing Neural Network Initializers in Faceswap

This test suite validates the custom initializers implemented in the Faceswap deep learning model. It focuses on testing ICNR and Convolution Aware initialization methods, which are crucial for proper neural network weight initialization and training stability.

Test Coverage Overview

The test suite provides comprehensive coverage of initialization methods used in the Faceswap project.

Key areas tested include:
  • ICNR (Iterative Correction of Neural Network Residuals) initialization
  • Convolution Aware initialization
  • Statistical properties of initialized weights (mean, standard deviation)
  • Shape handling for convolutional layers

Implementation Analysis

The testing approach utilizes pytest’s parametrization feature to test initializers with different tensor shapes.

Implementation highlights:
  • Custom runner function to verify statistical properties
  • Integration with TensorFlow/Keras backend
  • Parametrized tests for different backend configurations
  • Adaptation of Keras testing methodologies

Technical Details

Testing infrastructure includes:
  • pytest as the primary testing framework
  • NumPy for statistical calculations
  • TensorFlow/Keras backend integration
  • Custom initialization methods from lib.model
  • Tolerance limits for statistical assertions

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases for each initializer
  • Parameterized testing for different configurations
  • Clear documentation of test parameters and expectations
  • Proper error tolerance handling
  • Backend-agnostic test implementation

deepfakes/faceswap

tests/lib/model/initializers_test.py

            
#!/usr/bin/env python3
""" Tests for Faceswap Initializers.

Adapted from Keras tests.
"""

import pytest
import numpy as np

from tensorflow.keras import backend as K  # pylint:disable=import-error
from tensorflow.keras import initializers as k_initializers  # noqa:E501  # pylint:disable=import-error

from lib.model import initializers
from lib.utils import get_backend

CONV_SHAPE = (3, 3, 256, 2048)
CONV_ID = get_backend().upper()


def _runner(init, shape, target_mean=None, target_std=None,
            target_max=None, target_min=None):
    variable = K.variable(init(shape))
    output = K.get_value(variable)
    lim = 3e-2
    if target_std is not None:
        assert abs(output.std() - target_std) < lim
    if target_mean is not None:
        assert abs(output.mean() - target_mean) < lim
    if target_max is not None:
        assert abs(output.max() - target_max) < lim
    if target_min is not None:
        assert abs(output.min() - target_min) < lim


@pytest.mark.parametrize('tensor_shape', [CONV_SHAPE], ids=[CONV_ID])
def test_icnr(tensor_shape):
    """ ICNR Initialization Test

    Parameters
    ----------
    tensor_shape: tuple
        The shape of the tensor to feed to the initializer
    """
    fan_in, _ = initializers.compute_fans(tensor_shape)
    std = np.sqrt(2. / fan_in)
    _runner(initializers.ICNR(initializer=k_initializers.he_uniform(),  # pylint:disable=no-member
                              scale=2),
            tensor_shape,
            target_mean=0,
            target_std=std)


@pytest.mark.parametrize('tensor_shape', [CONV_SHAPE], ids=[CONV_ID])
def test_convolution_aware(tensor_shape):
    """ Convolution Aware Initialization Test

    Parameters
    ----------
    tensor_shape: tuple
        The shape of the tensor to feed to the initializer
    """
    fan_in, _ = initializers.compute_fans(tensor_shape)
    std = np.sqrt(2. / fan_in)
    _runner(initializers.ConvolutionAware(seed=123), tensor_shape,
            target_mean=0, target_std=std)