keras BatchNormalization axis clarification
Слой keras BatchNormalization
использует axis=-1
в качестве значения по умолчанию и утверждает, что ось объекта обычно нормализована. Почему это так?
Я полагаю, это удивительно, потому что я более знаком с использованием чего-то вроде StandardScaler
, что было бы эквивалентно использованию axis=0
. Это нормализует функции индивидуально.
Есть ли причина, по которой выборки по умолчанию индивидуально нормализуются (т.е. axis=-1
) в кератах, а не по функциям?
Изменение: пример для конкретности
Обычно данные преобразуются таким образом, что каждый объект имеет нулевое среднее значение и единичную дисперсию. Давайте просто рассмотрим часть с "нулевым средним" в этом фиктивном наборе данных, где каждая строка является выборкой:
>>> data = np.array([[ 1, 10, 100, 1000],
[ 2, 20, 200, 2000],
[ 3, 30, 300, 3000]])
>>> data.mean(axis=0)
array([ 2., 20., 200., 2000.])
>>> data.mean(axis=1)
array([ 277.75, 555.5 , 833.25])
Не имеет ли больше смысла вычитать среднее значение axis=0
, а не среднее axis=1
? Используя axis=1
, единицы измерения и шкалы могут быть совершенно разными.
Изменить 2:
Первое уравнение раздела 3 в этой статье, по-видимому, подразумевает, что axis=0
следует использовать для расчета ожиданий и отклонений для каждого элемента в отдельности, предполагая, что у вас есть (m, n) -образный набор данных, где m - это количество образцов, а n - это число признаков.
Изменить 3: еще один пример
Я хотел увидеть размеры средних и отклонений, которые BatchNormalization
рассчитывал на наборе игрушечных данных:
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from keras.optimizers import Adam
from keras.models import Model
from keras.layers import BatchNormalization, Dense, Input
iris = load_iris()
X = iris.data
y = pd.get_dummies(iris.target).values
input_ = Input(shape=(4, ))
norm = BatchNormalization()(input_)
l1 = Dense(4, activation='relu')(norm)
output = Dense(3, activation='sigmoid')(l1)
model = Model(input_, output)
model.compile(Adam(0.01), 'categorical_crossentropy')
model.fit(X, y, epochs=100, batch_size=32)
bn = model.layers[1]
bn.moving_mean # <tf.Variable 'batch_normalization_1/moving_mean:0' shape=(4,) dtype=float32_ref>
Вход X имеет форму (150, 4), а слой BatchNormalization
рассчитан по 4 средним значениям, что означает, что он работал над axis=0
.
Если BatchNormalization
имеет значение по умолчанию axis=-1
, тогда не должно ли быть 150 средних?
Ответы
Ответ 1
Путаница объясняется значением axis
в np.mean
сравнению с BatchNormalization
.
Когда мы берем среднее по оси, мы разрушаем это измерение и сохраняем все остальные измерения. В вашем примере data.mean(axis=0)
сворачивает 0-axis
, которая является вертикальным размером data
.
Когда мы вычисляем BatchNormalization
вдоль оси, мы сохраняем размеры массива, и мы нормализуемся относительно среднего и стандартного отклонения по любой другой оси. Поэтому в вашем 2D
примере BatchNormalization
с axis=1
вычитает среднее значение для axis=0
, как и ожидалось. Вот почему bn.moving_mean
имеет форму (4,)
.
Ответ 2
Я знаю, что этот пост старый, но я все еще отвечаю на него, потому что путаница все еще сохраняется в документации Keras. Я должен был пройти через код, чтобы понять это:
- Переменная оси, которая задокументирована как целое число, может фактически быть списком целых чисел, обозначающих несколько осей. Так, например, если у моего ввода было изображение в форматах NHWC или NCHW, укажите axis = [1,2,3], если бы я хотел выполнить BatchNormalization так, как этого хочет OP (то есть нормализовать только по измерению пакета).
- Список осей (или целое число) должен содержать оси, которые вы не хотите уменьшать при вычислении среднего значения и дисперсии. Другими словами, это дополнение осей, вдоль которых вы хотите нормализоваться - совершенно противоположное тому, что документация говорит, если вы придерживаетесь обычного определения "осей". Так, например, если вы указали значение я (N, H, W, C) или (N, C, H, W), то есть первое измерение было измерением партии, а вы хотели, чтобы только среднее значение и дисперсия вычислялись по измерению партии Вы должны предоставить ось = [1,2,3]. Это заставит Keras вычислять среднее значение M и дисперсию V тензоров формы (1, H, W, C) или (1, C, H, W) соответственно - т.е. размер партии будет маргинализирован/уменьшен вследствие агрегации (то есть среднее значение или дисперсия рассчитывается по первому измерению). В более поздних операциях, таких как (I-M) и (I-M)/V, первое измерение M и V будет передаваться всем N выборкам партии.
- В этом примере слой BatchNorm вызывает tf.nn.moments с axes = (1,)! Это так, потому что определение осей в tf.nn.moments является правильным.
- Точно так же tf.nn.moments вызывает tf.nn.reduce_mean, где опять-таки определение осей является правильным (то есть противоположным tf.keras.layers.BatchNormalization).
- Тем не менее, в документе BatchNormalization предлагается нормализация по пространственной карте HxW в дополнение к измерению партии (N). Следовательно, если следовать этому совету, то ось будет включать только измерение канала (C), потому что это единственное оставшееся измерение, которое вы не хотите уменьшать. Документация Keras, вероятно, намекает на это, хотя и довольно загадочно.
Ответ 3
если ваша мини-партия представляет собой матрицу A mxn, т.е. m образцов и n объектов, ось нормализации должна быть axis = 0, Как вы сказали, мы хотим нормализовать каждый объект индивидуально, по умолчанию axis = -1 в кератах, потому что когда он используется в свёрточном слое, размеры набора данных фигур обычно (сэмплы, ширина, высота, канал), а пакетные сэмплы нормализуются по длинной оси канала (последняя ось).