tensorflow(2)——TFrecord填坑

填坑

  • 前文的坑讓我蒙了近一個小時,然後出去接了杯水…

原代碼

    dics = {
        'data': tf.FixedLenFeature(shape=[100], dtype=tf.float32, default_value=0.0),
        'label': tf.FixedLenFeature(shape=[2], dtype=tf.float32)
    }

在這裏插入圖片描述

修改後

 dics = {
        'data': tf.FixedLenFeature(shape=[100], dtype=tf.float32),
        'label': tf.FixedLenFeature(shape=[2], dtype=tf.float32)
    }

在這裏插入圖片描述

  • 我還是太年輕,看到維度信息,一直以爲是前面的那個維度參數,沒想過後面填充的問題…

批量處理

tf.train.batch()

tf.train.batch(
    tensors,
    batch_size,
    num_threads=1,
    capacity=32,
    enqueue_many=False,
    shapes=None,
    dynamic_pad=False,
    allow_smaller_final_batch=False,
    shared_name=None,
    name=None
)

  • 該函數將會使用一個隊列,函數讀取一定數量的tensors送入隊列,然後每次從中選取batch_size個tensors組成一個新的tensors返回出來。

  • capacity參數決定了隊列的長度。

  • num_threads決定了有多少個線程進行入隊操作,如果設置的超過一個線程,它們將從不同文件不同位置同時讀取,可以更加充分的混合訓練樣本。

  • 如果enqueue_many參數爲False,則輸入參數tensors爲一個形狀爲[x, y, z]的張量,輸出爲一個形狀爲[batch_size, x, y, z]的張量。如果enqueue_many參數爲True,則輸入參數tensors爲一個形狀爲[, x, y, z]的張量,其中所有的數值相同,輸出爲一個形狀爲[batch_size, x, y, z]的張量。

  • 當allow_smaller_final_batch爲True時,如果隊列中的張量數量不足batch_size,將會返回小於batch_size長度的張量,如果爲False,剩下的張量會被丟棄。

tf.train.shuffle_batch()

tf.train.shuffle_batch(
    tensors,
    batch_size,
    capacity,
    min_after_dequeue,
    num_threads=1,
    seed=None,
    enqueue_many=False,
    shapes=None,
    allow_smaller_final_batch=False,
    shared_name=None,
    name=None
)

再挖一個坑

  • 以前是placeholder的代碼風格,現在準備改一改。
loss, train_op, global_step = m.train(xs, ys)
  • 該函數類似於上面的tf.train.batch(),同樣創建一個隊列,主要區別是會首先把隊列中的張量進行亂序處理,然後再選取其中的batch_size個張量組成一個新的張量返回。但是新增加了幾個參數。

  • capacity參數依然爲隊列的長度,建議capacity的取值如下:

  • min_after_dequeue + (num_threads + a small safety margin) * batch_size

  • min_after_dequeue這個參數的意思是隊列中,做dequeue(取數據)的操作後,線程要保證隊列中至少剩下min_after_dequeue個數據。如果min_after_dequeue設置的過少,則即使shuffle爲True,也達不到好的混合效果。

  • 假設你有一個隊列,現在裏面有m個數據,你想要每次隨機從隊列中取n個數據,則代表先混合了m個數據,再從中取走n個。
  • 當第一次取走n個後,隊列就變爲m-n個數據;當你下次再想要取n個時,假設隊列在此期間入隊進來了k個數據,則現在的隊列中有(m-n+k)個數據,則此時會從混合的(m-n+k)個數據中隨機取走n個。
  • 如果隊列填充的速度比較慢,k就比較小,那你取出來的n個數據只是與周圍很小的一部分(m-n+k)個數據進行了混合。
    因爲我們的目的肯定是想盡最大可能的混合數據,因此設置min_after_dequeue,可以保證每次dequeue後都有足夠量的數據填充盡隊列,保證下次dequeue時可以很充分的混合數據。
  • 其他參數和tf.train.batch()相同。

碰到的第二個Bug

ilename_queue = tf.train.string_input_producer([filenames], num_epochs=None,
                                                shuffle=True)
X_batch, y_batch = tf.train.shuffle_batch([X_out, y_out], batch_size=2,
                                          capacity=200, min_after_dequeue=100, num_threads=2)

num_epoch的None和shuffle_batch不兼容??

  • 我發現我num_epoch設置成1,2,3…(除了None),都會在sess.run處報錯
  • 我最開始一直一維是shuffle_batch的鍋,直到我一行一行排除…
  • 最後發現是在sess.run()處出現這個bug

在這裏插入圖片描述

  • 最後根據:https://blog.csdn.net/momowenbo/article/details/80473326
# 加上
sess.run(tf.local_variables_initializer())
  • 我真是fo了,我就想把自己代碼風格改一下,一下午+一晚上給玩進去了…

第三個坑

InvalidArgumentError (see above for traceback): Cannot assign a device for operation 'accuracy/ArgMax': Could not satisfy explicit device specification '/device:GPU:0' because no supported kernel for GPU devices is available.

部分代碼如下

  X_batch, y_batch = tf.train.shuffle_batch([X_out, y_out], batch_size=Config.batch_size,
                                              capacity=Config.batch_size*4+10, min_after_dequeue=Config.batch_size*2, num_threads=2)


    with tf.device("/device:GPU:0"):

        gpu_config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True))
        # 結束時自動釋放資源
        with tf.Session(config=gpu_config) as sess:
            # 激活所有變量
            sess.run(tf.global_variables_initializer())
            sess.run(tf.local_variables_initializer())

            print("Train and value start! ")

            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)

            _X_batch, _y_batch = sess.run([X_batch, y_batch])

            optim, loss, acc, summaries = textnn_model.train(_X_batch, _y_batch,0.5)

            print(sess.run(loss))

當我改爲CPU環境時

tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value cnn/conv-maxpool-2/W
	 [[Node: cnn/conv-maxpool-2/W/read = Identity[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"](cnn/conv-maxpool-2/W)]]
X_batch, y_batch = tf.train.shuffle_batch([X_out, y_out], batch_size=Config.batch_size,
                                              capacity=Config.batch_size*4+10, min_after_dequeue=Config.batch_size*2, num_threads=2)

    optim, loss, acc, summaries = textnn_model.train(X_batch, y_batch, 0.5)

    with tf.Session() as sess:
        # 激活所有變量
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())

        print("Train and value start! ")

        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)

        print(sess.run(optim))
  • 我把textnn_model.train的位置換到了上面,所有的報錯都沒了…
  • 我…自己瞎玩血浪費時間…

趟過上面的坑,基本就沒啥了

  • 但是我碰到一個讓我很無語的東西,以前我用yield的時候:
for epoch in range(epoch_ums):
	for batch in batch_iter:
		........
  • 但是我現在循環怎麼寫?
# 總不能:
for i in range(10000):
	........
  • 暫時有點不清楚怎麼巧妙設置這個值,只能用 epoch * batches 來代替…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章