TensorFlow:实战Google深度学习框架(六)图像数据处理
- 第七章 圖像數據處理
- 7.1 TFRecord輸入數據格式
- TensorFlow提供了一種統一的格式來存儲數據——TFRecord格式
- 7.1.1 TFRecord格式介紹
- 7.1.2 TFRecord樣例程序
- 7.2 圖像數據處理
- 7.2.1 TensorFlow圖像處理函數
- 1. 圖像編碼處理
- 2. 圖像大小調整
- 3. 圖像翻轉
- 4. 圖像色彩調整
- 5. 處理標注框
- 7.2.2 圖像預處理完整樣例
- 7.2.1 TensorFlow圖像處理函數
- 7.3 多線程輸入數據處理框架
- 7.3.1 隊列與多線程
- 7.3.2 輸入文件隊列
- 7.3.3 組合訓練數據(batching)
- 7.3.4 輸入數據處理框架
- 總結
- 7.1 TFRecord輸入數據格式
第七章 圖像數據處理
第6章中詳細介紹了卷積神經網絡,并提到了通過卷積神經網絡給圖像識別技術帶來了突破性進展,本章從另外一個維度來進一步提升圖像識別的精度以及訓練的速度。
7.1 TFRecord輸入數據格式
TensorFlow提供了一種統一的格式來存儲數據——TFRecord格式
7.1.1 TFRecord格式介紹
- tf.train.Example Protocol Buffer:TFRecord文件中的數據都是通過該格式儲存的。
下列代碼給出了tf.train.Example的定義
message Example{Features features=1;};message Features{map<string,Feature> feature=1;};message Feature{oneof kind{BytesList bytes_list=1;FloatList bytes_list=2;Int64List bytes_list=3;} };tf.train.Example中包含了一個從屬性名稱到取值的字典:
屬性名稱:一個字符串
屬性取值:字符串(BytesList)、實數列表(FloatList)、整數列表(Int64List)
7.1.2 TFRecord樣例程序
1. 將mnist輸入數據轉化為TFRecord格式
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import numpy as np# 1. 將輸入轉化成TFRecord格式并保存 # 定義函數轉化變量類型。 def _int64_feature(value):return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))def _bytes_feature(value):return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))# 讀取mnist數據。 mnist = input_data.read_data_sets("../../datasets/MNIST_data",dtype=tf.uint8, one_hot=True) images = mnist.train.images labels = mnist.train.labels pixels = images.shape[1] num_examples = mnist.train.num_examples# 輸出TFRecord文件的地址。 filename = "Records/output.tfrecords" # 需要存在Records目錄 writer = tf.python_io.TFRecordWriter(filename) for index in range(num_examples):image_raw = images[index].tostring()example = tf.train.Example(features=tf.train.Features(feature={'pixels': _int64_feature(pixels),'label': _int64_feature(np.argmax(labels[index])),'image_raw': _bytes_feature(image_raw)}))writer.write(example.SerializeToString()) writer.close() print("TFRecord文件已保存。")2. 讀取TFRecord文件中的數據
reader = tf.TFRecordReader() filename_queue = tf.train.string_input_producer(["Records/output.tfrecords"]) _,serialized_example = reader.read(filename_queue)# 解析讀取的樣例。 features = tf.parse_single_example(serialized_example,features={'image_raw':tf.FixedLenFeature([],tf.string),'pixels':tf.FixedLenFeature([],tf.int64),'label':tf.FixedLenFeature([],tf.int64)})images = tf.decode_raw(features['image_raw'],tf.uint8) labels = tf.cast(features['label'],tf.int32) pixels = tf.cast(features['pixels'],tf.int32)sess = tf.Session()# 啟動多線程處理輸入數據。 coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess,coord=coord)for i in range(10):image, label, pixel = sess.run([images, labels, pixels])7.2 圖像數據處理
7.2.1 TensorFlow圖像處理函數
1. 圖像編碼處理
圖像在存儲時并不是直接記錄像素矩陣中的數字,而是記錄了壓縮編碼之后的結果,所以要將一張圖像還原成一個三維矩陣,需要解碼的過程。TensorFlow提供了對jpeg和png格式圖像的編碼/解碼函數。
使用TensorFlow中對jpeg格式圖像的編碼/解碼函數
# matplotlib.pyplot是一個python畫圖工具 import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:# 將圖像使用的jpeg的格式解碼從而得到圖像對應的三維矩陣# TensorFlow還提供了tf.image.decode_png函數對png格式的圖像進行解碼# 解碼之后的結果為一個張量,在使用它的取值之前需要明確調用運行的過程img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 使用pyplot得到圖像plt.imshow(img_data.eval())plt.show()# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)# 將表示一張圖像的三維矩陣重新按照jpeg個數編碼并存到文件中# 打開該圖,可以得到和原圖一樣的圖像encode_image=tf.image.encode_jpeg(img_data) #輸入必須為uint8形式的,不然會報錯with tf.gfile.GFile("E:\\Opencv Image\\an.jpg",'wb') as f:f.write(encode_image.eval())2. 圖像大小調整
因為獲取的圖像大小不固定,但神經網絡輸入節點的個數是固定的,所以在將圖像像素作為輸入提供給神經網絡之前,需要先將圖像大小進行統一。
1.通過算法調整,使得得到的新圖像盡量保存原始圖像的所有信息
TensorFlow實現:提供了四種不同的算法,并封裝到了tf.image.resize_images函數
tf.image.resize_images(images, new_height, new_width, method=0) # Resize images to new_width, new_height using the specified method.tf.image.resize_images函數中method對應的取值
| 0 | 雙線性差值法(Bilinear interpolation) |
| 1 | 最近鄰法(Nearest neighbour interpolation) |
| 2 | 雙三次差值法(Bicubic interpolation) |
| 3 | 面積差值法(Area interpolation) |
代碼實現:
# matplotlib.pyplot是一個python畫圖工具 import matplotlib.pyplot as plt import tensorflow as tf import numpy as np# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:# 將圖像使用的jpeg的格式解碼從而得到圖像對應的三維矩陣# TensorFlow還提供了tf.image.decode_png函數對png格式的圖像進行解碼# 解碼之后的結果為一個張量,在使用它的取值之前需要明確調用運行的過程img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 使用pyplot得到圖像# plt.imshow(img_data.eval())# plt.show()# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)# 將表示一張圖像的三維矩陣重新按照jpeg個數編碼并存到文件中# 打開該圖,可以得到和原圖一樣的圖像# encode_image=tf.image.encode_jpeg(img_data)# with tf.gfile.GFile("E:\\Opencv Image\\an.jpg",'wb') as f:# f.write(encode_image.eval())with tf.Session() as sess:resized = tf.image.resize_images(img_data, [300, 300], method=3)print(img_data.get_shape())# TensorFlow的函數處理圖片后存儲的數據是float32格式的,需要轉換成uint8才能正確打印圖片。print( "Digital type: ", resized.dtype)angelababy2 = np.asarray(resized.eval(), dtype='uint8')# tf.image.convert_image_dtype(rgb_image, tf.float32)plt.imshow(angelababy2)plt.show()| 雙線性差值 | 最近鄰 |
| 雙三次插值 | 面積插值 |
2. 裁剪和填充
tf.image.resize_image_with_crop_or_pad(image, target_height, target_width)# Crops and/or pads an image to a target width and height. # Resizes an image to a target width and height by either centrally cropping the image or # padding it evenly with zeros.# image:原始圖像 # target_height, target_width:目標大小 # 如果原始圖像的尺寸大于目標圖像:自動截取居中的部分 # 如果原始圖像的尺寸小于目標圖像:四周全0填充 import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)with tf.Session() as sess:croped = tf.image.resize_image_with_crop_or_pad(img_data, 1000, 1000)padded = tf.image.resize_image_with_crop_or_pad(img_data, 500, 500)plt.imshow(croped.eval())plt.show()plt.imshow(padded.eval())plt.show()- 通過比例調整圖像大小——截取中間的部分
3. 圖像翻轉
實現圖像的上下翻轉、左右翻轉及對角線翻轉
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)# 6. 翻轉圖片 with tf.Session() as sess:# 上下翻轉# flipped1 = tf.image.flip_up_down(img_data)# 左右翻轉# flipped2 = tf.image.flip_left_right(img_data)# 對角線翻轉transposed = tf.image.transpose_image(img_data)plt.imshow(transposed.eval())plt.show()# 以一定概率上下翻轉圖片。# flipped = tf.image.random_flip_up_down(img_data)# 以一定概率左右翻轉圖片。# flipped = tf.image.random_flip_left_right(img_data)4. 圖像色彩調整
1. 亮度
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)plt.imshow(img_data.eval())plt.show()# 將圖片的亮度-0.5。# adjusted = tf.image.adjust_brightness(img_data, -0.5)# 將圖片的亮度+0.5adjusted = tf.image.adjust_brightness(img_data, 0.5)# 在[-max_delta, max_delta)的范圍隨機調整圖片的亮度。# adjusted = tf.image.random_brightness(img_data, max_delta=0.6)plt.imshow(adjusted.eval())plt.show()|
亮度增加0.5
2. 對比度
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)plt.imshow(img_data.eval())plt.show()# 將圖片的對比度-5# adjusted = tf.image.adjust_contrast(img_data, -5)# 將圖片的對比度+5adjusted = tf.image.adjust_contrast(img_data, 5)# 在[lower, upper]的范圍隨機調整圖的對比度。# adjusted = tf.image.random_contrast(img_data, lower, upper)plt.imshow(adjusted.eval())plt.show()|
對比度加5
3. 色相
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)adjusted = tf.image.adjust_hue(img_data, 0.1)# adjusted = tf.image.adjust_hue(img_data, 0.3)# adjusted = tf.image.adjust_hue(img_data, 0.6)# adjusted = tf.image.adjust_hue(img_data, 0.9)# 在[-max_delta, max_delta]的范圍隨機調整圖片的色相。max_delta的取值在[0, 0.5]之間。# adjusted = tf.image.random_hue(image, max_delta)plt.imshow(adjusted.eval())plt.show()|
4. 飽和度
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)print(img_data.eval())# 將數據的類型轉化成實數方便后續處理img_data=tf.image.convert_image_dtype(img_data,dtype=tf.uint8)# 將圖片的飽和度-5。adjusted = tf.image.adjust_saturation(img_data, -5)# 將圖片的飽和度+5。# adjusted = tf.image.adjust_saturation(img_data, 5)# 在[lower, upper]的范圍隨機調整圖的飽和度。# adjusted = tf.image.random_saturation(img_data, lower, upper)# 將代表一張圖片的三維矩陣中的數字均值變為0,方差變為1。# adjusted = tf.image.per_image_standardization(img_data)plt.imshow(adjusted.eval())plt.show()|
- TensorFlow還提供了API來完成圖像標準化的過程,將亮度均值變為0,方差變為1
|
5. 處理標注框
在很多圖像識別的數據集中,圖像中需要關注的物體通常會被標注框圈出來,利用下述函數實現:
tf.image.draw_bounding_boxs(images,boxes,name=None)# images:是 [batch, height, width, depth] 形狀的四維矩陣, # 數據類型為 float32、half 中的一種,第一個值batch是因為處理的是一組圖片。# boxes: 形狀 [batch, num_bounding_boxes, 4] 的三維矩陣, # num_bounding_boxes 是標注框的數量,標注框由四個數字標示 [y_min, x_min, y_max, x_max],數組類型為float32 # 例如:tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]]) # shape 為 [1,2,4] 表示一張圖片中的兩個標注框; # tf.constant([[[ 0. 0. 1. 1.]]]) 的 shape 為 [1,1,4]表示一張圖片中的一個標注框# name:操作的名稱(可選)。代碼示例:
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data=tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg",'rb').read()with tf.Session() as sess:img_data=tf.image.decode_jpeg(image_raw_data)# 先將圖像縮小,可讓標注框更為清楚img_data=tf.image.resize_images(img_data,180,260,methed=1)# tf.image.draw_bounding_boxes的輸入加一個batch,也就是多張圖像組成的思維矩陣# 所以要將解碼后的加一維度# tf.image.draw_bounding_boxes輸入為實數batched = tf.expand_dims(tf.image.convert_image_dtype(img_data, tf.float32), 0)boxes = tf.constant([[[0.01, 0.2, 0.5, 0.7],[0.25, 0.4, 0.32, 0.55]]])# [0.05, 0.05, 0.9, 0.7],(y min,x min,y max,x max)坐標點的相對位置,和原始大小相乘result=tf.image.draw_bounding_boxes(batched,boxes)plt.subplot(121), plt.imshow(img_data.eval())plt.subplot(122), plt.imshow(result[0].eval())plt.show()- 隨機截取圖像上有信息含量的部分也是提高模型健壯性的一種方式,可以使得訓練得到的模型不受識別物體的大小的影響。
代碼實現:
import matplotlib.pyplot as plt import tensorflow as tf# 讀取圖像的原始數據 image_raw_data = tf.gfile.FastGFile("E:\\Opencv Image\\anglababy.jpg", 'rb').read()with tf.Session() as sess:img_data = tf.image.decode_jpeg(image_raw_data)print(img_data.eval())img_data = tf.image.resize_images(img_data, (330, 200), method=1)boxes = tf.constant([[[0.01, 0.2, 0.5, 0.7], [0.25, 0.4, 0.32, 0.55]]])# 隨機圖像截取begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(tf.shape(img_data), bounding_boxes=boxes,min_object_covered=0.1)batched = tf.expand_dims(tf.image.convert_image_dtype(img_data, tf.float32), 0)image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)distorted_image = tf.slice(img_data, begin, size)plt.imshow(distorted_image.eval())plt.show()7.2.2 圖像預處理完整樣例
# 《TensorFlow實戰Google深度學習框架》07 圖像數據處理 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:ts07.03.py # 圖像預處理完整樣例import tensorflow as tf import numpy as np import matplotlib.pyplot as plt# 1. 隨機調整圖片的色彩,定義兩種順序 def distort_color(image, color_ordering=0):if color_ordering == 0:image = tf.image.random_brightness(image, max_delta=32./255.)image = tf.image.random_saturation(image, lower=0.5, upper=1.5)image = tf.image.random_hue(image, max_delta=0.2)image = tf.image.random_contrast(image, lower=0.5, upper=1.5)else:image = tf.image.random_saturation(image, lower=0.5, upper=1.5)image = tf.image.random_brightness(image, max_delta=32./255.)image = tf.image.random_contrast(image, lower=0.5, upper=1.5)image = tf.image.random_hue(image, max_delta=0.2)return tf.clip_by_value(image, 0.0, 1.0)# 2. 對圖片進行預處理,將圖片轉化成神經網絡的輸入層數據 # 給定一張解碼的圖像、目標尺寸、及圖像上的標注圖,此函數可以對給出的圖像進行預處理 # 輸入:原始訓練圖像 # 輸出:神經網絡模型的輸入層 # 注意:此處只處理模型的訓練數據,對預測數據不需要使用隨機變換的步驟 def preprocess_for_train(image, height, width, bbox):# 查看是否存在標注框,如果沒有標注框,則認為圖像就是整個需要關注的部分if bbox is None:bbox = tf.constant([0.0, 0.0, 1.0, 1.0], dtype=tf.float32, shape=[1, 1, 4])# 轉換圖像的張量類型if image.dtype != tf.float32:image = tf.image.convert_image_dtype(image, dtype=tf.float32)# 隨機的截取圖片中一個塊,減小物體大小對圖像識別算法的影響bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(tf.shape(image), bounding_boxes=bbox, min_object_covered=0.1)bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(tf.shape(image), bounding_boxes=bbox, min_object_covered=0.1)distorted_image = tf.slice(image, bbox_begin, bbox_size)# 將隨機截取的圖片調整為神經網絡輸入層的大小,大小調整的算法是隨機選擇的distorted_image = tf.image.resize_images(distorted_image, [height, width], method=np.random.randint(4))# 隨機左右翻轉圖像distorted_image = tf.image.random_flip_left_right(distorted_image)# 使用一種隨機的順序調整圖像的色彩distorted_image = distort_color(distorted_image, np.random.randint(2))return distorted_image# 3. 讀取圖片 image_raw_data = tf.gfile.FastGFile("E:\\Opencv Image\\dog.jpg", "rb").read() with tf.Session() as sess:img_data = tf.image.decode_jpeg(image_raw_data)boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])# 運行6次獲得6種不同的圖像for i in range(6):result = preprocess_for_train(img_data, 299, 299, boxes)plt.imshow(result.eval())plt.show()
7.3 多線程輸入數據處理框架
上述的預處理方法可以減小無關因素對圖像識別模型效果的影響,但這些復雜的操作會減慢整個訓練過程,為了避免預處理帶來的影響,TensorFlow提供了多線程處理輸入數據的框架。
經典輸入數據處理流程圖
7.3.1 隊列與多線程
隊列是計算圖上“有狀態”的節點,其他節點可以修改其內容,也就是其他隊列可以把新元素插入到隊列后端(rear),也可以將隊列前端(front)的元素刪除。
1. TensorFlow中提供了 FIFOQueue 和 RandomShuffleQueue 兩種隊列
對于隊列來說,修改隊列狀態的操作主要有Enqueue、EnqueueMany、Dequeue,他們需要獲取隊列指針,而非普通的值,如此才能修改隊列內容,在python API中,它們就是隊列的方法,例如:q.enqueue()
EnqueueMany:隊列的初始化
Dequeue:出隊
Enqueue:入隊
- FIFOQueue——先進先出隊列
輸出:
# 隊列開始有[0,10]兩個元素,第一個出隊的為0,加1之后再次入隊得到的隊列為[10,1]; # 第二次出隊的為10,加1之后為11,得到的隊列為[1,11]...0 10 1 11 2RandomShuffleQueue——會將隊列中的元素打亂,每次出隊列操作得到的是當前隊列中的隨機某個元素
神經網絡訓練中更希望使用的訓練數據盡量隨機,所以該方法更多用。
2. 隊列的作用
- 如上所示,隊列是一種數據結構
- 同時也是異步張量取值的一個重要機制(如多個線程可以同時向一個隊列中寫元素,或者同時讀取一個隊列中的元素)
3. 多線程協同功能
tf.Coordinator、tf.QueueRunner兩個類來完成多線程協同的功能
- tf.Coordinator主要用于協同多個線程一起停止(并提供了should_stop、request_stop、join三個函數)
工作過程:
- 聲明一個tf.Coordinator的類,并將該類傳入每一個創建的線程中去
- 啟動的線程要一直查詢should_stop函數,為True時當前線程需要退出
- 每一個啟動的線程都可以通過調用request_stop函數來通知其他線程退出(當一個線程調用request_stop函數時,should_stop函數就好被設置為True,這樣其他線程就可以同時終止)
輸出:
working on id: 0 working on id: 1 working on id: 2 working on id: 3 working on id: 4 working on id: 0 working on id: 3 working on id: 2 working on id: 1 working on id: 4 working on id: 3 working on id: 0 working on id: 2 working on id: 4 working on id: 1 stop from id: 4當所有線程啟動后,每個線程會打印各自的ID,于是前4行打印了它們的ID,暫停1s之后,所有的線程將會第二遍打印ID。
- tf.QueueRunner主要用于啟動多個線程來操作同一個隊列
啟動的所有線程可以通過tf.Coordinator類來同一管理
下列代碼展示了如何使用來管理多線程隊列操作
輸出:
-0.574549 1.83348 -0.675787.3.2 輸入文件隊列
本節介紹如何使用TensorFlow中的隊列管理輸入文件列表
雖然一個TFRecord文件可以存儲多個訓練樣本,但當訓練數據量較大時,可以將數據分成多個TFRecord文件來提高處理效率。
進行有效的管理:tf.train.string_input_producer
該函數會使用初始化時提供的文件列表創建一個輸入隊列,輸入隊列中的原始元素為文件列表中的所有文件,創建好的輸入隊列可以作為文件讀取函數的參數,每層調用文件讀取函數時,該函數會先判斷當前是否已經有打開的文件可讀,如果沒有或者打開的文件已經讀完,則該函數會從輸入隊列中出隊一個文件并從該文件中讀取數據。
當shuffle=True時,文件在加入隊列之前會被打亂順序,所以出隊順序也是隨機的;
- 隨機打亂文件順序以及加入輸入隊列的過程是一個單獨的線程,不會影響獲取文件的速度。
- 當輸入隊列中的所有文件都被處理完之后,會將初始化時提供的文件列表中的文件全部重新加入隊列。
num_epochs:限制加載初始文件列表的最大輪數
- 當設置為1時,計算完一輪之后,程序將自動停止。
- 神經網絡模型測試時,所有測試數據僅僅需要使用一次即可,所以將其設置為1。
生成樣例數據的簡單程序:
import tensorflow as tf# 創建TFRecord幫助函數 def _int64_feature(value):return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) # 模擬海量數據CIA將數據寫入不同的文件 # num_shards 定義了總共寫入多少個文件 # instances_per_shard定義了每個文件中有多少個數據 num_shards=2 instances_per_shard=2 for i in range(num_shards):# 將數據分為多個文件時,可以將不同文件以類似0000n-of-0000m的后綴區分# m:表示數據總共被存在了多少個文件中# n:表示當前文件的編號# 式樣的方式既方便了通過正則表達式獲取文件列表,又在文件名中加入了更多的信息filename=("E:\\Opencv Image\\data.tfrecords-%.5d-of-%.5d" % (i,num_shards))writer=tf.python_io.TFRecordWriter(filename)# 將數據封裝改成example結構并寫入TFRecord文件for j in range(instances_per_shard):# example結構僅包含當前樣例屬于第幾個文件以及是當前文件的第幾個樣本example=tf.train.Example(features=tf.train.Features(feature={'i':_int64_feature(i),'j':_int64_feature(j)}))writer.write(example.SerializeToString())writer.close()程序運行之后,會在指定目錄下生成兩個文件:
每個文件存儲了兩個樣例,生成樣例之后,以下代碼展示了兩個函數的使用方法
輸出:
[b'E:\\pycharm\\TensorFlow chap7\\data.tfrecords-00000-of-00002'b'E:\\pycharm\\TensorFlow chap7\\data.tfrecords-00001-of-00002'] [0, 0] [0, 1] [1, 0] [1, 1] [0, 0] [0, 1]7.3.3 組合訓練數據(batching)
將多個輸入樣例組織成一個batch可以提高模型訓練的效率,所以在得到單個樣例的預處理結果之后,還需要將其組織成batch,再提供給神經網絡的輸入層。
1. tf.train.batch:可以將樣例組織成batch會生成一隊列,隊列的入隊操作是生成單個樣例的方法,每次出隊會得到一個樣例。
2. tf.train.shuffle_batch:可以交給你樣例組織成batch,會生成一隊列,隊列的入隊操作是生成單個樣例的方法,每次出隊會得到一個樣例,但是tf.train.shuffle_batch函數會將數據順序打亂。
- tf.train.batch代碼示例:
輸出:
[0 0 1] [0 1 0] [1 0 0] [1 0 1] # tf.train.batch 函數可以將單個的數據組織成3個一組的batch # 在example,lable中讀到的數據依次為: example:0, lable:0 example:0, lable:1 example:1, lable:0 example:1, lable:1 # 這是因為函數不會隨機打亂順序,所以組合之后得到的數據組合成了上面給出的輸出- tf.train.shuffle_batch代碼示例如下:
輸出:
[0 1 1] [0 1 0] [1 0 0] [0 0 1]7.3.4 輸入數據處理框架
本節給出以上步驟整合之后的代碼
框架主要是三方面的內容:
- TFRecord 輸入數據格式
- 圖像數據處理
- 多線程輸入數據處理
以下代碼只是描繪了一個輸入數據處理的框架,需要根據實際使用環境進行修改
import tensorflow as tf# 創建文件列表 files = tf.train.match_filenames_once("E:\\pycharm\\TensorFlow chap7\\data.tfrecords-*")# 創建輸入文件隊列 filename_queue = tf.train.string_input_producer(files, shuffle=False)# 解析數據。假設image是圖像數據,label是標簽,height、width、channels給出了圖片的維度 reader = tf.TFRecordReader() _, serialized_example = reader.read(filename_queue) features = tf.parse_single_example(serialized_example,features={'image': tf.FixedLenFeature([], tf.string),'label': tf.FixedLenFeature([], tf.int64),'height': tf.FixedLenFeature([], tf.int64),'width': tf.FixedLenFeature([], tf.int64),'channels': tf.FixedLenFeature([], tf.int64)}) image, label = features['image'], features['label'] height, width = features['height'], features['width'] channels = features['channels']# 從原始圖像中解析出像素矩陣,并還原圖像 decoded_image = tf.decode_raw(image, tf.uint8) decoded_image.set_shape([height, width, channels])# 定義神經網絡輸入層圖片的大小 image_size = 299# preprocess_for_train函數是對圖片進行預處理的函數 distorted_image = preprocess_for_train(decoded_image, image_size, image_size,None)# 組合成batch min_after_dequeue = 10000 batch_size = 100 capacity = min_after_dequeue + 3 * batch_size image_batch, label_batch = tf.train.shuffle_batch([distorted_image, label],batch_size=batch_size,capacity=capacity,min_after_dequeue=min_after_dequeue)# 定義神經網絡的結構及優化過程 logit = inference(image_batch) loss = calc_loss(logit, label_batch) train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)with tf.Session() as sess:sess.run([tf.global_variables_initializer(),tf.local_variables_initializer()])coord = tf.train.Coordinator()threads = tf.train.start_queue_runners(coord=coord)# 神經網絡訓練過程for i in range(TRAINING_ROUNDS):sess.run(train_step)coord.request_stop()coord.join()總結
對于輸入數據的處理,大體上流程都差不多,可以歸結如下:
上圖就是以上代碼中輸入數據處理的全部流程
總結
以上是生活随笔為你收集整理的TensorFlow:实战Google深度学习框架(六)图像数据处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 济南一辆理想L9车头当街起火 官方回应:
- 下一篇: 梳理百年深度学习发展史-七月在线机器学习