72027


2枚の画像を入力して1つの出力を得る（分類される）CNNの設計を行っています。

具体的には，VGG16の特徴抽出層（重みは初期化しないでImagenetで学習済みのものを使用）を用いて2枚の画像から特徴を抽出し，それを全結合層で推論するネットワークです。

python3.6.4，keras2.3.1を使用しています。

ソースコードは以下の通りです。

[code]

    from keras.models import Model, Sequential
    from keras.layers import Input, Dense, Dropout, Activation, Flatten
    from keras.layers import add, concatenate
    from keras.utils import plot_model
    from keras.applications.vgg16 import VGG16
    import keras
    
    input_tensor = Input(shape=(224, 224, 3))
    
    NN1=VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
    NN2=VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
    merged = concatenate([NN1.output, NN2.output])
    
    NN3_conv = Flatten()(merged)
    NN3_conv = Dense(8192)(NN3_conv)
    NN3_conv = BatchNormalization()(NN3_conv)
    NN3_conv = Dense(8192)(NN3_conv)
    NN3_conv = BatchNormalization()(NN3_conv)
    NN3_conv = Dense(3, activation="softmax")(NN3_conv)
    
    model = Model([NN1.input, NN2.input], NN3_conv)
    
[/code]

しかし，以下のエラーが発生しました。

[code]

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-121-67cd30d6fe21> in <module>()
         21 NN3_conv = Dense(3, activation="softmax")(NN3_conv)
         22 
    ---> 23 model = Model([NN1.input, NN2.input], NN3_conv)
    
    ~\Anaconda3\lib\site-packages\keras\legacy\interfaces.py in wrapper(*args, **kwargs)
         89                 warnings.warn('Update your `' + object_name + '` call to the ' +
         90                               'Keras 2 API: ' + signature, stacklevel=2)
    ---> 91             return func(*args, **kwargs)
         92         wrapper._original_function = func
         93         return wrapper
    
    ~\Anaconda3\lib\site-packages\keras\engine\network.py in __init__(self, *args, **kwargs)
         92                 'inputs' in kwargs and 'outputs' in kwargs):
         93             # Graph network
    ---> 94             self._init_graph_network(*args, **kwargs)
         95         else:
         96             # Subclassed network
    
    ~\Anaconda3\lib\site-packages\keras\engine\network.py in _init_graph_network(self, inputs, outputs, name, **kwargs)
        159                              'is redundant. '
        160                              'All inputs should only appear once.'
    --> 161                              ' Found: ' + str(self.inputs))
        162         for x in self.inputs:
        163             # Check that x has appropriate `_keras_history` metadata.
    
    ValueError: The list of inputs passed to the model is redundant. All inputs should only appear once. Found: [<tf.Tensor 'input_24:0' shape=(?, 224, 224, 3) dtype=float32>, <tf.Tensor 'input_24:0' shape=(?, 224, 224, 3) dtype=float32>]
    
[/code]

ソースコード上のNN1，NN2をVGG16でなく自力で設計したものを適用するとうまくいくのですが，VGG16だとエラーが発生します。

どのようにすればエラーを解消できるのでしょうか。  
ご教授よろしくお願いします。


CC BY-SA 4.0
2020-11-17T07:30:28.410
72004
2020-11-18T05:12:37.500
41012
question
python python3 機械学習 深層学習 keras
kerasで2入力1出力のCNN設計をしたい


画像が二枚であれば、異なるinput_tensorを用意する必要があるのではないでしょうか。  
また、VGG16を2つ使う場合、レイヤー名の重複によるエラーが発生する可能性もあるため、明示的に変更する必要があります。Keras==2.4.3の場合、以下のように実行すればエラーの発生はしないようです。

[code]

    from keras.models import Model, Sequential
    from keras.layers import Input, Dense, Dropout, Activation, Flatten, BatchNormalization
    from keras.layers import add, concatenate
    from keras.utils import plot_model
    from keras.applications.vgg16 import VGG16
    import keras
    
    # 画像2つ分のinput_tensorを用意
    input_tensor1 = Input(shape=(224, 224, 3)) 
    input_tensor2 = Input(shape=(224, 224, 3))
    
    NN1 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor1)
    NN2 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor2)
    
    
    for i in range(1, len(NN2.layers)):
        NN2.layers[i]._name = NN2.layers[i].name + '1' #レイヤー名の明示的変更
    
    merged = concatenate([NN1.output, NN2.output])
    
    NN3_conv = Flatten()(merged)
    NN3_conv = Dense(8192)(NN3_conv)
    NN3_conv = BatchNormalization()(NN3_conv)
    NN3_conv = Dense(8192)(NN3_conv)
    NN3_conv = BatchNormalization()(NN3_conv)
    NN3_conv = Dense(3, activation="softmax")(NN3_conv)
    
    model = Model([NN1.input, NN2.input], NN3_conv)
    
[/code]

より古いバージョンのkerasでは、レイヤー名の変更部分のコードを以下のようにすることで機能する可能性があります:

[code]

    for layer in NN2.layers:
        layer.name += '_1'
    
[/code]

参考:  
[1]: <https://stackoverflow.com/questions/46213433/do-matrix-product-to-
outputs-of-two-models-in-keras>  
[2]: <https://github.com/keras-team/keras/issues/3974>


CC BY-SA 4.0
2020-11-18T04:05:05.680
72027
2020-11-18T05:12:37.500
2020-11-18T05:12:37.500
72004
answer