2015-12-28 5 views
8

の保存と復元: Tensorflow: how to save/restore a model?tensorflow:私は答えからの提案を実装しようとしていますセッション

私はsklearnスタイルでtensorflowモデルをラップするオブジェクトを持っています。

import tensorflow as tf 
class tflasso(): 
    saver = tf.train.Saver() 
    def __init__(self, 
       learning_rate = 2e-2, 
       training_epochs = 5000, 
        display_step = 50, 
        BATCH_SIZE = 100, 
        ALPHA = 1e-5, 
        checkpoint_dir = "./", 
      ): 
     ... 

    def _create_network(self): 
     ... 


    def _load_(self, sess, checkpoint_dir = None): 
     if checkpoint_dir: 
      self.checkpoint_dir = checkpoint_dir 

     print("loading a session") 
     ckpt = tf.train.get_checkpoint_state(self.checkpoint_dir) 
     if ckpt and ckpt.model_checkpoint_path: 
      self.saver.restore(sess, ckpt.model_checkpoint_path) 
     else: 
      raise Exception("no checkpoint found") 
     return 

    def fit(self, train_X, train_Y , load = True): 
     self.X = train_X 
     self.xlen = train_X.shape[1] 
     # n_samples = y.shape[0] 

     self._create_network() 
     tot_loss = self._create_loss() 
     optimizer = tf.train.AdagradOptimizer(self.learning_rate).minimize(tot_loss) 

     # Initializing the variables 
     init = tf.initialize_all_variables() 
     " training per se" 
     getb = batchgen(self.BATCH_SIZE) 

     yvar = train_Y.var() 
     print(yvar) 
     # Launch the graph 
     NUM_CORES = 3 # Choose how many cores to use. 
     sess_config = tf.ConfigProto(inter_op_parallelism_threads=NUM_CORES, 
                  intra_op_parallelism_threads=NUM_CORES) 
     with tf.Session(config= sess_config) as sess: 
      sess.run(init) 
      if load: 
       self._load_(sess) 
      # Fit all training data 
      for epoch in range(self.training_epochs): 
       for (_x_, _y_) in getb(train_X, train_Y): 
        _y_ = np.reshape(_y_, [-1, 1]) 
        sess.run(optimizer, feed_dict={ self.vars.xx: _x_, self.vars.yy: _y_}) 
       # Display logs per epoch step 
       if (1+epoch) % self.display_step == 0: 
        cost = sess.run(tot_loss, 
          feed_dict={ self.vars.xx: train_X, 
            self.vars.yy: np.reshape(train_Y, [-1, 1])}) 
        rsq = 1 - cost/yvar 
        logstr = "Epoch: {:4d}\tcost = {:.4f}\tR^2 = {:.4f}".format((epoch+1), cost, rsq) 
        print(logstr) 
        self.saver.save(sess, self.checkpoint_dir + 'model.ckpt', 
         global_step= 1+ epoch) 

      print("Optimization Finished!") 
     return self 

私が実行します。

tfl = tflasso() 
tfl.fit(train_X, train_Y , load = False) 

私は出力が得られます。しかし

Epoch: 50 cost = 38.4705 R^2 = -1.2036 
    b1: 0.118122 
Epoch: 100 cost = 26.4506 R^2 = -0.5151 
    b1: 0.133597 
Epoch: 150 cost = 22.4330 R^2 = -0.2850 
    b1: 0.142261 
Epoch: 200 cost = 20.0361 R^2 = -0.1477 
    b1: 0.147998 

、私は(たとえオブジェクトを殺すことなく)パラメータを回復しようとすると: tfl.fit(train_X, train_Y , load = True)

私は奇妙な結果を得ます。まず、ロードされた値は保存された値と一致しません。

loading a session 
loaded b1: 0.1   <------- Loaded another value than saved 
Epoch: 50 cost = 30.8483 R^2 = -0.7670 
    b1: 0.137484 

ロードする正しい方法は何でしょうか?おそらく最初に保存された変数を調べますか?

+0

tensorflowのドキュメントはかなり基本的な例を欠いている、あなたは例のフォルダに掘ると、ほとんど自分自身 – diffeomorphism

答えて

10

TL; DR:あなたは一度だけself.create_network()は、(i)と呼ばれているので、このクラスを手直ししようとする必要があり、および(ii)tf.train.Saver()前に構築されます。

ここには2つの微妙な問題があります。これはコード構造と、デフォルトの動作がtf.train.Saver constructorであるためです。 (コードのように)引数を持たないセーバーを構築すると、プログラム内の現在の変数セットが収集され、関数の保存と復元のためにグラフにopsが追加されます。あなたのコードでは、tflasso()を呼び出すと、それは保護者を構成し、変数はありません(create_network()はまだ呼び出されていないため)。その結果、チェックポイントは空になります。

2番目の問題は、デフォルトで— —です。保存されたチェックポイントの形式は、name property of a variableから現在の値までのマップです。同じ名前を持つ2つの変数を作成した場合、彼らはTensorFlowによって自動的に「単一化」になります。

v = tf.Variable(..., name="weights") 
assert v.name == "weights" 
w = tf.Variable(..., name="weights") 
assert v.name == "weights_1" # The "_1" is added by TensorFlow. 

この結果は、あなたがtfl.fit()に2回目の呼び出しでself.create_network()を呼び出すとき、変数はすべて持っているだろう、ということですチェックポイント—に格納されている名前とは異なる名前、またはネットワークの後にセーバーが構築されていたとします。 (あなたはセーバーのコンストラクタに名 - Variable辞書を渡すことで、この動作を回避することができますが、これは通常、非常に厄介である。)

を二つの主な回避策があります。tflasso.fit()への各呼び出しで

  1. は、作成します新たなモデルを新たに定義して、tf.Graphを定義し、そのグラフにネットワークを構築してtf.train.Saverを作成します。

  2. 推奨ネットワーク、tflassoコンストラクタで、その後tf.train.Saverを作成し、tflasso.fit()に各呼び出しでこのグラフを再利用します。特に、私があなたが何をself.Xself.xlenとしているか分からないが、placeholdersでこれを達成し、摂食することが可能でなければならないことに注意してください。

+0

でそれの意味を理解する必要があなたに感謝! 'xlen'は' self._create_network() 'の中で' X'の入力サイズを設定するために使われます(プレースホルダinit: 'self.vars.xx = tf.placeholder(" float "、shape = [None、self.xlen ])))。あなたが言うことから、好ましい方法は 'xlen'を初期化子に渡すことです。 –

+0

オブジェクトの再初期化時にuniquifier/clear old tf変数をリセットする方法はありますか? –

+1

これを行うには、新しい 'tf.Graph'を作成し、(i)ネットワークを作成し、(ii)' Saver'を作成する前にデフォルトにする必要があります。 'tf.Graph()。as_default():'ブロックで 'tflasso.fit()'の本文を折り返し、そのブロックの中で 'Saver'構造を動かすと、その名前はあなたの都度同じでなければなりません'fit()'を呼び出します。 – mrry

関連する問題