tensorflow的數據輸入

tensorflow有兩種數據輸入方法,比較簡單的一種是使用feed_dict,這種方法在畫graph的時候使用placeholder來站位,在真正run的時候通過feed字典把真實的輸入傳進去。比較簡單不再介紹。

比較惱火的是第二種方法,直接從文件中讀取數據(其實第一種也可以我們自己從文件中讀出來之后使用feed_dict傳進去,但方法二tf提供很完善的一套類和函數形成一個類似pipeline一樣的讀取線):
1.使用tf.train.string_input_producer函數把我們需要的全部文件打包為一個tf內部的queue類型,之后tf開文件就從這個queue中取目錄了,要注意一點的是這個函數的shuffle參數默認是True,也就是你傳給他文件順序是1234,但是到時候讀就不一定了,我一開始每次跑訓練第一次迭代的樣本都不一樣,還納悶了好久,就是這個原因。

files_in = ["./data/data_batch%d.bin" % i for i in range(1, 6)]
files = tf.train.string_input_producer(files_in)

2.搞一個reader,不同reader對應不同的文件結構,比如度bin文件tf.FixedLengthRecordReader就比較好,因為每次讀等長的一段數據。如果要讀什么別的結構也有相應的reader。

reader = tf.FixedLengthRecordReader(record_bytes=1+32*32*3)

3.用reader的read方法,這個方法需要一個IO類型的參數,就是我們上邊string_input_producer輸出的那個queue了,reader從這個queue中取一個文件目錄,然后打開它經行一次讀取,reader的返回是一個tensor(這一點很重要,我們現在寫的這些讀取代碼并不是真的在讀數據,還是在畫graph,和定義神經網絡是一樣的,這時候的操作在run之前都不會執行,這個返回的tensor也沒有值,他僅僅代表graph中的一個結點)。

key, value = reader.read(files)

4.對這個tensor做些數據與處理,比如CIFAR1-10中label和image數據是糅在一起的,這里用slice把他們切開,切成兩個tensor(注意這個兩個tensor是對應的,一個image對一個label,對叉了后便訓練就完了),然后對image的tensor做data augmentation。

data = tf.decode_raw(value, tf.uint8)
label = tf.cast(tf.slice(data, [0], [1]), tf.int64)
raw_image = tf.reshape(tf.slice(data, [1], [32*32*3]), [3, 32, 32])
image = tf.cast(tf.transpose(raw_image, [1, 2, 0]), tf.float32)

lr_image = tf.image.random_flip_left_right(image)
br_image = tf.image.random_brightness(lr_image, max_delta=63)
rc_image = tf.image.random_contrast(br_image, lower=0.2, upper=1.8)

std_image = tf.image.per_image_standardization(rc_image)

5.這時候可以發現,這個tensor代表的是一個樣本([高管道]),但是訓練網絡的時候的輸入一般都是一推樣本([樣本數寬*管道]),我們就要用tf.train.batch或者tf.train.shuffle_batch這個函數把一個一個小樣本的tensor打包成一個高一維度的樣本batch,這些函數的輸入是單個樣本,輸出就是4D的樣本batch了,其內部原理似乎是創建了一個queue,然后不斷調用你的單樣本tensor獲得樣本,直到queue里邊有足夠的樣本,然后一次返回一堆樣本,組成樣本batch。

images, labels = tf.train.batch([std_image, label],
                           batch_size=100,
                           num_threads=16,
                           capacity=int(50000* 0.4 + 3 * batch_size))

5.事實上一直到上一部的images這個tensor,都還沒有真實的數據在里邊,我們必須用Session run一下這個4D的tensor,才會真的有數據出來。這個原理就和我們定義好的神經網絡run一下出結果一樣,你一run這個4D tensor,他就會順著自己的operator找自己依賴的其他tensor,一路最后找到最開始reader那里。

除了上邊講的原理,其中還要注意幾點
1.tf.train.start_queue_runners(sess=sess)這一步一定要運行,且其位置要在定義好讀取graph之后,在真正run之前,其作用是把queue里邊的內容初始化,不跑這句一開始string_input_producer那里就沒用,整個讀取流水線都沒用了。

training_images = tf.train.batch(XXXXXXXXXXXXXXX)
tf.train.start_queue_runners(sess=self.sess)
real_images = sess.run(training_images)

2.image和label一定要一起run,要記清楚我們的image和label是在一張graph里邊的,跑一次那個graph,這兩個tensor都會出結果,且同一次跑出來的image和label才是對應的,如果你run兩次,第一次為了拿image第二次為了拿label,那整個就叉了,因為第一次跑出來第0到100號image和0到100號label,第二次跑出來第100到200的image和第100到200的label,你拿到了0100的image和100200的label,整個樣本分類全不對,最后網絡肯定跑不出結果。

training_images, training_labels = read_image()
tf.train.start_queue_runners(sess=self.sess)
real_images = sess.run(training_images) # 讀出來是真的圖片,但是和label對不上
real_labels = sess.run(training_labels) # 讀出來是真的label,但是和image對不上

# 正確調用方法,通過跑一次graph,將成套的label和image讀出來
real_images, real_labels = sess.run([training_images, training_labels])

因為不懂這個道理的up主跑了一下午正確率還是10%。。。。(10類別分類10%正確率不就是亂猜嗎)

原文:【tensorflow的數據輸入】

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容