TFRecord格式存储数据与队列读取实例


Posted in Python onJanuary 21, 2020

Tensor Flow官方网站上提供三种读取数据的方法

1. 预加载数据:在Tensor Flow图中定义常量或变量来保存所有数据,将数据直接嵌到数据图中,当训练数据较大时,很消耗内存。

x1=tf.constant([0,1])
x2=tf.constant([1,0])
y=tf.add(x1,x2)

2.填充数据:使用sess.run()的feed_dict参数,将Python产生的数据填充到后端,之前的MNIST数据集就是通过这种方法。也有消耗内存,数据类型转换耗时的缺点。

3. 从文件读取数据:从文件中直接读取,让队列管理器从文件中读取数据。分为两步

先把样本数据写入TFRecords二进制文件

再从队列中读取

TFRecord是TensorFlow提供的一种统一存储数据的二进制文件,能更好的利用内存,更方便的复制和移动,并且不需要单独的标记文件。下面通过代码来将MNIST转换成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]))
def convert_to(data_set,name):
 '''
 将数据填入到tf.train.Example的协议缓冲区(protocol buffer)中,将协议缓冲区序列
 化为一个字符串,通过tf.python_io.TFRecordWriter写入TFRecords文件 
 '''
 images=data_set.images
 labels=data_set.labels
 num_examples=data_set.num_examples
 if images.shape[0]!=num_examples:
  raise ValueError ('Imagessize %d does not match label size %d.'\
       %(images.shape[0],num_examples))
 rows=images.shape[1] #28
 cols=images.shape[2] #28
 depth=images.shape[3] #1 是黑白图像

 filename = os.path.join(FLAGS.directory, name + '.tfrecords')
 #使用下面语句就会将三个文件存储为一个TFRecord文件,当数据量较大时,最好将数据写入多个文件
 #filename="C:/Users/dbsdz/Desktop/TF练习/TFRecord"
 print('Writing',filename)
 writer=tf.python_io.TFRecordWriter(filename)
 for index in range(num_examples):
  image_raw=images[index].tostring() #将图像矩阵化为一个字符串

  #写入协议缓冲区,height、width、depth、label编码成int 64类型,image——raw编码成二进制
  example=tf.train.Example(features=tf.train.Features(feature={
    'height':_int64_feature(rows),
    'width':_int64_feature(cols),
    'depth':_int64_feature(depth),
    'label':_int64_feature(int(labels[index])),
    'image_raw':_bytes_feature(image_raw)}))
  writer.write(example.SerializeToString())  #序列化字符串
 writer.close()

上面程序可以将MNIST数据集中所有的训练数据存储到三个TFRecord文件中。结果如下图

TFRecord格式存储数据与队列读取实例

从队列中TFRecord文件,过程分三步

1. 创建张量,从二进制文件中读取一个样本

2. 创建张量,从二进制文件中随机读取一个mini-batch

3. 把每一批张量传入网络作为输入节点

具体代码如下

def read_and_decode(filename_queue):  #输入文件名队列
 reader=tf.TFRecordReader()
 _,serialized_example=reader.read(filename_queue)
 #解析一个example,如果需要解析多个样例,使用parse_example函数
 features=tf.parse_single_example( 
   serialized_example,
   #必须写明feature里面的key的名称
   features={
   #TensorFlow提供两种不同的属性解析方法,一种方法是tf.FixedLenFeature,  
   #这种方法解析的结果为一个Tensor。另一个方法是tf.VarLenFeature,
   #这种方法得到的解析结果为SparseTensor,用于处理稀疏数据。
   #这里解析数据的格式需要和上面程序写入数据的格式一致
     'image_raw':tf.FixedLenFeature([],tf.string),#图片是string类型
      'label':tf.FixedLenFeature([],tf.int64), #标记是int64类型
      })
 #对于BytesList,要重新进行编码,把string类型的0维Tensor变成uint8类型的一维Tensor
 image = tf.decode_raw(features['image_raw'], tf.uint8)
 image.set_shape([IMAGE_PIXELS])
 #tensor("input/DecodeRaw:0",shape=(784,),dtype=uint8)

 #image张量的形状为:tensor("input/sub:0",shape=(784,),dtype=float32)
 image = tf.cast(image, tf.float32) * (1. / 255) - 0.5

 #把标记从uint8类型转换为int32类性
 #label张量的形状为tensor(“input/cast_1:0",shape=(),dtype=int32)
 label = tf.cast(features['label'], tf.int32)
 return image,label
