2017-04-06 45 views
0

我在tensorflow1.1中訓練了一個ESPCN,每次修補的成本時間在訓練時幾乎線性增加。前100個紀元只需4-5秒,但第70個紀元大約需要半分鐘。請參見下面的訓練結果:爲什麼tensorflow1.1在訓練時變得越來越慢?它是內存泄漏還是隊列匱乏?

image image

我搜索谷歌和堆棧溢出同樣的問題,並試圖下面的解決方案,但似乎沒有工作: 每sess.run()後1.增加tf.reset_default_graph() ; 2.添加time.sleep(5)以防止隊列飢餓;

我知道一般的想法,那就是減少Session()中的操作。但是如何?任何人都有解決方案?

這裏是我的代碼部分:

L3, var_w_list, var_b_list = model_train(IN, FLAGS) 

cost = tf.reduce_mean(tf.reduce_sum(tf.square(OUT - L3), reduction_indices=0)) 

global_step = tf.Variable(0, trainable=False) 
learning_rate = tf.train.exponential_decay(FLAGS.base_lr, global_step * FLAGS.batch_size, FLAGS.decay_step, 0.96, staircase=True) 
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost, global_step = global_step, var_list = var_w_list + var_b_list) 
# optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9).minimize(cost, var_list = var_w_list + var_b_list) 

cnt = 0 

with tf.Session() as sess: 
    init_op = tf.initialize_all_variables() 
    sess.run(init_op) 
    saver = tf.train.Saver() 
    ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir) 
    print('\n\n\n =========== All initialization finished, now training begins ===========\n\n\n') 
    t_start = time.time() 
    t1 = t_start 

    for i in range(1, FLAGS.max_Epoch + 1): 

     LR_batch, HR_batch = batch.__next__() 
     global_step += 1 
     [_, cost1] = sess.run([optimizer, cost], feed_dict = {IN: LR_batch, OUT: HR_batch}) 
     # tf.reset_default_graph() 

     if i % 100 == 0 or i == 1: 
      print_step = i 
      print_loss = cost1/FLAGS.batch_size 

      test_LR_batch, test_HR_batch = test_batch.__next__() 
      test_SR_batch = test_HR_batch.copy() 
      test_SR_batch[:,:,:,0:3] = sess.run(L3, feed_dict = {IN: test_LR_batch[:,:,:,0:3]}) 
      # tf.reset_default_graph() 
      psnr_tmp = 0.0 
      ssim_tmp = 0.0 

      for k in range(test_SR_batch.shape[0]): 
       com1 = test_SR_batch[k, :, :, 0] 
       com2 = test_HR_batch[k, :, :, 0] 
       psnr_tmp += get_psnr(com1, com2, FLAGS.HR_size, FLAGS.HR_size) 
       ssim_tmp += get_ssim(com1, com2, FLAGS.HR_size, FLAGS.HR_size) 

      psnr[cnt] = psnr_tmp/test_SR_batch.shape[0] 
      ssim[cnt] = ssim_tmp/test_SR_batch.shape[0] 
      ep[cnt] = print_step 
      t2 = time.time() 
      print_time = t2 - t1 
      t1 = t2 

      print(("[Epoch] : {0:d} [Current cost] : {1:5.8f} \t [Validation PSNR] : {2:5.8f} \t [Duration time] : {3:10.8f} s \n").format(print_step, print_loss, psnr[cnt], print_time)) 
      # tf.reset_default_graph() 

      cnt += 1 

     if i % 1000 == 0: 

      L3_test = model_test(IN_TEST, var_w_list, var_b_list, FLAGS) 

      output_img = single_HR.copy() 
      output_img[:,:,:,0:3] = sess.run(L3_test, feed_dict = {IN_TEST:single_LR[:,:,:,0:3]}) 
      tf.reset_default_graph() 
      subname = FLAGS.img_save_dir + '/' + str(i) + ".jpg" 
      img_gen(output_img[0,:,:,:], subname) 

      print(('================= Saving model to {}/model.ckpt ================= \n').format(FLAGS.checkpoint_dir)) 

      time.sleep(5) 

      # saver.save(sess, FLAGS.checkpoint_dir + '/model.ckpt', print_step) 

t_tmp = time.time() - t_start 

我的配置是:windows10 + tf1.1 + python3.5 + cuda8.0 + cudnn5.1

======== ================================================== ======

此外,我在最後一層使用像素混合(PS)層而不是反捲積。我複製別人的PS代碼,如下所示:

def _phase_shift(I, r): 
    bsize, a, b, c = I.get_shape().as_list() 
    bsize = tf.shape(I)[0] # Handling Dimension(None) type for undefined batch dim 
    X = tf.reshape(I, (bsize, a, b, r, r)) 
    X = tf.transpose(X, (0, 1, 2, 4, 3)) # bsize, a, b, 1, 1 
    X = tf.split(X, a, 1) # a, [bsize, b, r, r] 
    X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2) # bsize, b, a*r, r 
    X = tf.split(X, b, 1) # b, [bsize, a*r, r] 
    X = tf.concat([tf.squeeze(x, axis=1) for x in X], 2) # bsize, a*r, b*r 
    return tf.reshape(X, (bsize, a*r, b*r, 1)) 

def PS(X, r, color=False): 
    if color: 
     Xc = tf.split(X, 3, 3) 
     X = tf.concat([_phase_shift(x, r) for x in Xc], 3) 
    else: 
     X = _phase_shift(X, r) 
    return X 

X是4維圖像張量,r裝置向上縮放因子,color確定圖像的信道是否是3(YCbCr格式)或1(灰度格式)。

要使用層很簡單,就像tf.nn.relu()做:

L3_ps = PS(L3, scale, True) 

現在我不知道該圖層是否造成緩行,因爲程序使用反褶積層時順利。使用解卷積層可能是一個解決方案,但由於某些原因我必須使用PS層。

+0

你能不能僅僅調用sess.run調用?這是使用tf運行時的唯一部分,在其他地方可能會出現緩慢。使用tf的方式在循環過程中似乎沒有觸發任何圖形增長(這會導致緩慢)。 –

+0

我已經試過你的建議:計時每一個'[_,cost1] = sess.run([優化器,成本],feed_dict = {IN:LR_batch,OUT:HR_batch})''。我看到每個時代都在放緩。我想知道PS層是否會導致放慢速度,這是在問題描述之後添加的。@AlexandrePassos – Cyiano

+0

我現在正在觀察這個確切的問題。你有沒有解決它? –

回答

0

我懷疑這條線是造成內存泄漏(雖然沒有看到代碼,我不能肯定地說):

L3_test = model_test(IN_TEST, var_w_list, var_b_list, FLAGS) 

L3_test似乎是一個tf.Tensor(因爲您以後將它傳遞給sess.run() ,因此model_test()在每次調用時(每1000步都會增加一個新節點)會導致更多的工作需要完成。

雖然這個解決方案非常簡單:因爲model_test()沒有取決於訓練循環中計算的任何東西,你可以將呼叫移至訓練循環之外,因此只調用一次。

+1

好吧,這是一個重要的因素,我將'model_test()'移到了循環外部,網絡運行速度更快。但它似乎不是至關重要的因素,因爲時間仍在每隔100個時代增加。我想知道'PS'層是否會導致放緩,這是在問題描述之後添加的。 – Cyiano

相關問題