вызвать ошибку типа(«Добавленный слой должен быть» Ошибка типа: добавленный слой должен быть экземпляром слоя класса. Найдено: tf.Тензор

#python #tensorflow #keras

Вопрос:

Я хотел бы знать, что я здесь делаю не так.

импорт:

 import glob
import rasterio as rs
import numpy as np
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow import keras as kr
from tensorflow.keras import layers
from tensorflow.python.keras.layers.convolutional import Conv2D
from tensorflow.python.keras.layers.convolutional import MaxPooling2D
from tensorflow.python.keras.metrics import Accuracy, accuracy
 

Код, который работал:

 model = kr.Sequential([
    kr.layers.Conv2D(32, (2,2), activation='relu', input_shape=(10,10,8)), # output is a 9x9x32 image
    kr.layers.Conv2D(64, (4,4), activation='relu'),                        # output is a 6x6x64 image
    kr.layers.MaxPooling2D(3,3),                                           # output is a 2x2x64 image
    kr.layers.Conv2D(1024, (2,2), activation='relu'),                      # output is a 1x1x1024 layer
    kr.layers.Dropout(0.5),
    kr.layers.Conv2D(3, (1,1), activation=tf.nn.softmax)
]) 

model.compile(optimizer='Adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) 
model.fit(train, train_labels, epochs=50) 
print("results=",model.evaluate(test, test_labels))
 

Код выдает ошибку:

 in_shape = (10,10,8)

conv1 = kr.layers.Conv2D(32, (2,2), activation='relu', input_shape=in_shape)(train)
print('shape of 2nd convolution', np.array(conv1).shape)

conv2 = kr.layers.Conv2D(64, (4,4), activation='relu')(conv1)
print('shape of 2nd convolution', np.array(conv2).shape)

pool1 = kr.layers.MaxPooling2D((3,3))(conv2)
print('shape of 1st pool', np.array(pool1).shape)

conv3 = kr.layers.Conv2D(1024, (2,2), activation='relu')(pool1)
print('shape of 3rd convolution', np.array(conv3).shape)

conv4 = kr.layers.Conv2D(3, (1,1), activation=tf.nn.softmax)(conv3)
print('shape of 4th convolution', np.array(conv4).shape)

# M   O   D   E   L

model = kr.Sequential([conv1, conv2, pool1, conv3, conv4])

model.compile(optimizer='Adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) 
model.fit(train, train_labels, epochs=50) 
print("results=",model.evaluate(test, test_labels))
 

Ошибка:

Ошибка типа: Добавленный слой должен быть экземпляром слоя класса. Найдено: tf.Тензор

Комментарии:

1. Ваш второй код не имеет смысла, вы каким-то образом смешиваете использование функциональных и последовательных API, которые не поддерживаются, вы также не используете функциональный API.

2. Когда вы передаете входные данные в слой , подобный этому: pool1 = kr.layers.MaxPooling2D((3,3))(conv2) , который вы передали (conv2) , результатом будет тензор. Если вам нужны только слои, просто удалите каждый ввод после определения слоев.

Ответ №1:

Это происходит потому, что вы смешиваете последовательную модель Keras с функциональным API Keras.

Вкратце, когда вы делаете это:

 foo = kr.layers.Conv2D(32, (2,2), activation='relu', input_shape=in_shape)(train)
 

поскольку вы используете слой для указанного значения (то есть train ), результат, сохраненный в foo нем, будет тензором, как указано здесь:

Тензор ранга 4 , представляющий активацию(conv2d(входы, ядро) смещение).

Это действительно типичный способ, когда вы пытаетесь создать модель с помощью функционального API.

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

Добавленный слой должен быть экземпляром класса Layer. Найдено: tf.Тензор

Последовательная модель Keras допускает что-то Layer классное. Проблема в том, что когда вы делаете это:

 model = kr.Sequential([conv1, conv2, pool1, conv3, conv4])
 

вы добавляете в последовательную модель ряд тензоров.

Напротив, вы хотите добавить в последовательную модель переменную, хранящую слой, поэтому вам следует сделать это:

 foo = kr.layers.Conv2D(32, (2, 2), activation="relu", input_shape=in_shape)
[...]
model = kr.Sequential([foo, ...])
 

обратите внимание, что train в конце kr.layers.Conv2D слоя его нет, и foo переменная фактически хранит слой,

или это:

 model = kr.Sequential()
model.add(kr.layers.Conv2D(32, (2, 2), activation="relu", input_shape=in_shape))
[...]
 

Другой фрагмент кода, который вы опубликовали, действительно работает, потому что вы действительно напрямую добавляете слой в последовательную модель:

 model = kr.Sequential([
    kr.layers.Conv2D(32, (2,2), activation='relu', input_shape=(10,10,8)), # output is a 9x9x32 image
    kr.layers.Conv2D(64, (4,4), activation='relu'),                        # output is a 6x6x64 image
    kr.layers.MaxPooling2D(3,3),                                           # output is a 2x2x64 image
    kr.layers.Conv2D(1024, (2,2), activation='relu'),                      # output is a 1x1x1024 layer
    kr.layers.Dropout(0.5),
    kr.layers.Conv2D(3, (1,1), activation=tf.nn.softmax)
]) 
 

Комментарии:

1. Спасибо вам за быстрый ответ. Я смог решить эту проблему и также опубликовал решение.

Ответ №2:

Я смог исправить себя с помощью https://www.youtube.com/watch?v=pAhPiF3yiXI, что я хотел сделать, так это реализовать функциональный api в keras, и эквивалентный код для того же самого выглядит следующим образом:

 import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

inp = layers.Input(shape=(10,10,8))

conv1 = layers.Conv2D(32, (2,2), activation='relu')(inp)
conv2 = layers.Conv2D(64, (4,4), activation='relu')(conv1)
pool1 = layers.MaxPooling2D(3,3)(conv2)
conv3 = layers.Conv2D(1024, (2,2), activation='relu')(pool1)
dr_out = layers.Dropout(0.5)(conv3)

out = layers.Conv2D(3, (1,1), activation='softmax')(dr_out)

model = keras.Model(inputs=inp, outputs=out)