InvalidArgumentError: обязательные транслируемые формы в loc(неизвестно)

#python #tensorflow #neural-network #conv-neural-network #tf.keras

Вопрос:

Фон

Я совершенно новичок в Python и в машинном обучении. Я просто попытался настроить UNet из кода, который нашел в Интернете, и хотел адаптировать его к делу, над которым я работаю, бит за битом. При попытке получить доступ к .fit данным обучения, я получил следующую ошибку:

 InvalidArgumentError:  required broadcastable shapes at loc(unknown)
     [[node Equal (defined at <ipython-input-68-f1422c6f17bb>:1) ]] [Op:__inference_train_function_3847]
 

Я получаю много результатов, когда ищу его, но в основном это разные ошибки.

Что это значит? И, что еще более важно, как я могу это исправить?

Код, вызвавший ошибку

Контекст этой ошибки выглядит следующим образом: Я хочу сегментировать изображения и помечать различные классы. Я настроил каталоги «trn», «tst» и «val» для данных обучения, тестирования и проверки. dir_dat() Функция применяется os.path.join() для получения полного пути к соответствующему набору данных. В каждой из 3 папок есть подкаталоги для каждого класса, помеченные целыми числами. В каждой папке есть несколько .tif изображений для соответствующего класса.

Я определил следующие генераторы данных изображений (обучающие данные разрежены, следовательно, увеличение):

 classes = np.array([ 0,  2,  4,  6,  8, 11, 16, 21, 29, 30, 38, 39, 51])
bs = 15 # batch size

augGen = ks.preprocessing.image.ImageDataGenerator(rotation_range = 365,
                                                   width_shift_range = 0.05,
                                                   height_shift_range = 0.05,
                                                   horizontal_flip = True,
                                                   vertical_flip = True,
                                                   fill_mode = "nearest") 
    .flow_from_directory(directory = dir_dat("trn"),
                         classes = [str(x) for x in classes.tolist()],
                         class_mode = "categorical",
                         batch_size = bs, seed = 42)
    
tst_batches = ks.preprocessing.image.ImageDataGenerator() 
    .flow_from_directory(directory = dir_dat("tst"),
                         classes = [str(x) for x in classes.tolist()],
                         class_mode = "categorical",
                         batch_size = bs, shuffle = False)

val_batches = ks.preprocessing.image.ImageDataGenerator() 
    .flow_from_directory(directory = dir_dat("val"),
                         classes = [str(x) for x in classes.tolist()],
                         class_mode = "categorical",
                         batch_size = bs)
 

Затем я настроил UNet на основе этого примера. Здесь я изменил несколько параметров, чтобы адаптировать UNet к ситуации (несколько классов), а именно активацию на последнем уровне и функцию потерь:

 layer_in = ks.layers.Input(shape = (imgr, imgc, imgdim))
# convert pixel integer values to float
inVals = ks.layers.Lambda(lambda x: x / 255)(layer_in)

