web-dev-qa-db-ja.com

入力層を置き換えるKeras

私が持っている(変更できない)コードは、my_input_tensorをinput_tensorとしてResnetを使用しています。

model1 = keras.applications.resnet50.ResNet50(input_tensor=my_input_tensor, weights='imagenet')

ソースコード を調べると、ResNet50関数はmy_input_tensorで新しいkeras入力レイヤーを作成し、残りのモデルを作成します。これは、自分のモデルでコピーしたい動作です。 h5ファイルからモデルをロードします。

model2 = keras.models.load_model('my_model.h5')

このモデルにはすでに入力レイヤーがあるため、my_input_tensorで定義された新しい入力レイヤーに置き換えたいと思います。

入力レイヤーを置き換えるにはどうすればよいですか?

10
zcadqe

次を使用してモデルを保存したとき:

old_model.save('my_model.h5')

以下を保存します:

  1. モデルを作成できるモデルのアーキテクチャ。
  2. モデルの重み。
  3. モデルのトレーニング構成(損失、オプティマイザー)。
  4. オプティマイザーの状態。以前の場所からトレーニングを再開できます。

そのため、モデルをロードすると:

res50_model = load_model('my_model.h5')

同じモデルを取得する必要があります。次を使用して同じことを確認できます。

res50_model.summary()
res50_model.get_weights()

これで、入力レイヤーをポップし、以下を使用して独自のレイヤーを追加できます。

res50_model.layers.pop(0)
res50_model.summary()

新しい入力レイヤーを追加します。

newInput = Input(batch_shape=(0,299,299,3))    # let us say this new InputLayer
newOutputs = res50_model(newInput)
newModel = Model(newInput, newOutputs)

newModel.summary()
res50_model.summary()
20
Milind Deore

残念ながら、@ MilindDeoreの解決策はうまくいきませんでした。新しいモデルの概要を印刷できますが、予測時に「Matrix size incompatible」エラーが表示されます。高密度層の新しい入力形状は、古い高密度層の重みの形状と一致しないため、これは理にかなっていると思います。

したがって、ここに別の解決策があります。私にとっての鍵は、「レイヤー」の代わりに「_レイヤー」を使用することでした。後者はコピーを返すだけのようです。

import keras
import numpy as np

def get_model():
    old_input_shape = (20, 20, 3)
    model = keras.models.Sequential()
    model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
    model.add(keras.layers.MaxPooling2D((2, 2)))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(1, activation="sigmoid"))
    model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
    model.summary()
    return model

def change_model(model, new_input_shape=(None, 40, 40, 3)):
    # replace input shape of first layer
    model._layers[1].batch_input_shape = new_input_shape

    # feel free to modify additional parameters of other layers, for example...
    model._layers[2].pool_size = (8, 8)
    model._layers[2].strides = (8, 8)

    # rebuild model architecture by exporting and importing via json
    new_model = keras.models.model_from_json(model.to_json())
    new_model.summary()

    # copy weights from old model to new one
    for layer in new_model.layers:
        try:
            layer.set_weights(model.get_layer(name=layer.name).get_weights())
        except:
            print("Could not transfer weights for layer {}".format(layer.name))

    # test new model on a random input image
    X = np.random.Rand(10, 40, 40, 3)
    y_pred = new_model.predict(X)
    print(y_pred)

    return new_model

if __name__ == '__main__':
    model = get_model()
    new_model = change_model(model)
3
gebbissimo