从TFRrecord文件中多线程的读取数据
从这一篇开始,要啃一些硬骨头了,不过掌握这一篇的内容就等于是掌握了深度学习中最重要的内容之一了
1. TFRecord文件介绍
前一篇我们已经获取了用于训练和测试的数据,这些数据需要生成一个一个的mini-batch喂给神经网络让它学习,我们希望这个mini-batch能快速产生,而且每一个mini-batch中image和label必须要互相对应(错误的label,网络必然学到错误的结果),与此同时,我们还希望这个batch是乱序的。出于这些要求,我们选用从TFRecord文件中多线程的读取数据的方式来产生mini-batch。(这是TensorFlow为解决数据导入而设计的标准方式)
TFRecord文件中将数据通过tf.train.Example Protocol Buffer的格式存储,实际上就是一个数据打包的过程,我们的一组数据应该包括一幅转置后的图(image)和一幅没有转置的图(label),同时这些图还有行数,列数,通道数等属性,对于分类问题可能还有类别,我们通过tf.train.Example Protocol Buffer格式,将同一组的相关属性打包,这样就整合了同一组数据中不同类型不同大小的属性封装到一起,这样给我们的管理数据带来了极大的便利。每一组打包好的数据结构中,都包含了一个从属性名称到取值的字典,其中属性名称是一个字符串,属性的取值可以为字符串,实数列表或者整数列表。对于本系列博客将要处理的问题,图片都是28x28的灰度图像,我们只需将image和与之对应的label封装到一起,属性名称分别为‘image’和‘label’,属性取值为对应图像的像素值,每一幅图片的尺寸和通道都是固定的,就不用打包了。
2. 生成TFRecord文件
为了统一文件路径,在大量写代码之前,我们先统一文件路径吧,我们统一在E盘建一个名为MNIST_data的文件夹,其中有下列子文件夹:
文件夹 | 存放内容 |
---|---|
code | 代码 |
models | 训练好的神经网络模型 |
result | 测试结果 |
TensorBoard | 训练过程可视化文件 |
test_images | 测试数据 |
test_labels | 测试数据理想输出 |
train_images | 训练数据 转置后的图像 |
train_labels | 训练数据 未转置的图像 |
按照,第一部分对TFRecord文件的介绍,我们开始将数据存放到TFRecord文件中。程序如下:(备注:初学的话不要过多的在意代码的细节,知道流程看懂代码就ok啦)拷贝到Spyder或Notebook中运行,代码估计需要好几分钟,可以歇会儿了。如果报错说找不到PIL包,你知道的吧:activate TensorFlow、 conda install pillow(不知道的话回看第二篇)
import os
import tensorflow as tf
from PIL import Image
image_path = 'E:\\MNIST_data\\train_images\\' # 输入图像的路径
label_path = 'E:\\MNIST_data\\train_labels\\' # 输出图像的路径
TFRecord_path = 'E:\\MNIST_data\\tfrecord\\train_data_set.tfrecord'# 输出TFRecord文件的路径
def _bytes_feature(value): # 生成字符串型的属性,用于存储图片像素信息,根据自己问题的要求选择要存的属性
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
# 将image_path和label_path中的图片一一对应封装在TFRecord_path中
def generate_TFRecordfile(image_path,label_path,TFRecord_path):
images = []
labels = []
for file in os.listdir(image_path):
images.append(image_path+file) # 得到所有转置图像的文件名
for file in os.listdir(label_path):
labels.append(label_path+file) # 得到所有未转置图像的文件名
num_examples = len(images) # 统计有多少用于训练的图片
p