web-dev-qa-db-ja.com

Tensorflowの新しいモデルのサブセットである変数を復元しますか?

Tensorflowを介してブースティング(4層DNNから5層DNN)の例を実行しています。 TFチュートに短い段落があるため、セッションの保存とTFでの復元でそれを作成しています:「たとえば、4つのレイヤーでニューラルネットをトレーニングし、5つのレイヤーで新しいモデルをトレーニングして、復元したい場合以前にトレーニングされたモデルの4つのレイヤーから新しいモデルの最初の4つのレイヤーへのパラメーター。 '、ここでテンソルフローチュートは https://www.tensorflow.org/how_tos/variables/ から着想を得ています。

ただし、チェックポイントが4つのレイヤーのパラメーターを保存するときに「復元」を使用する方法を誰も尋ねていないことがわかりましたが、それを5つのレイヤーに入れて、赤いフラグを立てる必要があります。

これを実際のコードで作成して、

with tf.name_scope('fcl1'):
    hidden_1 = fully_connected_layer(inputs, train_data.inputs.shape[1], num_hidden)            
with tf.name_scope('fcl2'):
    hidden_2 = fully_connected_layer(hidden_1, num_hidden, num_hidden)                
with tf.name_scope('fclf'):
    hidden_final = fully_connected_layer(hidden_2, num_hidden, num_hidden)    
with tf.name_scope('outputl'):
    outputs = fully_connected_layer(hidden_final, num_hidden, train_data.num_classes, tf.identity)
    outputs = tf.nn.softmax(outputs)
with tf.name_scope('boosting'):
    boosts = fully_connected_layer(outputs, train_data.num_classes, train_data.num_classes, tf.identity)

ここで、 'fcl1'の内部(またはそこから呼び出される)の変数-重みとバイアスに 'fcl1/Variable'と 'fcl1/Variable_1'があるように-'fcl2'、 'fclf'、および 'outputl'はsaver.saveによって保存されます()「ブースト」レイヤーなしのスクリプト内。ただし、「ブースト」レイヤーがあるため、saver.restore(sess、 "saved_models/model_list.ckpt")は次のように機能しません

NotFoundError: Key boosting/Variable_1 not found in checkpoint

この問題について、ぜひお聞かせください。ありがとうございました。以下のコードは、私が困っているコードの主要部分です。

def fully_connected_layer(inputs, input_dim, output_dim, nonlinearity=tf.nn.relu):
    weights = tf.Variable(
        tf.truncated_normal(
            [input_dim, output_dim], stddev=2. / (input_dim + output_dim)**0.5), 
        'weights')
    biases = tf.Variable(tf.zeros([output_dim]), 'biases')
    outputs = nonlinearity(tf.matmul(inputs, weights) + biases)    

    return outputs

inputs = tf.placeholder(tf.float32, [None, train_data.inputs.shape[1]], 'inputs')
targets = tf.placeholder(tf.float32, [None, train_data.num_classes], 'targets')

with tf.name_scope('fcl1'):
    hidden_1 = fully_connected_layer(inputs, train_data.inputs.shape[1], num_hidden)            
with tf.name_scope('fcl2'):
    hidden_2 = fully_connected_layer(hidden_1, num_hidden, num_hidden)                
with tf.name_scope('fclf'):
    hidden_final = fully_connected_layer(hidden_2, num_hidden, num_hidden)    
with tf.name_scope('outputl'):
    outputs = fully_connected_layer(hidden_final, num_hidden, train_data.num_classes, tf.identity)

with tf.name_scope('error'):    
    error = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(outputs, targets))
with tf.name_scope('accuracy'):
    accuracy = tf.reduce_mean(tf.cast(
        tf.equal(tf.argmax(outputs, 1), tf.argmax(targets, 1)), 
        tf.float32))
with tf.name_scope('train'):
    train_step = tf.train.AdamOptimizer().minimize(error)

init = tf.global_variables_initializer()  
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(init)
    saver.restore(sess, "saved_models/model.ckpt")
    print("Model restored")

    print("Optimization Starts!")
    for e in range(training_epochs):
        ...

   #Save model - save session        
    save_path = saver.save(sess, "saved_models/model.ckpt")
    ### I once saved the variables using var_list, but didn't work as well...
    print("Model saved in file: %s" % save_path)

明確にするために、チェックポイントファイルには

fcl1/Variable:0

fcl1/Variable_1:0

fcl2/Variable:0

fcl2/Variable_1:0

fclf/Variable:0

fclf/Variable_1:0

outputl/Variable:0

outputl/Variable_1:0

元の4レイヤーモデルには「ブースト」レイヤーがありません。

11
sdr2002

この場合、チェックポイントからブースティングの値を読み取るのは正しくありません。それは、あなたがしたいことではないと思います。変数を復元している間、最初にモデル内のすべての変数のリストをキャッチしてから、チェックポイントで対応する変数を探しますが、それらはありません。

モデル変数のサブセットを定義することにより、モデルの一部のみを復元できます。たとえば、tf.slimライブラリを使用してそれを行うことができます。モデル内の変数のリストを取得します。

variables = slim.get_variables_to_restore()

変数はテンソルのリストになりましたが、各要素についてそのname属性にアクセスできます。これを使用して、ブースティング以外のレイヤーのみを復元することを指定できます。例:

variables_to_restore = [v for v in variables if v.name.split('/')[0]!='boosting'] 
model_path = 'your/model/path'

saver = tf.train.Saver(variables_to_restore)

with tf.Session() as sess:
    saver.restore(sess, model_path)

これにより、4つのレイヤーが復元されます。理論的には、変数リストをブーストするだけの別のサーバーを作成し、選択した変数の名前をチェックポイントから変更することにより、チェックポイントから変数の1つの値をキャッチしようとすることができますが、ここで必要なものはないと思います。

これはモデルのカスタムレイヤーであり、この変数はどこにもないため、インポートしようとする代わりに、ワークフロー内で初期化するだけです。たとえば、完全に接続された関数を呼び出すときに、この引数を渡すことで実行できます。

weights_initializer = slim.variance_scaling_initializer()

ただし、インポートの内容や、ここで使用している関数がわからないため、詳細を自分で確認する必要があります。

一般的には、スリムライブラリを確認することをお勧めします。これにより、レイヤーのモデルとスコープを簡単に定義できます(関数を呼び出すときにスコープ引数を渡して定義するのではなく)。それはスリムでそのようなものになるでしょう:

boost = slim.fully_connected(input, number_of_outputs, activation_fn=None, scope='boosting', weights_initializer=slim.variance_scaling_initializer())
14
Karaszka