#python #tensorflow #keras #tensorboard
#python #tensorflow #keras #tensorboard
Вопрос:
Используя функциональный API, есть ли способ получить правильно структурированный график тензорной доски, созданный из кода keras?
Есть ли какой-нибудь способ, например, назвать блок инструкций в функциональном подходе как во время создания экземпляра, так и во время вызова?
Я пытаюсь получить график сети, хорошо структурированный в tensorboard.
По-видимому, при использовании функционального API tf.name_scope используется в графике при создании экземпляра модели / слоя, напротив, имя kwargs используется при вызове модели / слоя, который уже был создан. Более того, блоки tf.name_scope не отображаются в части графика, соответствующей вызову (они появляются в части создания экземпляра).
Единственный способ, которым я обнаружил, что одно и то же имя используется как при создании экземпляра, так и при вызове, а также при правильной структуре блоков слоев на графике, — это получение пользовательских слоев из слоя базового класса. Но то, что это действительно болезненно / излишне, делает код нечитаемым в больших моделях или может быть неосуществимым для некоторых моделей с несколькими входами / несколькими выходами.
Вот пример с кодом автокодирования.
Пример с функциональным API
from keras import Model
from keras import backend as K
from keras.layers import Input, Dense, ReLU
layers=[1024,512,128,64]
graph = K.tf.Graph()
with graph.as_default():
with K.name_scope('ns_encoder'):
x = Input(shape=(layers[0],))
z = x
for hu in layers[1:]:
with K.name_scope('ns_encblock'):
z = Dense(hu)(z)
z = ReLU()(z)
encoder = Model(inputs=x,outputs=z, name='m_encoder')
with K.name_scope('ns_decoder'):
x = Input(shape=(layers[-1],))
z = x
for hu in layers[:-1][::-1]:
with K.name_scope('ns_decblock'):
z = Dense(hu)(z)
z = ReLU()(z)
decoder = Model(inputs=x,outputs=z, name='m_decoder')
with K.name_scope('ns_ae'):
x = Input(shape=(layers[0],))
z = encoder(x)
xh = decoder(z)
ae = Model(inputs=x,outputs=xh, name='m_ae')
writer = K.tf.summary.FileWriter(logdir='logdir', graph=graph)
writer.flush()
График, созданный функциональным API
Тот же слой re_lu_3 корректно отображается внутри блока в ns_encoder, но не в «m_encoder» из «ns_ae». Кроме того, name_scope ‘ns_encoder’ используется в определении модели кодера, в то время как name kwarg ‘m_encoder’ используется в функциональном использовании модели в «ns_ae»
Пример с производным классом
from keras import Model
from keras import backend as K
from keras.layers import Input, Dense, ReLU, Layer
layers=[1024,512,128,64]
class Block(Layer):
def __init__(self, hu, **kwargs):
super().__init__(**kwargs)
self.hu = hu
def build(self,input_shape):
self.dense = Dense(self.hu)
self.relu = ReLU()
super().build(input_shape)
def compute_output_shape(self, input_shape):
return self.relu.compute_output_shape(
self.dense.compute_output_shape(input_shape))
def call(self,x):
return self.relu(self.dense(x))
graph = K.tf.Graph()
with graph.as_default():
with K.name_scope('ns_encoder'):
x = Input(shape=(layers[0],))
z = x
for hu in layers[1:]:
with K.name_scope('ns_encblock'):
z = Block(hu)(z)
encoder = Model(inputs=x,outputs=z, name='m_encoder')
with K.name_scope('ns_decoder'):
x = Input(shape=(layers[-1],))
z = x
for hu in layers[:-1][::-1]:
with K.name_scope('ns_decblock'):
z = Block(hu)(z)
decoder = Model(inputs=x,outputs=z, name='m_decoder')
with K.name_scope('ns_ae'):
x = Input(shape=(layers[0],))
z = encoder(x)
xh = decoder(z)
ae = Model(inputs=x,outputs=xh, name='m_ae')
writer = K.tf.summary.FileWriter(logdir='logdir', graph=graph)
writer.flush()
График, созданный производным класса
На этот раз график правильно структурирован: block_3 отображается как в encoder, так и в full auto-encoder. Но код действительно перегружен, и эта парадигма не может применяться постоянно.