Keras Lambda层的运行两次,即使仅调用一次



为什么以下代码运行两次克层?

import numpy as np
from keras.applications import vgg19
from keras import backend as K
from keras.layers import Input, Lambda
import tensorflow as tf
from keras.models import Model
def gram_layer(y):
    print('Using Gram Layer')
    # assert K.ndim(y) == 4
    print(y.shape, 'y.shape')
    # a = y.get_shape()[1].value
    # b = y.get_shape()[2].value
    # c = y.get_shape()[3].value
    # print(a, b, c)
    # x = K.squeeze(y, axis=0)
    # features = K.batch_flatten(K.permute_dimensions(x, (2, 0, 1)))
    # features_nomean = features - K.mean(features, axis=0, keepdims=True)
    # gram = K.dot(features_nomean, K.transpose(features_nomean)) / (a * b * c)
    print('exiting Gram')
    # return x
    return y

In = K.placeholder((1, 256, 256, 3))
model = vgg19.VGG19(input_tensor = In, weights='imagenet', include_top=False)
for layer in model.layers:
    if layer.name == 'block1_conv1':
        print(layer.name)
        print(layer.output.shape)
        outputs = (Lambda(gram_layer))(layer.output)

调试信息:

block1_conv1
(1, 256, 256, 64)
Using Gram Layer
(1, 256, 256, 64) y.shape
exiting Gram
Using Gram Layer
(?, ?, ?, 64) y.shape
exiting Gram

调试信息包含两个"使用革兰氏层",这意味着该层运行两次,并且第二次失败,但奇怪的是仅被称为一次。

任何想法怎么了?

ps:我意识到问题在于for循环部分,如果最后一行

outputs = (Lambda(gram_layer))(layer.output)

被替换为

outputs = (Lambda(gram_layer))(In)

调试信息如

block1_conv1
(1, 256, 256, 64)
Using Gram Layer
(1, 256, 256, 3) y.shape
exiting Gram
Using Gram Layer
(?, ?, ?, 3) y.shape
exiting Gram

如果最后5行被替换为

outputs = (Lambda(gram_layer))(In)

然后调试信息

Using Gram Layer
(1, 256, 256, 3) y.shape
exiting Gram
Using Gram Layer
(1, 256, 256, 3) y.shape
exiting Gram

它仍然运行两次,但形状推断是正确的。这是一个错误吗?还是我应该在github报告?

不确定为什么您的功能被称为两次,但是看到这一点并不少见。首先在汇编过程中被称为

似乎以"无"值重塑的问题。这不支持。

您可以用" -1"而不是没有重塑,但是在重塑中只能有一个" -1"。

建议1:

您所有的重塑代码都可以替换为:x = K.squeeze(y,axis=0)

警告:

,但这在凯拉斯(Keras)非常不寻常。axis=0尺寸是批处理大小。此代码只能使用batch_size = 1运行良好。(要么您的代码和我的建议)。

建议2:

如果您要使用batch_flatten,为什么要重塑?您在batch_flatten()之前进行的任何重塑都是毫无意义的,除非您真的是要平坦的最后两个维度并具有(256,768)张量。

建议3:

如果您想要a的实际值,bc对于计算,则需要获得其张量值而不是其配置值:

shp = K.shape(y)
a = shp[1] #maybe you need shp[1:2], depending on whether you get an error in the division line    
b = shp[2]
c = shp[3]

建议4:

使用占位符很奇怪。那不是卡拉斯的方式。

您应该简单地创建模型并告诉它您想要的形状:

model = vgg19.VGG19(input_shape = (256,256,64), weights='imagenet', include_top=False)

如果您确实要执行1个大小为1,则可以创建输入张量:

inputTensor = Input(batch_shape=(1,256,256,64)   
output = model(inputTensor)
model = Model(inputTensor, output)

最新更新