python - bias - batch normalization keras example
¿Dónde llamo a la función BatchNormalization en Keras? (7)
Si quiero usar la función BatchNormalization en Keras, ¿debo llamarla solo una vez al principio?
Leí esta documentación: http://keras.io/layers/normalization/
No veo dónde se supone que debo llamarlo. A continuación se muestra mi código intentando usarlo:
model = Sequential()
keras.layers.normalization.BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None)
model.add(Dense(64, input_dim=14, init=''uniform''))
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
model.add(Dense(64, init=''uniform''))
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
model.add(Dense(2, init=''uniform''))
model.add(Activation(''softmax''))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss=''binary_crossentropy'', optimizer=sgd)
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)
Pregunto porque si ejecuto el código con la segunda línea, incluida la normalización por lotes, y si ejecuto el código sin la segunda línea, obtengo resultados similares. Entonces, o no estoy llamando a la función en el lugar correcto, o supongo que no hace mucha diferencia.
Casi se ha convertido en una tendencia ahora tener un
Conv2D
seguido de un
ReLu
seguido de una capa
BatchNormalization
.
Así que hice una pequeña función para llamarlos a todos a la vez.
Hace que la definición del modelo se vea mucho más limpia y fácil de leer.
def Conv2DReluBatchNorm(n_filter, w_filter, h_filter, inputs):
return BatchNormalization()(Activation(activation=''relu'')(Convolution2D(n_filter, w_filter, h_filter, border_mode=''same'')(inputs)))
Es otro tipo de capa, por lo que debe agregarla como una capa en un lugar apropiado de su modelo
model.add(keras.layers.normalization.BatchNormalization())
Vea un ejemplo aquí: https://github.com/fchollet/keras/blob/master/examples/kaggle_otto_nn.py
Este hilo es engañoso. Intenté comentar la respuesta de Lucas Ramadan, pero todavía no tengo los privilegios correctos, así que lo pondré aquí.
La normalización por lotes funciona mejor después de la función de activación, y here o here es por qué: se desarrolló para evitar el cambio interno de covariable. El cambio interno de covariable ocurre cuando la distribución de las activaciones de una capa cambia significativamente durante el entrenamiento. La normalización de lote se usa para que la distribución de las entradas (y estas entradas son literalmente el resultado de una función de activación) a una capa específica no cambie con el tiempo debido a las actualizaciones de parámetros de cada lote (o al menos, permite que cambie de manera ventajosa). Utiliza estadísticas de lote para hacer la normalización, y luego usa los parámetros de normalización de lote (gamma y beta en el documento original) "para asegurarse de que la transformación insertada en la red pueda representar la transformación de identidad" (cita del documento original). Pero el punto es que estamos tratando de normalizar las entradas a una capa, por lo que siempre debe ir inmediatamente antes de la siguiente capa en la red. Si eso es o no después de una función de activación depende de la arquitectura en cuestión.
Este hilo tiene un debate considerable sobre si BN debe aplicarse antes de la no linealidad de la capa actual o a las activaciones de la capa anterior.
Aunque no hay una respuesta correcta, los autores de Batch Normalization dicen que debe aplicarse inmediatamente antes de la no linealidad de la capa actual. El motivo (citado del artículo original):
"Agregamos la transformación BN inmediatamente antes de la no linealidad, normalizando x = Wu + b. También podríamos haber normalizado las entradas de capa u, pero dado que es probable que u sea la salida de otra no linealidad, es probable que la forma de su distribución cambie durante entrenar, y restringir su primer y segundo momento no eliminaría el cambio covariable. Por el contrario, es más probable que Wu + b tenga una distribución simétrica, no dispersa, que es "más gaussiana" (Hyv¨arinen & Oja, 2000) "normalizar es probable que produzca activaciones con una distribución estable".
Keras ahora admite la opción
use_bias=False
, por lo que podemos guardar algunos cálculos escribiendo como
model.add(Dense(64, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation(''tanh''))
o
model.add(Convolution2D(64, 3, 3, use_bias=False))
model.add(BatchNormalization(axis=bn_axis))
model.add(Activation(''relu''))
La normalización por lotes se utiliza para normalizar la capa de entrada y las capas ocultas ajustando la media y la escala de las activaciones. Debido a este efecto de normalización con capa adicional en redes neuronales profundas, la red puede usar una mayor tasa de aprendizaje sin desaparecer o explotar gradientes. Además, la normalización por lotes regulariza la red de modo que sea más fácil generalizar y, por lo tanto, no es necesario utilizar el abandono para mitigar el sobreajuste.
Justo después de calcular la función lineal usando say, Dense () o Conv2D () en Keras, usamos BatchNormalization () que calcula la función lineal en una capa y luego agregamos la no linealidad a la capa usando Activación ().
from keras.layers.normalization import BatchNormalization
model = Sequential()
model.add(Dense(64, input_dim=14, init=''uniform''))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
model.add(Dense(64, init=''uniform''))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
model.add(Dense(2, init=''uniform''))
model.add(BatchNormalization(epsilon=1e-06, mode=0, momentum=0.9, weights=None))
model.add(Activation(''softmax''))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss=''binary_crossentropy'', optimizer=sgd)
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True,
validation_split=0.2, verbose = 2)
¿Cómo se aplica la normalización por lotes?
Supongamos que hemos ingresado a [l-1] en una capa l. También tenemos pesos W [l] y unidad de polarización b [l] para la capa l. Deje que a [l] sea el vector de activación calculado (es decir, después de agregar la no linealidad) para la capa l y z [l] sea el vector antes de agregar la no linealidad
- Usando un [l-1] y W [l] podemos calcular z [l] para la capa l
- Por lo general, en la propagación de avance agregaremos la unidad de sesgo a la z [l] en esta etapa como esta z [l] + b [l], pero en la Normalización de lotes este paso de adición de b [l] no es necesario y no Se utiliza el parámetro b [l].
- Calcular z [l] significa y restarlo de cada elemento
- Divida (z [l] - media) usando la desviación estándar. Llámalo Z_temp [l]
-
Ahora defina nuevos parámetros γ y β que cambiarán la escala de la capa oculta de la siguiente manera:
z_norm [l] = γ.Z_temp [l] + β
En este extracto de código, Dense () toma a [l-1], usa W [l] y calcula z [l]. Luego, la BatchNormalization () inmediata realizará los pasos anteriores para dar z_norm [l]. Y luego la Activación inmediata () calculará tanh (z_norm [l]) para dar un [l] es decir
a[l] = tanh(z_norm[l])
Solo para responder esta pregunta con un poco más de detalle, y como dijo Pavel, la Normalización de lotes es solo otra capa, por lo que puede usarla como tal para crear la arquitectura de red deseada.
El caso de uso general es usar BN entre las capas lineales y no lineales en su red, ya que normaliza la entrada a su función de activación, de modo que esté centrado en la sección lineal de la función de activación (como Sigmoid). Hay una pequeña discusión al respecto here
En su caso anterior, esto podría verse así:
# import BatchNormalization
from keras.layers.normalization import BatchNormalization
# instantiate model
model = Sequential()
# we can think of this chunk as the input layer
model.add(Dense(64, input_dim=14, init=''uniform''))
model.add(BatchNormalization())
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
# we can think of this chunk as the hidden layer
model.add(Dense(64, init=''uniform''))
model.add(BatchNormalization())
model.add(Activation(''tanh''))
model.add(Dropout(0.5))
# we can think of this chunk as the output layer
model.add(Dense(2, init=''uniform''))
model.add(BatchNormalization())
model.add(Activation(''softmax''))
# setting up the optimization of our weights
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss=''binary_crossentropy'', optimizer=sgd)
# running the fitting
model.fit(X_train, y_train, nb_epoch=20, batch_size=16, show_accuracy=True, validation_split=0.2, verbose = 2)
Espero que esto aclare las cosas un poco más.