AttributeError: «Последовательный» без атрибута «get_shape» при объединении моделей

Я пытаюсь создать две последовательные модели (каждая из которых обучена разным наборам данных - разным изображениям). Затем я хотел бы взять среднее значение их выходных данных и добавить слой softmax, чтобы получить один результат классификации на основе двух последовательных моделей. Мой код приведен ниже, но я получаю ошибку атрибута, в которой говорится, что объект «Последовательный» не имеет атрибута «get_shape».

Полный код ошибки:

Traceback (most recent call last):
  File "Mergedmodels.pyu", line 135, in <module>
   merged = average ([modelo, modelN1])
  File "G:\Anaconda\lib\site-packages\keras\layers\merge.py", line 481, in average
   return Average(**kwargs)(inputs)
  File "G:\Anaconda\lib\site-packages\keras\engine\topology.py", line 542, in _ call_input_shapes.append(K.int_sshape(x_elem))
  File "G:\Anaconda\lib\site-packages\keras\backend\tensorflow_backend.py", line 411, in int_shape
    shape = x.get_shape()
  AttributeError: 'Sequential' object has no attribute 'get_shape'

Любая идея о том, как это исправить?

 import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import merge
from keras.layers import average
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.preprocessing.image import ImageDataGenerator
from keras.datasets import mnist
import pandas as pd
from numpy import array
from PIL import Image
import matplotlib.pyplot as plt
from keras import backend as K
import glob
import os

K.set_image_dim_ordering('th')


np.random.seed(123) #set for reproducibility

size = 48, 48

#IMPORTING TRAINING IMAGES FOR FIRST MODEL (ORIGINAL)
folder = 'images'

read = lambda imname: np.asarray(Image.open(imname).convert("RGB"))

ims = [read(os.path.join(folder, filename)) for filename in os.listdir(folder)]
X_train = np.array([read(os.path.join(folder, filename)) for filename in os.listdir(folder)], dtype='uint8')
#CHECK print (X_train.shape)

X_train = X_train.reshape(X_train.shape[0],3,48,48)
#X_test = X_test.reshape(X_test.shape[0],1,28,28)
X_train = X_train.astype ('float32')
#X_test = X_test.astype ('float32')
X_train /= 255
#X_test /= 255

#IMPORTING TRAINING IMAGES FOR SECOND MODEL (NORMALIZED)
folder = 'images2'

read = lambda imname: np.asarray(Image.open(imname).convert("RGB"))

ims = [read(os.path.join(folder, filename)) for filename in os.listdir(folder)]
X_training = np.array([read(os.path.join(folder, filename)) for filename in os.listdir(folder)], dtype='uint8')
#CHECK print (X_train.shape)

X_training = X_training.reshape(X_train.shape[0],3,48,48)
#X_test = X_test.reshape(X_test.shape[0],1,28,28)
X_training = X_training.astype ('float32')
#X_test = X_test.astype ('float32')
X_training /= 255
#X_test /= 255


#IMPORTING LABELS FOR 10K TRAINING IMAGES 
saved_column = pd.read_csv('labels4.csv')

y_labels = array(saved_column)

Y_train = np_utils.to_categorical(y_labels,501)

#y_train = np.array ([0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1])
#(X_train, y_train),(X_test, y_test) = mnist.load_data()

#COPYING LABELS FOR SECOND MODEL TRAINING IMAGES
#Y_training = Y_train

#IMPORTING TEST IMAGES
folder2 = 'test'
read = lambda imname: np.asarray(Image.open(imname).convert("RGB"))
ims = [read(os.path.join(folder2, filename)) for filename in os.listdir(folder2)]
X_test = np.array([read(os.path.join(folder2, filename)) for filename in os.listdir(folder2)], dtype='uint8')

X_test = X_test.reshape(X_test.shape[0],3,48,48)
X_test = X_test.astype ('float32')
X_test /= 255

#IMPORTING LABELS FOR TEST IMAGES
another_column = pd.read_csv('labelstest4.csv')
test_labels = array(another_column)
Y_test = np_utils.to_categorical(test_labels,501)
#train_labels = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
#Y_train = np_utils.to_categorical(y_train, 2)
#Y_test = np_utils.to_categorical(y_test,10)


#BUILDING FIRST NN FOR ORIGINAL IMAGES
modelo = Sequential()

modelo.add(Convolution2D(32,3,3, activation='relu', input_shape=(3,48,48), dim_ordering='th'))
modelo.add(Convolution2D(32,3,3, activation = 'relu'))
modelo.add(MaxPooling2D(pool_size=(2,2)))
modelo.add(Dropout(0.25))