def inputs(train,batch_size,num_epochs):
 #输入参数:
 #train:选择输入训练数据/验证数据
 #batch_size:训练的每一批有多少个样本
 #num_epochs:过几遍数据,设置为0/None表示永远训练下去
 '''
 返回结果: A tuple (images,labels)
 *images:类型为float,形状为【batch_size,mnist.IMAGE_PIXELS],范围【-0.5,0.5】。
 *label:类型为int32,形状为【batch_size],范围【0,mnist.NUM_CLASSES]
 注意tf.train.QueueRunner必须用tf.train.start_queue_runners()来启动线程

 '''
 if not num_epochs:num_epochs=None
 #获取文件路径,即./MNIST_data/train.tfrecords,./MNIST_data/validation.records
 filename=os.path.join(FLAGS.train_dir,TRAIN_FILE if train else VALIDATION_FILE)
 with tf.name_scope('input'):
  #tf.train.string_input_producer返回一个QueueRunner,里面有一个FIFOQueue
  filename_queue=tf.train.string_input_producer(#如果样本量很大,可以分成若干文件,把文件名列表传入
    [filename],num_epochs=num_epochs)  
  image,label=read_and_decode(filename_queue)
  #随机化example,并把它们整合成batch_size大小
  #tf.train.shuffle_batch生成了RandomShuffleQueue,并开启两个线程
  images,sparse_labels=tf.train.shuffle_batch(
    [image,label],batch_size=batch_size,num_threads=2,
    capacity=1000+3*batch_size,
    min_after_dequeue=1000) #留下一部分队列,来保证每次有足够的数据做随机打乱
  return images,sparse_labels

最后,构建一个三层的神经网络,包含两层卷积层以及一层使用SoftMax层,附上完整代码如下

# -*- coding: utf-8 -*-
"""
Created on Sun Apr 8 11:06:16 2018

@author: dbsdz

https://blog.csdn.net/xy2953396112/article/details/54929073
"""
import tensorflow as tf
import os
import time
import math
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)


# Basic model parameters as external flags. 
flags = tf.app.flags 
flags.DEFINE_float('learning_rate', 0.01, 'Initial learning rate.') 
flags.DEFINE_integer('hidden1', 128, 'Number of units in hidden layer 1.') 
flags.DEFINE_integer('hidden2', 32, 'Number of units in hidden layer 2.') 
flags.DEFINE_integer('batch_size', 100, 'Batch size. ' 
      'Must divide evenly into the dataset sizes.') 
flags.DEFINE_string('train_dir', 'Mnist_data/', 'Directory to put the training data.') 
flags.DEFINE_string('directory', './MNIST_data',
       'Directory to download data files and write the '
       'converted result')
flags.DEFINE_integer('validation_size', 5000,
       'Number of examples to separate from the training '
       'data for the validation set.')
