получить до последней возможности сети для встраивания, не работает - PullRequest
0 голосов
/ 21 сентября 2018

Мне бы хотелось, чтобы изображение было встроено, чтобы понять, какие изображения сеть видит ближе, а какие, по-видимому, для него сильно отличаются.Во-первых, я хотел использовать обратные вызовы Tensorboard в Keras, но документация для меня недостаточно ясна, и я не смог найти никаких полезных примеров для их воспроизведения.Следовательно, чтобы понять, что я делаю, я предпочел сделать вложение самостоятельно.

Для этого я планировал загрузить модель, уже обученную на моих данных, удалил последние слои (последний выпадающий и плотный слой) и сделал прогноз на проверочных изображениях, чтобы получить функции, связанные с каждым изображением.Затем я просто сделал бы PCA для этих функций и построил изображения в соответствии с их первыми тремя значениями основных компонентов.

Но я думаю, что я что-то неправильно понял, так как, когда я удаляю последние слои, предсказания модели все еще остаютсяразмер числа классов, но для меня он должен быть размером с последним слоем, который в моем случае равен 128.

Ниже приведен код для пояснения (где я просто поместил строки, которые кажутся полезнымичтобы ответить на вопрос, но не стесняйтесь спрашивать более подробную информацию):

#model creation
base_model = applications.inception_v3.InceptionV3(include_top=False, 
                                                   weights='imagenet',
                                                   pooling='avg', 
                                                   input_shape=(img_rows, img_cols, img_channel))
#Adding custom Layers
add_model = Sequential()
add_model.add(Dense(128, activation='relu',input_shape=base_model.output_shape[1:],
                    kernel_regularizer=regularizers.l2(0.001)))
add_model.add(Dropout(0.60))
add_model.add(Dense(2, activation='sigmoid'))   
# creating the final model
model = Model(inputs=base_model.input, outputs=add_model(base_model.output))

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

model = load_model(os.path.join(ROOT_DIR,'model_1','model_cervigrams_all.h5'))
#remove the last two layers
#remove dense_2
model.layers[-1].pop()
#remove dropout_1
model.layers[-1].pop()
model.summary() # last alyer output shape is : (None, 128), so the removal worked
#predict
model.predict(np.reshape(image,[1,image.shape[0],image.shape[1],3])) #output only two values

Где я не прав?Есть ли у вас какие-либо рекомендации?

1 Ответ

0 голосов
/ 22 сентября 2018

Решение при добавлении пользовательских слоев с использованием функционального API Keras:

Если вы используете Функциональный API Keras для добавления пользовательских слоев, следующие решения работают правильно:

# base model creation
base_model = applications.inception_v3.InceptionV3(include_top=False, 
                                                   weights='imagenet',
                                                   pooling='avg', 
                                                   input_shape=(150, 150, 3))
# adding custom Layers
x = Dense(128, activation='relu',input_shape=base_model.output_shape[1:],
                    kernel_regularizer=regularizers.l2(0.001))(base_model.output)
x = Dropout(0.60)(x)
out = Dense(2, activation='sigmoid')(x)

# creating the final model
model = Model(inputs=base_model.input, outputs=out)
model.compile(loss='categorical_crossentropy', optimizer='adam')

Вот как можно извлечь активации пользовательских слоев путем определения новой модели:

# construct a new model to get the activations of custom layers
new_model = Model(model.inputs, [model.layers[-3].output,
                                 model.layers[-2].output,
                                 model.layers[-1].output])

# predict one one random input sample
inp = np.random.rand(1, 150, 150, 3)
output = new_model.predict([inp])

# verify that's what we want
print(output[0].shape)  # shape of first dense layer output, prints: (1, 128) 
print(output[1].shape)  # shape of dropout layer output, prints: (1, 128)
print(output[2].shape)  # shape of second dense layer output, prints: (1, 2)

В качестве альтернативы, вы можете определить функцию Keras:

from keras import backend as K

func = K.function(inputs=model.inputs + [K.learning_phase()],
                  outputs=[model.layers[-3].output,
                           model.layers[-2].output, 
                           model.layers[-1].output])

# usage of the defined function: 
#     the inputs should be a *list* of input arrays
#     plus 1 or 0 for the train/test mode
sample_input = np.random.rand(1, 150, 150, 3)

# train mode
output = func([sample_input, 1])

# test mode
ouput = func([sample_input, 0])

Обратите внимание, что необходимо использовать K.learning_phase(), поскольку модель содержит слои, такие как BatchNormalization и Dropout, которые ведут себя по-разному в тестовом и обучающем режимах.


ПРИМЕЧАНИЕ. Вышеуказанные решения НЕ работают должным образом, если вы используете класс Sequential для добавления пользовательских слоев. Это потому, что при использовании add_model(base_model.output) в построении model все add_model сохраняется как единое целое.слой model.Вы можете проверить это, запустив model.summary() или print(model.layers[-1]).И нет никакого способа получить доступ к выходным данным средних слоев этой последовательной модели.Конечно, вы можете использовать model.layers[-1].layers[1].output (который является выпадающим слоем):

new_model = Model(model.inputs, model.layers[-1].layers[1].output)
new_model.predict(...)

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

ValueError: Graph disconnected: cannot obtain value for tensor Tensor("dense_7_input:0", shape=(?, 2048), dtype=float32) at layer "dense_7_input". The following previous layers were accessed without issue: []

На самом деле, я ожидал, что внутренние слои последовательной модели (т.е. model.layers[-1].layer[1:]) имеют дополнительные входящие и исходящие узлы, но, похоже, это не так.Я не знаю, пропускаю ли я что-то здесь, или это как-то ошибка или невозможность сделать в Керасе.


Примечание: На самом деле, с использованием pop()на layers атрибут объекта модели не работает, так как вам нужно обновить некоторые внутренние атрибуты модели (хотя, только для последовательных моделей встроенный pop()метод был реализован).

...