Help us understand the problem. What is going on with this article?

KerasのContainer内部のtrainable設定について検証してみた

More than 1 year has passed since last update.

Kerasには、複数レイヤをまとめてインスタンス化するContainerが用意されている。例えば以下のように書くと、2層の全結合層をインスタンス化したshared_layerが作成される。これによってネットワーク内に共通のパラメータを持った層を組み込むことができる。

inputs = Input((3,))
x = Dense(3, activation="sigmoid", use_bias=False)(inputs)
x = Dense(3, activation="sigmoid", use_bias=False)(x)
shared_layer = Container(inputs=inputs, outputs=x, name="shared_layer")

検証すること

kerasではモデルを構成するそれぞれの層のtrainableを変更することでその層の重みを更新するかどうか決定するが、どうやらContainerで作ったインスタンスとContainerを構成する各層でこの設定が独立してるらしい。
ということで以下の2つの設定をそれぞれ変更した4通りについて層の重みが更新されるか検証する。
①Containerでインスタンス化した層のtrainable設定
②Container内部の層のtrainable設定

実行環境

Keras:2.1.6
Python:3.6.4

※keras2.2以降ではContainerの代わりにNetworkを使うらしいので注意

検証モデル

使用するライブラリは以下の通り。

from keras.layers import Input, Dense
from keras.models import Model
from keras.engine.topology import Container
from keras.optimizers import sgd

import numpy as np

3層のニューラルネットワークを構築し、shared_layer内のtrainable設定をいじっておく。

model.py
#共有レイヤ作成
inputs = Input((3,))
x = Dense(3, activation="sigmoid", use_bias=False)(inputs)
x = Dense(3, activation="sigmoid", use_bias=False)(x)
shared_layer = Container(inputs=inputs, outputs=x, name="shared_layer")

#テストモデル構築
y = shared_layer(inputs)

model = Model(inputs=inputs, outputs=y)

#shared_layerのうち片方の重みを固定
model.get_layer("shared_layer").layers[1].trainable=False

①shared_layer.trainable=True

trainableの状況確認

print("shared_layer.trainable = " + str(model.get_layer("shared_layer").trainable) + "\n")
print("--each layer.trainable in shared_layer--")
for i in model.get_layer("shared_layer").layers:
    print(i.name, i.trainable)

shared_layer.trainable = True

--each layer.trainable in shared_layer--
input_1 False
dense_1 False
dense_2 True

パラメータの確認

for i in model.layers:
    print(i.name, i.get_weights())

input_1 []
shared_layer [array([[-0.43590093, -0.49712682, -0.5146408 ],
[ 0.51134324, 0.07132649, 0.2040441 ],
[-0.62061524, 0.42325187, -0.5272429 ]], dtype=float32), array([[-0.09528399, 0.9781587 , 0.22182012],
[ 0.90270543, 0.23723674, -0.18667579],
[ 0.929554 , -0.57312965, 0.7156825 ]], dtype=float32)]

学習

#optimizer作成
SGD = sgd(lr = 10)

#ダミーデータ作成(バッチサイズ5)
train_x = np.random.rand(5,3)
train_y = np.random.rand(5,3)

#重み更新
model.compile(optimizer=SGD, loss="mean_squared_error")
model.fit(x=train_x, y=train_y)

#重みの確認
for i in model.layers:
    print(i.name, i.get_weights())

input_1 []
shared_layer [array([[-0.43590093, -0.49712682, -0.5146408 ],
[ 0.51134324, 0.07132649, 0.2040441 ],
[-0.62061524, 0.42325187, -0.5272429 ]], dtype=float32), array([[-0.18501434, 0.9731035 , 0.05751626],
[ 0.8193617 , 0.24262278, -0.386313 ],
[ 0.8491909 , -0.57754445, 0.57252395]], dtype=float32)]

2番めのDense層のみパラメータが更新されている。。。

②shared_layer.trainable=False

設定変更、trainableの状況確認

#設定の変更
model.get_layer("shared_layer").trainable=False

print("shared_layer.trainable = " + str(model.get_layer("shared_layer").trainable) + "\n")
print("--each layer.trainable in shared_layer--")
for i in model.get_layer("shared_layer").layers:
    print(i.name, i.trainable)

shared_layer.trainable = False

--each layer.trainable in shared_layer--
input_1 False
dense_1 False
dense_2 True

パラメータの確認

for i in model.layers:
    print(i.name, i.get_weights())

input_1 []
shared_layer [array([[-0.43590093, -0.49712682, -0.5146408 ],
[ 0.51134324, 0.07132649, 0.2040441 ],
[-0.62061524, 0.42325187, -0.5272429 ]], dtype=float32), array([[-0.18501434, 0.9731035 , 0.05751626],
[ 0.8193617 , 0.24262278, -0.386313 ],
[ 0.8491909 , -0.57754445, 0.57252395]], dtype=float32)]

学習

#ダミーデータ作成(バッチサイズ5)
train_x = np.random.rand(5,3)
train_y = np.random.rand(5,3)

#重み更新
model.compile(optimizer=SGD, loss="mean_squared_error")
model.fit(x=train_x, y=train_y)

#重みの確認
for i in model.layers:
    print(i.name, i.get_weights())

input_1 []
shared_layer [array([[-0.43590093, -0.49712682, -0.5146408 ],
[ 0.51134324, 0.07132649, 0.2040441 ],
[-0.62061524, 0.42325187, -0.5272429 ]], dtype=float32), array([[-0.18501434, 0.9731035 , 0.05751626],
[ 0.8193617 , 0.24262278, -0.386313 ],
[ 0.8491909 , -0.57754445, 0.57252395]], dtype=float32)]

どの層も重みの変化なし。。。

結論

まとめるとこんな感じ。早い話、コンテナのtrainableとコンテナ内の層のtrainableの論理積だった。

コンテナのtrainable\コンテナ内のlayer.trainable True False
True ×
False × ×
ryota717
物体検出、物体追跡関係の研究をしている某大学院のM2です。 普段はkerasを使っていますが、現在chainer,pytorch勉強中。 最近atcoder始めました(水coder)。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした