Да.
Наблюдаемое вами поведение является ошибкой - и вам не нужен BN, чтобы его увидеть;График слева для #V1
, справа для #V2
:
![enter image description here](https://i.stack.imgur.com/xSP2v.png)
#V1
model = Sequential()
model.add(Dense(8, input_shape=(12,)))
#model.add(Activation('linear')) <-- uncomment == #V2
model.add(Dense(12))
model.compile(optimizer='adam', loss='mean_squared_error')
Совершенно бессмысленно, как Activation('linear')
после слоя с activation=None
(== 'linear'
) будет тождество : model.layers[1].output.name == 'activation/activation/Identity:0'
. Это может быть подтверждено в дальнейшем путем выборки и построения графиков выходных данных промежуточного слоя, которые идентичны для 'dense'
и 'activation'
- здесь не будут указаны.
Итак, активация буквально ничего не делает, кроме этого - где-тов цепочке коммитов между 1.14.0 и 2.0.0 это было исправлено, хотя я не знаю где. Результаты с BN с использованием TF 2.0.0 с Keras 2.3.1 ниже:
val_loss = 0.840 # without BN
val_loss = 0.819 # with BN
![enter image description here](https://i.stack.imgur.com/fdynR.png)
Решение : обновление до TensorFlow 2.0.0, Keras 2.3.1.
Совет : использование Anaconda с виртуальной средой. Если у вас еще нет виртуальных envs, запустите:
conda create --name tf2_env --clone base
conda activate tf2_env
conda uninstall tensorflow-gpu
conda uninstall keras
conda install -c anaconda tensorflow-gpu==2.0.0
conda install -c conda-forge keras==2.3.1
Может быть немного сложнее, чем это, но это тема другого вопроса.
ОБНОВЛЕНИЕ : импорт из keras
вместо tf.keras
также решает проблему.
Отказ от ответственности : BN остается «спорным» слоем в Keras, но еще не полностью исправлен - см. Соответствующий Git ;Я планирую исследовать это сам в конечном счете, но для ваших целей этого ответа должно хватить.
Я также рекомендую ознакомиться с основополагающей теорией BN, в частности, касающейся ее работы "поезд против логического вывода";в двух словах, размеры пакетов до 32 - довольно плохая идея, и набор данных должен быть достаточно большим, чтобы BN мог точно аппроксимировать набор тестов gamma
и beta
.
Кодиспользуется:
x_train=np.random.normal(0, 1, (100, 12))
model = Sequential()
model.add(Dense(8, input_shape=(12,)))
#model.add(Activation('linear'))
#model.add(tf.keras.layers.BatchNormalization())
model.add(Dense(12))
model.compile(optimizer='adam', loss='mean_squared_error')
W_sum_all = [] # fit rewritten to allow runtime weight collection
for _ in range(20):
for i in range(9):
x = x_train[i*10:(i+1)*10]
model.train_on_batch(x, x)
W_sum_all.append([])
for layer in model.layers:
if layer.trainable_weights != []:
W_sum_all[-1] += [np.sum(layer.get_weights()[0])]
model.evaluate(x[-10:], x[-10:])
plt.plot(W_sum_all)
plt.title("Sum of weights (#V1)", weight='bold', fontsize=14)
plt.legend(labels=["dense", "dense_1"], fontsize=14)
plt.gcf().set_size_inches(7, 4)
Импорт / предварительное выполнение:
import numpy as np
np.random.seed(1)
import random
random.seed(2)
import tensorflow as tf
if tf.__version__[0] == '2':
tf.random.set_seed(3)
else:
tf.set_random_seed(3)
import matplotlib.pyplot as plt
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Input, Dense, Activation