Tensorflow 2でload_Weightsのいくつかの研究

6464 ワード

kerasモデルを定義し、save_を使用するとします.Weights関数にはいくつかのパラメータが保存されています.このモデルの一部のみを定義しload_を使用しますWeightsは私たちが保存したこの完全なモデルをロードします.何が起こりますか?
まずソースコードを見てload_Weightsは実際にtensorflowを呼び出したcore/python/keras/engine/network.pyファイルのNetworkクラスのload_Weights関数ですが、この関数ではsave_formatはtfとh 5の2種類のファイルに対して異なる処理を行い、ここではh 5ファイルではないので、明らかにtfファイルであるべきである.ソースコードは貼られていません.ソースコードによると、tfファイルを読み取る関数はtensorflow_だと推測します.core/python/training/tracking/util.pyのTrackableSaverクラスのrestore関数です.私はこの関数のdocでこのような言葉を見つけた.
 If the checkpoint has not been consumed completely, then the list of restore ops will grow as more objects are added to the dependency graph.
この文は、私たちのcheckpoingファイルの内容がすべてロードされていない場合、残りのロードされていない変数は、私たちがこの図を使用するときに動的にロードされます.
では、実験をしましょう.まず、prosody-tacotronのglobal style token(gst)層を定義した.この図には2つのモードがある、'reference'と'weight'は、'reference'モードではモデルパラメータが完全に定義され、'weight'モードでは、モデルはgst埋め込みのみを定義し、マルチヘッド注意層とボリューム層の変数を定義しない.次は効果
hp.gst_mode = 'reference'
model = get_gst()
for i in model.trainable_variables:
    print(i.name)

"""
  :
gst_tokens:0
gst/multihead_attention/attention_v:0
gst/multihead_attention/attention_g:0
gst/multihead_attention/attention_b:0
gst/multihead_attention/conv1d/kernel:0
gst/multihead_attention/conv1d/bias:0
gst/multihead_attention/conv1d_1/kernel:0
gst/multihead_attention/conv1d_1/bias:0
"""

hp.gst_mode = 'weight'
model = get_gst()
for i in model.trainable_variables:
    print(i.name)

"""
  :
gst_tokens:0
"""

'reference'モードでモデルを保存し、'weight'モードでモデルを読み込み、同じかどうかを比較します.
hp.gst_mode = 'reference'
model1 = get_gst()
model1.save_weights('./checkpoint')

hp.gst_mode = 'weight'
model2 = get_gst()
model2.load_weights('./checkpoint')

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(True, shape=(), dtype=bool)
"""

モデルパラメータの一部のみを定義モデル2は、完全モデルモデル1の対応部分と同じパラメータであることがわかる.次にmodel 2を用いて'reference'モードで計算を行い,両者のパラメータを比較した.
hp.gst_mode = 'reference'
model2(np.zeros([32, 128], dtype=np.float32))

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/attention_v:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/attention_g:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/attention_b:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d/kernel:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d/bias:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d_1/kernel:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d_1/bias:0: tf.Tensor(True, shape=(), dtype=bool)
"""

モデル2が完全に定義、モデル1とモデル2のすべてのパラメータが同じであることがわかる.比較として、model 2がmodel 1のパラメータをロードしなければ、以下のような出力を得る.
hp.gst_mode = 'reference'
model1 = get_gst()
model1.save_weights('./checkpoint')

hp.gst_mode = 'weight'
model2 = get_gst()

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(False, shape=(), dtype=bool)
"""

hp.gst_mode = 'reference'
model2(np.zeros([32, 128], dtype=np.float32))

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(False, shape=(), dtype=bool)
gst/multihead_attention/attention_v:0: tf.Tensor(False, shape=(), dtype=bool)
gst/multihead_attention/attention_g:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/attention_b:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d/kernel:0: tf.Tensor(False, shape=(), dtype=bool)
gst/multihead_attention/conv1d/bias:0: tf.Tensor(True, shape=(), dtype=bool)
gst/multihead_attention/conv1d_1/kernel:0: tf.Tensor(False, shape=(), dtype=bool)
gst/multihead_attention/conv1d_1/bias:0: tf.Tensor(True, shape=(), dtype=bool)
"""

モデル2がモデル1に保存するモデルをロードしない場合、モデル1とモデル2のパラメータは異なるが、結果の同じ部分は、これらのパラメータを定数に初期化するためであることに注意する.
では、モデル1にモデル2が保存しているモデルをロードさせる方法を変えれば、何が起こるのでしょうか.次は実験結果です.
hp.gst_mode = 'weight'
model2 = get_gst()
model2.save_weights('./checkpoint')

hp.gst_mode = 'reference'
model1 = get_gst()
model1.load_weights('./checkpoint')

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(True, shape=(), dtype=bool)
"""

hp.gst_mode = 'reference'
model2(np.zeros([32, 128], dtype=np.float32))

for i in range(len(model2.trainable_variables)):
    v1 = model1.trainable_variables[i]
    v2 = model2.trainable_variables[i]
    print(v1.name, end=": ")
    print(tf.reduce_all(tf.equal(v1, v2)))

"""
  :
gst_tokens:0: tf.Tensor(True, shape=(), dtype=bool)
gst_1/multihead_attention/attention_v:0: tf.Tensor(False, shape=(), dtype=bool)
gst_1/multihead_attention/attention_g:0: tf.Tensor(True, shape=(), dtype=bool)
gst_1/multihead_attention/attention_b:0: tf.Tensor(True, shape=(), dtype=bool)
gst_1/multihead_attention/conv1d_2/kernel:0: tf.Tensor(False, shape=(), dtype=bool)
gst_1/multihead_attention/conv1d_2/bias:0: tf.Tensor(True, shape=(), dtype=bool)
gst_1/multihead_attention/conv1d_3/kernel:0: tf.Tensor(False, shape=(), dtype=bool)
gst_1/multihead_attention/conv1d_3/bias:0: tf.Tensor(True, shape=(), dtype=bool)
"""

モデル1は、モデル2が保存するモデルをロードすることができるが、モデル2は一部のモデルのみを含むため、モデル1はこの部分のみをロードすることができ、残りの部分はランダムに初期化するので、モデル2が完全に定義された後、残りのパラメータについては、モデル1とモデル2は異なる.