Взгляните на эту строку из UNetModel
класса:
x, x_skip1 = self.encoder_block(32)(inputs)
, где self.encoder_block()
определяется как
self.encoder_block = Enc_block(in_dim)
encoder_block
является экземпляром класса. Делая self.encoder_block(32)
, вы вызываете метод __call__()
класса End_block
, который ожидает получения повторяемых входных данных изображения rank=4
. Вместо этого вы передаете целое число 32
, равное rank=0
, и вы получаете ValueError
, которое говорит именно то, что я только что объяснил: expected ndim=4, found ndim=0
. Вероятно, вы намеревались сделать:
x, x_skip1 = self.encoder_block(inputs)
Вы повторяете ту же ошибку и в последующих строках. Существуют дополнительные ошибки, когда вы определяете один и тот же in_dim
для каждого пользовательского слоя:
self.encoder_block = Enc_block(in_dim)
self.bottleneck = Bottleneck(in_dim)
self.decoder_block = Dec_block(in_dim)
self.output_block = Output_block(in_dim)
Форма ввода для слоя Bottleneck
должна совпадать с формой вывода слоя Enc_Block
и т. Д. Я предлагаю вам сначала понять простой пример, прежде чем пытаться реализовать более сложные. Посмотрите на этот пример. Имеет два пользовательских слоя:
import tensorflow as tf
import numpy as np
from tensorflow.keras import layers
class CustomLayer1(layers.Layer):
def __init__(self, outshape=4):
super(CustomLayer1, self).__init__()
self.outshape = outshape
def build(self, input_shape):
self.kernel = self.add_weight(name='kernel',
shape=(int(input_shape[1]), self.outshape),
trainable=True)
super(CustomLayer1, self).build(input_shape)
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
class CustomLayer2(layers.Layer):
def __init__(self):
super(CustomLayer2, self).__init__()
def call(self, inputs):
return inputs / tf.reshape(tf.reduce_sum(inputs, 1), (-1, 1))
Теперь я буду использовать оба этих слоя в новом CombinedLayers
классе:
class CombinedLayers(layers.Layer):
def __init__(self, units=3):
super(CombinedLayers, self).__init__()
# `units` defines a number of units in the layer. It is the
# output shape of the `CustomLayer`
self.layer1 = CustomLayer1(units)
# The input shape is inferred dynamically in the `build()`
# method of the `CustomLayer1` class
self.layer2 = CustomLayer1(units)
# Some layers such as this one do not need to know the shape
self.layer3 = CustomLayer2()
def call(self, inputs):
x = self.layer1(inputs)
x = self.layer2(x)
x = self.layer3(x)
return x
Обратите внимание, что форма ввода CustomLayer1
выводится динамически в методе build()
. Теперь давайте проверим это с помощью некоторого ввода:
x_train = [np.random.normal(size=(3, )) for _ in range(5)]
x_train_tensor = tf.convert_to_tensor(x_train)
combined = CombinedLayers(3)
result = combined(x_train_tensor)
result.numpy()
# array([[ 0.50822063, -0.0800476 , 0.57182697],
# [ -0.76052217, 0.50127872, 1.25924345],
# [-19.5887986 , 9.23529798, 11.35350062],
# [ -0.33696137, 0.22741248, 1.10954888],
# [ 0.53079047, -0.08941536, 0.55862488]])
Вот как вы должны подойти к этому. Создайте слои один за другим. Каждый раз, когда вы добавляете новый слой, проверяйте все с некоторыми данными, чтобы убедиться, что вы все делаете правильно.