# Contraction path
c1 = ks.layers.Conv2D(16, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(inVals)
c1 = ks.layers.Dropout(0.1)(c1)
c1 = ks.layers.Conv2D(16, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c1)
p1 = ks.layers.MaxPooling2D((2, 2))(c1)

c2 = ks.layers.Conv2D(32, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(p1)
c2 = ks.layers.Dropout(0.1)(c2)
c2 = ks.layers.Conv2D(32, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c2)
p2 = ks.layers.MaxPooling2D((2, 2))(c2)
 
c3 = ks.layers.Conv2D(64, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(p2)
c3 = ks.layers.Dropout(0.2)(c3)
c3 = ks.layers.Conv2D(64, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c3)
p3 = ks.layers.MaxPooling2D((2, 2))(c3)
 
c4 = ks.layers.Conv2D(128, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(p3)
c4 = ks.layers.Dropout(0.2)(c4)
c4 = ks.layers.Conv2D(128, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c4)
p4 = ks.layers.MaxPooling2D(pool_size = (2, 2))(c4)
 
c5 = ks.layers.Conv2D(256, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(p4)
c5 = ks.layers.Dropout(0.3)(c5)
c5 = ks.layers.Conv2D(256, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c5)

# Expansive path 
u6 = ks.layers.Conv2DTranspose(128, (2, 2), strides = (2, 2), padding = "same")(c5)
u6 = ks.layers.concatenate([u6, c4])
c6 = ks.layers.Conv2D(128, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(u6)
c6 = ks.layers.Dropout(0.2)(c6)
c6 = ks.layers.Conv2D(128, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c6)
 
u7 = ks.layers.Conv2DTranspose(64, (2, 2), strides = (2, 2), padding = "same")(c6)
u7 = ks.layers.concatenate([u7, c3])
c7 = ks.layers.Conv2D(64, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(u7)
c7 = ks.layers.Dropout(0.2)(c7)
c7 = ks.layers.Conv2D(64, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c7)
 
u8 = ks.layers.Conv2DTranspose(32, (2, 2), strides = (2, 2), padding = "same")(c7)
u8 = ks.layers.concatenate([u8, c2])
c8 = ks.layers.Conv2D(32, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(u8)
c8 = ks.layers.Dropout(0.1)(c8)
c8 = ks.layers.Conv2D(32, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c8)
 
u9 = ks.layers.Conv2DTranspose(16, (2, 2), strides = (2, 2), padding = "same")(c8)
u9 = ks.layers.concatenate([u9, c1], axis = 3)
c9 = ks.layers.Conv2D(16, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(u9)
c9 = ks.layers.Dropout(0.1)(c9)
c9 = ks.layers.Conv2D(16, (3, 3), activation = "relu",
                            kernel_initializer = "he_normal", padding = "same")(c9)
 
out = ks.layers.Conv2D(1, (1, 1), activation = "softmax")(c9)
 
model = ks.Model(inputs = layer_in, outputs = out)
model.compile(optimizer = "adam", loss = "sparse_categorical_crossentropy", metrics = ["accuracy"])
model.summary()
 

Наконец, я определил обратные вызовы и запустил обучение, которое привело к ошибке:

 cllbs = [
    ks.callbacks.EarlyStopping(patience = 4),
    ks.callbacks.ModelCheckpoint(dir_out("Checkpoint.h5"), save_best_only = True),
    ks.callbacks.TensorBoard(log_dir = './logs'),# log events for TensorBoard
    ]

model.fit(augGen, epochs = 5, validation_data = val_batches, callbacks = cllbs)
 

Полный вывод на консоль

Это полный вывод при запуске последней строки (на случай, если это поможет решить проблему):

 trained = model.fit(augGen, epochs = 5, validation_data = val_batches, callbacks = cllbs)
Epoch 1/5
Traceback (most recent call last):

  File "<ipython-input-68-f1422c6f17bb>", line 1, in <module>
    trained = model.fit(augGen, epochs = 5, validation_data = val_batches, callbacks = cllbs)

  File "c:usersmanuelpythonlibsite-packagestensorflowpythonkerasenginetraining.py", line 1183, in fit
    tmp_logs = self.train_function(iterator)

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerdef_function.py", line 889, in __call__
    result = self._call(*args, **kwds)

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerdef_function.py", line 950, in _call
    return self._stateless_fn(*args, **kwds)

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerfunction.py", line 3023, in __call__
    return graph_function._call_flat(

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerfunction.py", line 1960, in _call_flat
    return self._build_call_outputs(self._inference_function.call(

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerfunction.py", line 591, in call
    outputs = execute.execute(

  File "c:usersmanuelpythonlibsite-packagestensorflowpythoneagerexecute.py", line 59, in quick_execute
    tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,

InvalidArgumentError:  required broadcastable shapes at loc(unknown)
     [[node Equal (defined at <ipython-input-68-f1422c6f17bb>:1) ]] [Op:__inference_train_function_3847]

Function call stack:
train_function
 

Ответ №1:

Я столкнулся с этой проблемой, когда количество меток классов не совпадало с формой выходной формы выходного слоя.

Например, если существует 10 меток классов и мы определили Выходной слой как:

 output = tf.keras.layers.Conv2D(5, (1, 1), activation = "softmax")(c9)
 

Так как количество меток классов ( 10 ) не равно выходной форме ( 5 ).
Тогда мы получим эту ошибку.

Убедитесь, что количество меток классов совпадает с выходной формой выходного слоя.

Ответ №2:

Я нашел здесь несколько проблем. Модель предназначалась для использования для семантической сегментации с несколькими классами (именно поэтому я изменил активацию выходного слоя на "softmax" и установил "sparse_categorical_crossentropy" потерю). Следовательно, в ImageDataGenerators class_mode должно быть установлено значение None . classes не подлежат предоставлению. Вместо этого мне нужно было вставить изображения, классифицированные вручную как y . Я думаю, новички совершают много ошибок новичков.

Ответ №3:

У меня возникла та же проблема, потому что я использовал количество n_classes в модели (для выходного слоя), отличное от фактического количества классов в массиве меток/масок. Я вижу, что у вас здесь аналогичная проблема: у вас 13 классов, но вашему выходному слою присвоен только 1. Лучший способ-избежать жесткого кодирования количества классов и передать в модель только переменную (например, n_classes), а затем объявить эту переменную перед вызовом модели. Например, n_classes = y_Train.shape[-1] или n_classes = len(np.уникальный(y_Train))

Ответ №4:

Попробуйте проверить, имеют ли ks.layers.concatenate layers входные данные одинаковую размерность. Например ks.layers.concatenate([u7, c3]) , здесь проверьте, что тензоры u7 и c3 имеют одинаковую форму для объединения, за исключением оси, вводимой в функцию ks.layers.concatenate . Axis = -1 по умолчанию это последнее измерение. Чтобы проиллюстрировать , если вы даете ks.layers.concatenate([u7,c3],axis=0) , то, за исключением первой оси как u7, так и c3, размеры всех остальных осей должны точно совпадать, пример, u7.shape = [3,4,5], c3.shape = [6,4,5].