Используя функциональный API, можно ли получить график тензорной диаграммы, созданный из кода keras, правильно структурированного?
Можно ли, например, назвать блокинструкций в функциональном подходе как во время создания, так и во время вызова?
Я пытаюсь получить график сети, хорошо структурированный в тензорной доске.
По-видимому, при использовании функционального API, tf.name_scope используется в графе при создании экземпляра модели / слоя, напротив, name kwargsиспользуется при вызове модели / слоя, когда он уже создан.Более того, блоки tf.name_scope не отображаются в части графика, соответствующей вызову (они появляются в части создания экземпляра).
Единственный способ, которым я обнаружил, - одно и то же имя используется как при создании, так и при вызове.правильное структурирование блока слоев на графике означает получение пользовательских слоев из базового класса Layer.Но то, что это действительно больно / излишне, делает код нечитабельным в больших моделях или может быть невозможным для некоторых моделей с несколькими входами / несколькими выходами.
Вот пример с кодом авто-кодера.
Пример с функциональным 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' используется в определении модели кодера, а имя 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 появляется как на кодере, так и на полном авто-кодере.Но код действительно переутомлен, и эта парадигма не может применяться постоянно.