tf.kerasのモデルの名前を変更してアンサンブルモデルを作る

Tensorflow.kerasのモデル名変更のイメージ図 プログラミング
Tensorflow.kerasのモデル名変更のイメージ図

本記事の適用シーン

アンサンブル推論の際に同じモデル名の複数の転移学習モデルを1つに合体したい

tensorflowのkerasにおいて、既に用意されているモデルである、resnetやmobilenetやefficientnetを使い転移学習をすることがよくあると思います。

その際に、モデルを複数用意して1つの入力画像に対して、複数の出力値を元に結果を判断する手法を「アンサンブル学習」と呼ばれています。

実は同じ学習データ、同じモデルを複数用意して学習しても、精度向上を図ることができます。

参考記事:ニューラルネットワークを使ったEnd-to-Endなアンサンブル学習

従いまして、resnet等の既に用意されているモデルを複数呼び出してアンサンブルモデルを作ることで簡単に精度をあげることができます。

概要

アンサンブルモデルを作る際に、例えば10個のモデルを用意したとして、1つの画像に対して5回推論をさせるのは非常に効率が悪いです。

ですので、10つのモデルを1つに合体させて、1回の推論で10回分の推論をすることを考えます。

コードにすると以下のようになります。

import tensorflow as tf

#アンサンブルのモデルの数
model_num = 10
#モデルを入れる空のリスト
models = []
#for文でモデルをリストに入れる
for n in range(model_num):
    #モデルの定義
    base_model = tf.keras.applications.EfficientNetB2(
        include_top=True, weights='imagenet',
        input_shape=(260, 260, 3))
  #モデルのコンパイル
    base_model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
    #リストに追加
    models.append(base_model)

#アンサンブルモデルのinputを作成
unsamble_input = tf.keras.layers.Input(shape=(260, 260, 3))

#モデルに作成したinputを入れてoutputのリストを作る
outputs = []
for n in range(model_num):
    outputs.append(models[n](unsamble_input))

#アンサンブルモデルを定義
unsamble_model = Model(unsamble_input, outputs)

ただ、このコードではtf.kerasの同じモデル名のものを1つのモデルにしようしているため

以下のコードの部分で

#アンサンブルモデルを定義
unsamble_model = Model(unsamble_input, outputs)
ValueError: The name "efficientnetb2" is used 10 times in the model. All layer names should be unique.

同じモデル名を使うな、と怒られてしまいます。

ですので、モデルの名前を変更する必要があります。

名前変更コード

model._name = model.name + "好きな文字列"

これで名前を変更できます。

実例

先ほどのコードの一部を変更します。

モデルを10個作りリストに格納した後に以下のようにモデル名に連番を付けるコードを追加しています。

#モデルの名前に連番をつける
for n, m in enumerate(models):
    m._name = m.name + "_" + str(n)

最後に全体のコードを載せておきます。

ここではimagenetの同じ重みを用いて10個のモデルを1つにしていますが、実際には学習したモデルを合体させない意味ないので注意です。

実際には転移学習で出力層の分類数を変更し、学習しなおしたモデルを使うことになります。

import tensorflow as tf

#アンサンブルのモデルの数
model_num = 10
#モデルを入れる空のリスト
models = []
#for文でモデルをリストに入れる
for n in range(model_num):
    #モデルの定義
    base_model = tf.keras.applications.EfficientNetB2(
        include_top=True, weights='imagenet',
        input_shape=(260, 260, 3))
  #モデルのコンパイル
    base_model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
    #リストに追加
    models.append(base_model)

#モデルの名前に連番をつける
for n, m in enumerate(models):
    m._name = m.name + "_" + str(n)

#アンサンブルモデルのinputを作成
unsamble_input = tf.keras.layers.Input(shape=(260, 260, 3))

#モデルに作成したinputを入れてoutputのリストを作る
outputs = []
for n in range(model_num):
    outputs.append(models[n](unsamble_input))

#アンサンブルモデルを定義
unsamble_model = Model(unsamble_input, outputs)

最後に

レイヤ名の変更記事は多かったですがモデル名はなかったので記事させていただきました。

ここでは書かなかったですが1つ1つ推論するより1つに合体させた方が推論時間も短くなります。

ぜひ試してみてください。

コメント

タイトルとURLをコピーしました