Назад в TensorFlow <2.0 мы использовали для определения слоев, особенно для более сложных установок, таких как <em>начальные модули , например, группируя их с tf.name_scope
или tf.variable_scope
.
Используя этиоператоры, которым мы смогли удобно структурировать граф вычислений, в результате чего представление графика TensorBoard стало намного проще для интерпретации.
Только один пример для структурированных групп: 
Это очень удобно для отладки сложных архитектур.
К сожалению, tf.keras
, похоже, игнорирует tf.name_scope
и tf.variable_scope
отсутствует в TensorFlow> = 2.0.Таким образом, подобное решение ...
with tf.variable_scope("foo"):
with tf.variable_scope("bar"):
v = tf.get_variable("v", [1])
assert v.name == "foo/bar/v:0"
... больше не доступно.Есть ли замена?
Как мы можем сгруппировать слои и целые модели в TensorFlow> = 2.0?Если мы не группируем слои, tf.keras
создает большой беспорядок для сложных моделей, просто помещая все последовательно в представление графика.
Есть ли замена для tf.variable_scope
?Пока я не смог найти ничего, но интенсивно использовал метод в TensorFlow <2.0. </p>
EDIT : я сейчас реализовал пример для TensorFlow 2.0 .Это простая GAN, реализованная с использованием tf.keras
:
# Generator
G_inputs = tk.Input(shape=(100,), name=f"G_inputs")
x = tk.layers.Dense(7 * 7 * 16)(G_inputs)
x = tf.nn.leaky_relu(x)
x = tk.layers.Flatten()(x)
x = tk.layers.Reshape((7, 7, 16))(x)
x = tk.layers.Conv2DTranspose(32, (3, 3), padding="same")(x)
x = tk.layers.BatchNormalization()(x)
x = tf.nn.leaky_relu(x)
x = tf.image.resize(x, (14, 14))
x = tk.layers.Conv2DTranspose(32, (3, 3), padding="same")(x)
x = tk.layers.BatchNormalization()(x)
x = tf.nn.leaky_relu(x)
x = tf.image.resize(x, (28, 28))
x = tk.layers.Conv2DTranspose(32, (3, 3), padding="same")(x)
x = tk.layers.BatchNormalization()(x)
x = tf.nn.leaky_relu(x)
x = tk.layers.Conv2DTranspose(1, (3, 3), padding="same")(x)
x = tf.nn.sigmoid(x)
G_model = tk.Model(inputs=G_inputs,
outputs=x,
name="G")
G_model.summary()
# Discriminator
D_inputs = tk.Input(shape=(28, 28, 1), name=f"D_inputs")
x = tk.layers.Conv2D(32, (3, 3), padding="same")(D_inputs)
x = tf.nn.leaky_relu(x)
x = tk.layers.MaxPooling2D((2, 2))(x)
x = tk.layers.Conv2D(32, (3, 3), padding="same")(x)
x = tf.nn.leaky_relu(x)
x = tk.layers.MaxPooling2D((2, 2))(x)
x = tk.layers.Conv2D(64, (3, 3), padding="same")(x)
x = tf.nn.leaky_relu(x)
x = tk.layers.Flatten()(x)
x = tk.layers.Dense(128)(x)
x = tf.nn.sigmoid(x)
x = tk.layers.Dense(64)(x)
x = tf.nn.sigmoid(x)
x = tk.layers.Dense(1)(x)
x = tf.nn.sigmoid(x)
D_model = tk.Model(inputs=D_inputs,
outputs=x,
name="D")
D_model.compile(optimizer=tk.optimizers.Adam(learning_rate=1e-5, beta_1=0.5, name="Adam_D"),
loss="binary_crossentropy")
D_model.summary()
GAN = tk.Sequential()
GAN.add(G_model)
GAN.add(D_model)
GAN.compile(optimizer=tk.optimizers.Adam(learning_rate=1e-5, beta_1=0.5, name="Adam_GAN"),
loss="binary_crossentropy")
tb = tk.callbacks.TensorBoard(log_dir="./tb_tf2.0", write_graph=True)
# dummy data
noise = np.random.rand(100, 100).astype(np.float32)
target = np.ones(shape=(100, 1), dtype=np.float32)
GAN.fit(x=noise,
y=target,
callbacks=[tb])
График в TensorBoard этих моделей выглядит как this .Слои - это просто полный беспорядок, а модели «G» и «D» (справа) покрывают некоторый беспорядок.«ГАН» полностью отсутствует.Тренировочную операцию «Адам» нельзя открыть должным образом: слишком много слоев просто нанесено слева направо и стрелки повсюду.Очень трудно проверить правильность вашей GAN таким образом.
Althought a TensorFlow 1.X реализация того же GAN охватывает множество "шаблонного кода" ...
# Generator
Z = tf.placeholder(tf.float32, shape=[None, 100], name="Z")
def model_G(inputs, reuse=False):
with tf.variable_scope("G", reuse=reuse):
x = tf.layers.dense(inputs, 7 * 7 * 16)
x = tf.nn.leaky_relu(x)
x = tf.reshape(x, (-1, 7, 7, 16))
x = tf.layers.conv2d_transpose(x, 32, (3, 3), padding="same")
x = tf.layers.batch_normalization(x)
x = tf.nn.leaky_relu(x)
x = tf.image.resize_images(x, (14, 14))
x = tf.layers.conv2d_transpose(x, 32, (3, 3), padding="same")
x = tf.layers.batch_normalization(x)
x = tf.nn.leaky_relu(x)
x = tf.image.resize_images(x, (28, 28))
x = tf.layers.conv2d_transpose(x, 32, (3, 3), padding="same")
x = tf.layers.batch_normalization(x)
x = tf.nn.leaky_relu(x)
x = tf.layers.conv2d_transpose(x, 1, (3, 3), padding="same")
G_logits = x
G_out = tf.nn.sigmoid(x)
return G_logits, G_out
# Discriminator
D_in = tf.placeholder(tf.float32, shape=[None, 28, 28, 1], name="D_in")
def model_D(inputs, reuse=False):
with tf.variable_scope("D", reuse=reuse):
with tf.variable_scope("conv"):
x = tf.layers.conv2d(inputs, 32, (3, 3), padding="same")
x = tf.nn.leaky_relu(x)
x = tf.layers.max_pooling2d(x, (2, 2), (2, 2))
x = tf.layers.conv2d(x, 32, (3, 3), padding="same")
x = tf.nn.leaky_relu(x)
x = tf.layers.max_pooling2d(x, (2, 2), (2, 2))
x = tf.layers.conv2d(x, 64, (3, 3), padding="same")
x = tf.nn.leaky_relu(x)
with tf.variable_scope("dense"):
x = tf.reshape(x, (-1, 7 * 7 * 64))
x = tf.layers.dense(x, 128)
x = tf.nn.sigmoid(x)
x = tf.layers.dense(x, 64)
x = tf.nn.sigmoid(x)
x = tf.layers.dense(x, 1)
D_logits = x
D_out = tf.nn.sigmoid(x)
return D_logits, D_out
# models
G_logits, G_out = model_G(Z)
D_logits, D_out = model_D(D_in)
GAN_logits, GAN_out = model_D(G_out, reuse=True)
# losses
target = tf.placeholder(tf.float32, shape=[None, 1], name="target")
d_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits, labels=target))
gan_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=GAN_logits, labels=target))
# train ops
train_d = tf.train.AdamOptimizer(learning_rate=1e-5, name="AdamD") \
.minimize(d_loss, var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="D"))
train_gan = tf.train.AdamOptimizer(learning_rate=1e-5, name="AdamGAN") \
.minimize(gan_loss, var_list=tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="G"))
# dummy data
dat_noise = np.random.rand(100, 100).astype(np.float32)
dat_target = np.ones(shape=(100, 1), dtype=np.float32)
sess = tf.Session()
tf_init = tf.global_variables_initializer()
sess.run(tf_init)
# merged = tf.summary.merge_all()
writer = tf.summary.FileWriter("./tb_tf1.0", sess.graph)
ret = sess.run([gan_loss, train_gan], feed_dict={Z: dat_noise, target: dat_target})
... полученный график TensorBoard выглядит значительно чище.Обратите внимание, как чистые области видимости «AdamD» и «AdamGAN» находятся в правом верхнем углу.Вы можете напрямую проверить, что ваши оптимизаторы подключены к нужным областям / градиентам.