flags.DEFINE_integer('num_epochs',10,'num_epochs set')
FLAGS = tf.app.flags.FLAGS
IMAGE_SIZE = 28
IMAGE_PIXELS = IMAGE_SIZE * IMAGE_SIZE  #图片像素728
TRAIN_FILE = "train.tfrecords"
VALIDATION_FILE="validation.tfrecords"
#生成整数型的属性
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]))
def convert_to(data_set,name):
 '''
 将数据填入到tf.train.Example的协议缓冲区(protocol buffer)中,将协议缓冲区序列
 化为一个字符串,通过tf.python_io.TFRecordWriter写入TFRecords文件 
 '''
 images=data_set.images
 labels=data_set.labels
 num_examples=data_set.num_examples
 if images.shape[0]!=num_examples:
  raise ValueError ('Imagessize %d does not match label size %d.'\
       %(images.shape[0],num_examples))
 rows=images.shape[1] #28
 cols=images.shape[2] #28
 depth=images.shape[3] #1 是黑白图像

 filename = os.path.join(FLAGS.directory, name + '.tfrecords')
 #使用下面语句就会将三个文件存储为一个TFRecord文件,当数据量较大时,最好将数据写入多个文件
 #filename="C:/Users/dbsdz/Desktop/TF练习/TFRecord"
 print('Writing',filename)
 writer=tf.python_io.TFRecordWriter(filename)
 for index in range(num_examples):
  image_raw=images[index].tostring() #将图像矩阵化为一个字符串

  #写入协议缓冲区,height、width、depth、label编码成int 64类型,image——raw编码成二进制
  example=tf.train.Example(features=tf.train.Features(feature={
    'height':_int64_feature(rows),
    'width':_int64_feature(cols),
    'depth':_int64_feature(depth),
    'label':_int64_feature(int(labels[index])),
    'image_raw':_bytes_feature(image_raw)}))
  writer.write(example.SerializeToString())  #序列化字符串
 writer.close()


def inference(images, hidden1_units, hidden2_units):
 with tf.name_scope('hidden1'):
 weights = tf.Variable(
  tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
       stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),name='weights')
 biases = tf.Variable(tf.zeros([hidden1_units]),name='biases')
 hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
 with tf.name_scope('hidden2'):
 weights = tf.Variable(
  tf.truncated_normal([hidden1_units, hidden2_units],
       stddev=1.0 / math.sqrt(float(hidden1_units))),
  name='weights')
 biases = tf.Variable(tf.zeros([hidden2_units]),
       name='biases')
 hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
 with tf.name_scope('softmax_linear'):
 weights = tf.Variable(
  tf.truncated_normal([hidden2_units,FLAGS.num_epochs],
       stddev=1.0 / math.sqrt(float(hidden2_units))),name='weights')
 biases = tf.Variable(tf.zeros([FLAGS.num_epochs]),name='biases')
 logits = tf.matmul(hidden2, weights) + biases
 return logits
def lossFunction(logits, labels):
 labels = tf.to_int64(labels)
 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
  logits=logits, labels=labels, name='xentropy')
 loss = tf.reduce_mean(cross_entropy, name='xentropy_mean')
 return loss
def training(loss, learning_rate):
 tf.summary.scalar(loss.op.name, loss)
 optimizer = tf.train.GradientDescentOptimizer(learning_rate)
 global_step = tf.Variable(0, name='global_step', trainable=False)
 train_op = optimizer.minimize(loss, global_step=global_step)
 return train_op
def read_and_decode(filename_queue):  #输入文件名队列
 reader=tf.TFRecordReader()
 _,serialized_example=reader.read(filename_queue)
 #解析一个example,如果需要解析多个样例,使用parse_example函数
 features=tf.parse_single_example( 
   serialized_example,
   #必须写明feature里面的key的名称
   features={
   #TensorFlow提供两种不同的属性解析方法,一种方法是tf.FixedLenFeature,  
   #这种方法解析的结果为一个Tensor。另一个方法是tf.VarLenFeature,
   #这种方法得到的解析结果为SparseTensor,用于处理稀疏数据。
   #这里解析数据的格式需要和上面程序写入数据的格式一致
     'image_raw':tf.FixedLenFeature([],tf.string),#图片是string类型
      'label':tf.FixedLenFeature([],tf.int64), #标记是int64类型
      })
 #对于BytesList,要重新进行编码,把string类型的0维Tensor变成uint8类型的一维Tensor
 image = tf.decode_raw(features['image_raw'], tf.uint8)
 image.set_shape([IMAGE_PIXELS])
 #tensor("input/DecodeRaw:0",shape=(784,),dtype=uint8)

 #image张量的形状为:tensor("input/sub:0",shape=(784,),dtype=float32)
 image = tf.cast(image, tf.float32) * (1. / 255) - 0.5

 #把标记从uint8类型转换为int32类性
 #label张量的形状为tensor(“input/cast_1:0",shape=(),dtype=int32)
 label = tf.cast(features['label'], tf.int32)
 return image,label

