TensorFlow2 реализует условную пакетную нормализацию (Conditional Batch Normalization).

искусственный интеллект TensorFlow
TensorFlow2 реализует условную пакетную нормализацию (Conditional Batch Normalization).

"Это седьмой день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."

Условная пакетная нормализация

Пакетная нормализация (BN) — это широко используемый метод обучения сети в глубоком обучении, который может не только ускорить сходимость модели, но и в определенной степени облегчить проблему «градиентной дисперсии» в глубоких сетях. и более стабильны для обучения моделей глубоких сетей, поэтому BN стал стандартным навыком почти для всех сверточных нейронных сетей.Просто просмотрите уравнения следующей партии BN:

BN(x)=γ(xмю(x)о(x))+бетаBN(x) = \gamma (\frac {x-\mu(x)}{\sigma(x)}) + \beta

Среди них среднееµµи стандартное отклонениеоовычисляется в измерении (N, H, W) только с одной парой параметров аффинного преобразования на слой нормализацииγγибетабета, которые усваиваются самой сетью во время обучения.

Однако использование BN в генеративно-состязательных сетях (GAN) в определенной степени приведет к недостатку гомогенизации генерируемых изображений. Например, в наборе данных CIFAR10 есть 10 категорий изображений: 6 — животные (соответственно: птицы, кошки, олени, собаки, лягушки и лошади) и 4 — транспортные средства (соответственно: самолеты, автомобили, корабли и грузовики). ). Ясно, что изображения из разных классов выглядят очень по-разному: у дорожного движения обычно четкие и прямые края, а у животных — изогнутые края и более мягкие текстуры.

существуетпередача стиляКак мы видели в , активированная статистика определяет стиль изображения. Таким образом, смешивание пакетной статистики может создавать изображения, которые немного похожи на животных, а также немного на транспортное средство (например, кошка в форме автомобиля). Это связано с тем, что при пакетной нормализации используется только одно изображение во всем пакете, состоящем из разных классов изображений.γ\gammaибета\beta. если в каждой категории естьγ\gammaибета\beta, проблема решена, в чем и заключается условная пакетная нормализация. В каждой категории есть одинγ\gammaибета\beta, поэтому 10 категорий в CIFAR10 имеют по 10 на каждый слой.γ\gammaи 10бета\beta.

TensorFlow реализует условную пакетную нормализацию

Теперь мы можем создать переменные, необходимые для условной пакетной нормализации, следующим образом:

  1. формы (10, С)бета\betaиγ\gamma, где C — количество активных каналов.
  2. (1, 1, 1, C) среднее значение ходьбы и дисперсия формы. Во время обучения среднее значение и дисперсия вычисляются из мини-пакетов. Во время вывода мы используем скользящее среднее, накопленное во время обучения. Их форма позволяет выполнять арифметические операции в размерах N, H и W.

Чтобы реализовать условную пакетную нормализацию с пользовательским слоем, сначала создайте необходимые переменные:

class ConditionBatchNorm(Layer):
    def build(self, input_shape):
        self.input_size = input_shape
        n, h, w, c = input_shape
        self.gamma = self.add_weight(shape=[self.n_class, c], 
            initializer='zeros', trainable=True, name='gamma')
        self.moving_mean = self.add_weight(shape=[1, 1, 1, c],
            initializer='zeros', trainable=False, name='moving_mean')
        self.moving_var = self.add_weight(shape=[1, 1, 1, c], 
            initializer='zeros', trainable=False, name='moving_var')

При выполнении условной пакетной нормализации получить правильное значение для метокбета\betaиγ\gamma. Это делается с помощью tf.gather(self.beta, labels), который концептуально эквивалентен beta = self.beta[labels] следующим образом:

    def call(self, x, labels, trainable=False):
        beta = tf.gather(self.beta, labels)
        beta = tf.expand_dims(beta, 1)
        gamma = tf.gather(self.gamma, labels)
        gamma = tf.expand_dims(gamma, 1)
		if training:
			mean, var = tf.nn.moments(x, axes=(0,1,2), keepdims=True)
			self.moving_mean.assign(self.decay * self.moving_mean + (1-self.decay)*mean)
			self.moving_var.assign(self.decay * self.moving_var + (1-self.decay)*var)
			output = tf.nn.batch_normalization(x, mean, var, beta, gamma, self.eps)
		else:
			output = tf.nn.batch_normalization(x, self.moving_mean, self.moving_var, beta, gamma, self.eps)
		return output

Примените условную пакетную нормализацию в остаточных блоках

Условная пакетная нормализация используется так же, как и пакетная нормализация, в качестве примера, теперь мы добавляем условную пакетную нормализацию в остаточный блок:

class ResBlock(Layer):
    def build(self, input_shape):
        input_filter = input_shape[-1]
        self.conv_1 = Conv2D(self.filters, 3, padding='same', name='conv2d_1')
        self.conv_2 = Conv2D(self.filters, 3, padding='same', name='conv2d_2')
        self.cbn_1 = ConditionBatchNorm(self.n_class)
        self.cbn_2 = ConditionBatchNorm(self.n_class)
        self.learned_skip = False
        if self.filters != input_filter:
            self.learned_skip = True
            self.conv_3 = Conv2D(self.filters, 1, padding='same', name='conv2d_3')
            self.cbn_3 = ConditionBatchNorm(self.n_class)

Вот код для прямого вычисления остаточных блоков с использованием условной пакетной нормализации:

    def call(self, input_tensor, labels):
        x = self.conv_1(input_tensor)
        x = self.cbn_1(x, labels)
        x = tf.nn.leaky_relu(x, 0.2)
        x = self.conv_2(x)
        x = tf.cbn_2(x, labels)
        x = tf.nn.leaky_relu(x, 0.2)
        if self.learned_skip:
            skip = self.conv_3(input_tensor)
            skip = self.cbn_3(skip, labels)
            skip = tf.nn.leaky_relu(skip, 0.2)
        else:
            skip = input_tensor
        output = skip + x
        return output