質問

以下のような動作をするCNNをKerasまたはTensorFlowで実装したいです.
ループ部分と多数決部分の実装法を教えていただきたいです.(CNN部分は大丈夫です)

画像の説明をここに入力

条件

  • 学習するCNNは単一のものを2*2のブロックに適用したいです
  • ブロックの分割は格子状に行います
  • 多数決はCNNで導出した確率を元に行いたいです

発生している問題

実装の際に,途中のループ処理の部分の文法がわからず困っています.
通常の機械学習では画像一枚へCNNを一回適用して判定結果を出すのに対して
このモデルではCNNを2*2回適用して,集計結果を最終的な判断としているためループが必要となってしまいます.

ソースコード

def set_vgg_model():
    inputs = Input(shape=(2174, 2174, 3)) #入力画像
    x = Lambda(lambda image: tf.image.resize_images(image, (224*2, 224*2)))(inputs) #画像のリサイズでCNNの入力層に合わせる
    x = Lambda(lambda image: block_transform(image, mode="channel"))(x) #ブロックに分割

    #モデル作成でここからをループ処理にしたい

    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(inputs)
    x = BatchNormalization()(x)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), padding='same', name='block1_pool')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = BatchNormalization()(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), padding='same', name='block2_pool')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = BatchNormalization()(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
    x = BatchNormalization()(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), padding='same', name='block3_pool')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
    x = BatchNormalization()(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
    x = BatchNormalization()(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), padding='same', name='block4_pool')(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
    x = BatchNormalization()(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)
    x = BatchNormalization()(x)
    x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), padding='same', name='block5_pool')(x)
    flattened = Flatten(name='flatten')(x)
    x = Dense(4096, activation='relu', name='fc1')(flattened)
    x = Dropout(0.5, name='dropout1')(x)
    x = Dense(4096, activation='relu', name='fc2')(x)
    x = Dropout(0.5, name='dropout2')(x)
    predictions = Dense(nb_classes, activation='softmax', name='predictions')(x)

    #ループ処理はここまで

    fin_pred = Lambda(lambda p: voting(p))(predictions) #多数決処理
    model = Model(inputs=inputs, outputs=predictions)
    return model 

if __name__ == '__main__':
    start = time.time()

    # モデル作成
    input_shape = (224, 224, 3)
    model = set_vgg_model()

    # モデルをプロットする。
    from keras.utils import plot_model
    plot_model(model, to_file='model.png', 
               show_shapes=True, show_layer_names=True)
    #sys.exit()

    # 多クラス分類を指定
    model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-5, momentum=0.9),#Adam(lr=0.1, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False), 
              metrics=['accuracy'])


    x_train, y_train, x_test, y_test = set_tensor()

    # Fine-tuning
    history = model.fit(x_train, 
                            y_train, 
                            batch_size=batch_size, 
                            epochs=nb_epoch,
                            validation_data=(x_test, y_test), 
                            verbose=1, 
                            shuffle=True)

実装上の疑問

  • ループ処理はモデル定義内で実装することは可能なのか.(main内で実装することになるのか,またはそもそもKerasでは不可能なのか)