2017-11-27 6 views
0

なぜ次のコードがグラムレイヤーを2回実行するのですか?ケラスラムダレイヤーは一度だけ呼び出されても2回実行されます

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 

デバッグ情報は、この層は二回実行され、それが2回目に失敗しますが、妙にそれは一度だけ呼ばれています意味し、「グラム・レイヤーを使用した」2が含まれています。

何が悪いと思いますか?

PS:私は

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 
と行くように最後の行

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

を交換した場合、問題は、forループの部分にあることを認識

最後の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で報告すべきですか?

答えて

0

なぜあなたの関数が2回呼び出されたのか分かりませんが、それを見るのは珍しいことではありません。コンパイル時に最初に呼び出されます。

"なし"の値で再形成するような問題があります。それはサポートされていません。

Noneの代わりに "-1"を使用して変形することはできますが、 "-1"は1つしか変形できません。

提案1:

あなたのすべてのリシェイプコードを置き換えることができます:x = K.squeeze(y,axis=0)

警告:

しかし、これはkerasで非常に珍しいです。 axis=0の寸法はバッチサイズです。このコードはbatch_size = 1で正常に動作します。 (あなたのコードと私の提案のいずれか)。

提言2:

あなたはなぜリシェイプそして、batch_flattenを使用するつもりなら? batch_flatten()の前に行う再構成は、最後の2つのディメンションのみを平坦化し、テンソルが(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:

プレースホルダを使用するのは非常に奇妙です。それはケラスのやり方ではありません。

あなたは、単にモデルを作成し、それをあなたが望む形教えてください:あなたは、あなたが入力テンソルを作成することができ、1のバッチサイズを強制したくない場合は

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

を:

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

返信いただきありがとうございます。今ではほとんどの行を削除して、gram_layer関数は単に入力yを返しますが、問題はまだ存在します。私のコードは "None"の値で続けることはできません。 – DDz

+0

新しいコードと新しいエラーを投稿できますか? –

+0

確かに。元の投稿を編集する準備ができました。いくつかの行はコメントアウトされていて、デバッグ情報は少し異なります。 – DDz

関連する問題