modelo.add(Flatten())
modelo.add(Dense(128,activation='relu'))
modelo.add(Dropout(0.5))
modelo.add(Dense(501, activation = 'sigmoid'))

modelo.compile(loss='categorical_crossentropy',
    optimizer = 'adam',
    metrics = ['accuracy'])

modelo.fit(X_train, Y_train, 
    batch_size = 5, nb_epoch= 5, verbose = 1)

score = modelo.evaluate(X_test, Y_test, verbose=0)

#BUILDING SECOND NN FOR NORMALIZED IMAGES
modelN1 = Sequential()

modelN1.add(Convolution2D(32,3,3, activation='relu', input_shape=(3,48,48), dim_ordering='th'))
modelN1.add(Convolution2D(32,3,3, activation = 'relu'))
modelN1.add(MaxPooling2D(pool_size=(2,2)))
modelN1.add(Dropout(0.25))

modelN1.add(Flatten())
modelN1.add(Dense(128,activation='relu'))
modelN1.add(Dropout(0.5))
modelN1.add(Dense(501, activation = 'sigmoid'))

modelN1.compile(loss='categorical_crossentropy',
    optimizer = 'adam',
    metrics = ['accuracy'])

modelN1.fit(X_training, Y_train, 
    batch_size = 5, nb_epoch= 1, verbose = 1)

score = modelN1.evaluate(X_test, Y_test, verbose=0)

#MERGING MODELS
merged = average([modelo, modelN1])

finalmodel = Sequential ()
finalmodel.add(merged)
finalmodel.add(Dense(501, activation = 'softmax'))

finalmodel.compile(loss='categorical_crossentropy',
    optimizer = 'adam',
    metrics = ['accuracy'])

Y_madeuplabels = np.array ([0, 1, 52, 20])  
Y_training = np_utils.to_categorical(Y_madeuplabels, 501)


finalmodel.fit([X_train], Y_training, 
    batch_size = 5, nb_epoch= 1, verbose = 1)

score = finalmodel.evaluate(X_test, Y_test, verbose=0)

print ("the code ran")

comment
в какой строке выдается ошибка атрибуции?   -  person DrBwts    schedule 04.05.2017
comment
В строке 135: объединено = среднее ([modelo, modelN1])   -  person Deya    schedule 04.05.2017


Ответы (1)


Этот способ объединения последовательных моделей не работает в Keras 2.0, так как average работает поверх тензоры, а не слои. Это причина сообщения об ошибке, в котором говорится, что модель Sequential не имеет методов noget_shape(); get_shape() существует только на тензорах.

Вот пример, который повторяет ошибку:

mod1 = Sequential()
mod1.add(Dense(1, input_shape=(10,)))

mod2 = Sequential()
mod2.add(Dense(1, input_shape=(10,)))

avg = average([mod1, mod2]) # throws AttributeError 

Хитрый способ обойти это — использовать функциональный API для объединения выходные данные двух моделей, а затем выполните слой softmax. В качестве примера:

X1 = np.random.rand(10, 10)
X2 = np.random.rand(10, 10)
Y  = np.random.choice(2, 10) 

mod1 = Sequential()
mod1.add(Dense(16, input_shape=(10,)))

mod2 = Sequential()
mod2.add(Dense(16, input_shape=(10,)))

# so use the outputs of the models to do the average over 
# this way we do averaging over tensor __not__ models.
avg = average([mod1.output, mod2.output])
dense = Dense(1, activation="sigmoid")(avg)

# the two inputs are the inputs to the sequential models
# and the output is the dense layer
mod3 = Model(inputs=[mod1.input, mod2.input], outputs=[dense])
mod3.compile(loss='binary_crossentropy',  optimizer='sgd')
mod3.fit([X1, X2], Y)
person parsethis    schedule 04.05.2017
comment
Благодарю вас! Не могли бы вы указать мне хороший учебник по использованию функционального API - я еще не использовал его. - person Deya; 04.05.2017
comment
Рад, что могу помочь, в документации по keras есть хорошие руководства: вот ссылка keras .io/getting-started/functional-api-guide. Я также связался с ним в ответе. Если этот ответ помог вам, не забудьте принять его, чтобы он мог помочь другим - person parsethis; 04.05.2017
comment
Вместе с документацией по keras эта ссылка очень помогла мне понять, как создавать модели keras, соединять модели, обучать только части модели и т. д.: kdnuggets.com/2016/07/ - person Daniel Möller; 04.05.2017
comment
Спасибо тебе за это! - person cyril; 01.08.2017