web-dev-qa-db-ja.com

model.trainable =モデルの下の誤ったフリーズウェイトはすべきではありませんか?

無料でトレーニングされたVGG16のレイヤー(以下の「conv_base」)をフリーズし、特徴抽出のためにそれらの上に新しいレイヤーを追加しようとしています。モデルの 'conv_base' before(ret1)/ after(ret2)フィットから同じ予測結果が得られると期待していますが、そうではありません。これは体重の凍結をチェックする間違った方法ですか?

vGG16をロードし、トレーニング不可に設定

conv_base  = applications.VGG16(weights='imagenet', include_top=False, input_shape=[150, 150, 3]) 
conv_base.trainable = False

モデル適合前の結果

ret1 = conv_base.predict(np.ones([1, 150, 150, 3]))

vGG16の上にレイヤーを追加し、モデルをコンパイルします

model = models.Sequential()
model .add(conv_base)
model .add(layers.Flatten())
model .add(layers.Dense(10, activation='relu'))
model .add(layers.Dense(1, activation='sigmoid'))
m.compile('rmsprop', 'binary_crossentropy', ['accuracy'])

モデルに合わせる

m.fit_generator(train_generator, 100, validation_data=validation_generator, validation_steps=50)

モデル適合後の結果

ret2 = conv_base.predict(np.ones([1, 150, 150, 3]))

これが真実であることを願っていますが、そうではありません。

np.equal(ret1, ret2)
8
page

これは興味深いケースです。このようなことが起こる理由は、次のことが原因です。

コンパイル後にモデル全体をフリーズすることはできません。コンパイルされていない場合はフリーズされません

フラグを設定した場合model.trainable=False次に、コンパイル中にkerasは、すべてのレイヤーをトレーニング不可に設定します。コンパイル後にこのフラグを設定すると、モデルにはまったく影響しません。同じ-コンパイルする前にこのフラグを設定してから、モデルの一部を再利用して別のモデルをコンパイルする場合-再利用されたレイヤーには影響しません。そう model.trainable=Falseは、次の順序で適用する場合にのみ機能します。

# model definition
model.trainable = False
model.compile()

他のシナリオでは、期待どおりに機能しません。

10
Marcin Możejko

レイヤーを個別にフリーズする必要があります(コンパイル前):

for l in conv_base.layers: 
    l.trainable=False

これが機能しない場合は、おそらく新しいシーケンシャルモデルを使用してレイヤーをフリーズする必要があります。

モデルにモデルがある場合は、これを再帰的に実行する必要があります。

def freezeLayer(layer):
    layer.trainable = False
    if hasattr(layer, 'layers'):
        for l in layer.layers:
            freezeLayer(l)

freezeLayer(model)
8
Daniel Möller

一流の答えは機能しません。 Kerasの公式ドキュメント( https://keras.io/getting-started/faq/ )で示唆されているように、レイヤーごとに実行する必要があります。モデルには「トレーニング可能」なパラメーターがありますが、おそらくまだ実装されていません。最も安全な方法は、次のようにすることです。

for layer in model.layers:
    layer.trainable = False
model.compile()
1
Tristan_