def inputs(train,batch_size,num_epochs):
 #输入参数:
 #train:选择输入训练数据/验证数据
 #batch_size:训练的每一批有多少个样本
 #num_epochs:过几遍数据,设置为0/None表示永远训练下去
 '''
 返回结果: A tuple (images,labels)
 *images:类型为float,形状为【batch_size,mnist.IMAGE_PIXELS],范围【-0.5,0.5】。
 *label:类型为int32,形状为【batch_size],范围【0,mnist.NUM_CLASSES]
 注意tf.train.QueueRunner必须用tf.train.start_queue_runners()来启动线程

 '''
 if not num_epochs:num_epochs=None
 #获取文件路径,即./MNIST_data/train.tfrecords,./MNIST_data/validation.records
 filename=os.path.join(FLAGS.train_dir,TRAIN_FILE if train else VALIDATION_FILE)
 with tf.name_scope('input'):
  #tf.train.string_input_producer返回一个QueueRunner,里面有一个FIFOQueue
  filename_queue=tf.train.string_input_producer(#如果样本量很大,可以分成若干文件,把文件名列表传入
    [filename],num_epochs=num_epochs)  
  image,label=read_and_decode(filename_queue)
  #随机化example,并把它们整合成batch_size大小
  #tf.train.shuffle_batch生成了RandomShuffleQueue,并开启两个线程
  images,sparse_labels=tf.train.shuffle_batch(
    [image,label],batch_size=batch_size,num_threads=2,
    capacity=1000+3*batch_size,
    min_after_dequeue=1000) #留下一部分队列,来保证每次有足够的数据做随机打乱
  return images,sparse_labels
def run_training():
 with tf.Graph().as_default():
  #输入images和labels
  images,labels=inputs(train=True,batch_size=FLAGS.batch_size,
        num_epochs=3)  #num_epochs就是训练的轮数 
  #构建一个从推理模型来预测数据的图
  logits=inference(images,FLAGS.hidden1,FLAGS.hidden2)
  loss=lossFunction(logits,labels) #定义损失函数
  #Add to the Graph operations that train the model
  train_op=training(loss,FLAGS.learning_rate)
  #初始化参数,特别注意:string——input_producer内部创建了一个epoch计数变量
  #归入tf.graphkey.local_variables集合中,必须单独用initialize_local_variables()初始化
  init_op=tf.group(tf.global_variables_initializer(),
       tf.local_variables_initializer())
  sess=tf.Session()
  sess.run(init_op)
  #Start input enqueue threads
  coord =tf.train.Coordinator()
  threads=tf.train.start_queue_runners(sess=sess,coord=coord)
  try:
   step=0
   while not coord.should_stop(): #进入永久循环
    start_time=time.time()
    _,loss_value=sess.run([train_op,loss])

    #每100次训练输出一次结果
    if step % 100 ==0:
     duration=time.time()-start_time
     print('Step %d: loss=%.2f (%.3f sec)'%(step,loss_value,duration))
    step+=1
  except tf.errors.OutOfRangeError:
   print('Done training for %d epochs,%d steps.'%(FLAGS.num_epochs,step))
  finally:
   coord.request_stop()#通知其他线程关闭
  coord.join(threads)
  sess.close()

def main(unused_argv):

 #获取数据
 data_sets=input_data.read_data_sets(FLAGS.directory,dtype=tf.uint8,reshape=False,
         validation_size=FLAGS.validation_size)

 #将数据转换成tf.train.Example类型,并写入TFRecords文件

 convert_to(data_sets.train,'train')

 convert_to(data_sets.validation,'validation')

 convert_to(data_sets.test,'test')
 print('convert finished')
 run_training()

if __name__ == '__main__':
 tf.app.run()

运行结果如图

TFRecord格式存储数据与队列读取实例

