Я обучаю последовательную модель tf.keras
, которую хочу преобразовать в формат tfjs
, состоящий из файла model.json
с описанием слоев и файлов двоичных весов, чтобы развернуть ее на веб-сайте для вывода.
Два слоя в моей модели являются пользовательскими слоями, так как в tf.keras.layers
нет подходящих слоев, предопределенных для работы. Это фиктивная версия того, как выглядит мой код модели:
import tensorflow as tf
class SliceChannelsLayer(tf.keras.layers.Layer):
... (model implementation) ...
class L1NormLayer(tf.keras.layers.Layer):
... (model implementation) ...
def sequential_model():
inputs = tf.keras.Input(shape=(30, 36, 36, 6), batch_size=None)
outputs_a = SliceChannelsLayer(start=0, end=3)(inputs)
outputs_b = SliceChannelsLayer(start=3, end=6)(inputs)
...
other Keras layers
...
attention = L1NormLayer(1)(attention)
outputs_motion = tf.keras.layers.Multiply()([outputs_a, attention])
return tf.keras.Model(inputs, outputs_b)
model = sequential_model()
В моем коде JavaScript я реализовал два настраиваемых слоя как , как показано в примере, приведенном в tf js -examples :
class SliceChannelsLayer extends tf.layers.Layer {
... (model implementation) ...
}
class L1NormLayer extends tf.layers.Layer {
... (model implementation) ...
}
При запуске tfjs.converters.save_keras_model(model, "tfjs_export")
оба настраиваемых слоя получают одинаковое имя в model.json
: TensorFlowOpLayer
.
Однако , Мне нужно сопоставить имена моих реализаций слоя JavaScript с этими именами, что невозможно, когда несколько слоев получают одно и то же имя. Мой код работает, когда я вручную редактирую файл model.json
, чтобы заменить TensorFlowOpLayer
на SliceChannelsLayer
или L1NormLayer
.
Мой вопрос : Как мне избежать необходимости вручную изменять имена слоев в model.json
после экспорта?
Изменить: поведение можно воспроизвести с помощью следующего кода:
import tensorflow as tf
import tensorflowjs as tfjs
class L1NormLayer(tf.keras.layers.Layer):
"""L1NormLayer"""
def __init__(self, axis, **kwargs):
super(L1NormLayer, self).__init__()
self.axis = axis
def __call__(self, inputs):
inputs, _ = tf.linalg.normalize(inputs, ord=1, axis=self.axis)
return inputs
class SliceChannelsLayer(tf.keras.layers.Layer):
"""SliceChannelsLayer"""
def __init__(self, start, end, **kwargs):
super(SliceChannelsLayer, self).__init__()
self.start = start
self.end = end
def __call__(self, inputs):
inputs = inputs[:, :, :, :, self.start:self.end]
return inputs
inputs = tf.keras.Input(shape=(29, 36, 36, 6), batch_size=1)
outputs_a = SliceChannelsLayer(start=0, end=3, name="SliceChannels")(inputs)
outputs_b = SliceChannelsLayer(start=3, end=6, name="SliceChannels")(inputs)
attention = tf.keras.layers.TimeDistributed(
tf.keras.layers.Conv2D(
filters=1, kernel_size=(1, 1), activation="sigmoid"))(
outputs_b)
attention = L1NormLayer(1, name="L1Norm")(attention)
outputs_a = tf.keras.layers.Multiply()([outputs_b, attention])
outputs_a = tf.keras.layers.Dense(units=1, activation="linear")(outputs_a)
model = tf.keras.Model(inputs=inputs, outputs=outputs_a)
model.compile(loss='mean_squared_error',
optimizer=tf.keras.optimizers.RMSprop())
model.summary()
tfjs.converters.save_keras_model(model, "tfjs")