以上这篇TFRecord格式存储数据与队列读取实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python使用py2exe打包程序介绍
Nov 20 Python
pygame学习笔记(5):游戏精灵
Apr 15 Python
Python 中 Meta Classes详解
Feb 13 Python
致Python初学者 Anaconda入门使用指南完整版
Apr 05 Python
spark: RDD与DataFrame之间的相互转换方法
Jun 07 Python
Python使用sqlalchemy模块连接数据库操作示例
Mar 13 Python
梅尔频率倒谱系数(mfcc)及Python实现
Jun 18 Python
python and or用法详解
Jun 26 Python
python3利用Axes3D库画3D模型图
Mar 25 Python
Python matplotlib画图时图例说明(legend)放到图像外侧详解
May 16 Python
使用OpenCV实现人脸图像卡通化的示例代码
Jan 15 Python
详解Python中的Lock和Rlock
Jan 26 Python
TensorFlow dataset.shuffle、batch、repeat的使用详解
Jan 21 #Python
使用 tf.nn.dynamic_rnn 展开时间维度方式
Jan 21 #Python
python爬取本站电子书信息并入库的实现代码
Jan 20 #Python
浅谈Tensorflow 动态双向RNN的输出问题
Jan 20 #Python
关于tf.nn.dynamic_rnn返回值详解
Jan 20 #Python
双向RNN:bidirectional_dynamic_rnn()函数的使用详解
Jan 20 #Python
关于tf.reverse_sequence()简述
Jan 20 #Python
You might like
用PHP为SHOPEX增加日志功能代码
2010/07/02 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
js控制页面控件隐藏显示的两种方法介绍
2013/10/09 Javascript
javascript 操作符(~、&、|、^、)使用案例
2014/12/31 Javascript
node.js 使用ejs模板引擎时后缀换成.html
2015/04/22 Javascript
JS实现具备延时功能的滑动门菜单效果
2015/09/17 Javascript
jquery.validate 自定义验证方法及validate相关参数
2016/01/18 Javascript
Ionic实现仿通讯录点击滑动及$ionicscrolldelegate使用分析
2016/01/18 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
Bootstrap 3的box-sizing样式导致UEditor控件的图片无法正常缩放的解决方案
2016/09/15 Javascript
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
Bootstrap组件之下拉菜单,多级菜单及按钮布局方法实例
2017/05/25 Javascript
JS实现自定义状态栏动画文字效果示例
2017/10/12 Javascript
JS实现div模块的截图并下载功能
2017/10/17 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
2019/09/02 Javascript
nodejs文件夹深层复制功能
2019/09/03 NodeJs
vue 中this.$set 动态绑定数据的案例讲解
2021/01/29 Vue.js
Python pickle模块用法实例分析
2015/05/27 Python
Python操作SQLite数据库的方法详解
2017/06/16 Python
Python中应该使用%还是format来格式化字符串
2018/09/25 Python
浅析python的Lambda表达式
2019/02/27 Python
对Python 简单串口收发GUI界面的实例详解
2019/06/12 Python
Django 模型类(models.py)的定义详解
2019/07/19 Python
10行Python代码计算汽车数量的实现方法
2019/10/23 Python
TensorFlow设置日志级别的几种方式小结
2020/02/04 Python
Python API 操作Hadoop hdfs详解
2020/06/06 Python
10张动图学会python循环与递归问题
2021/02/06 Python
python解决OpenCV在读取显示图片的时候闪退的问题
2021/02/23 Python
浅谈css3中的前缀
2016/07/20 HTML / CSS
HTML5 新标签全部总汇(推荐)
2016/06/13 HTML / CSS
美国著名的户外用品品牌:L.L.Bean
2018/01/05 全球购物
一年级小学生评语
2014/04/22 职场文书
玄武湖导游词
2015/02/05 职场文书
幼儿园卫生保健制度
2015/08/05 职场文书
MySQL图形化管理工具Navicat安装步骤
2021/12/04 MySQL
SQL Server #{}可以防止SQL注入
2022/05/11 SQL Server