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的Flask框架中实现简单的登录功能的教程
Apr 20 Python
python通过ssh-powershell监控windows的方法
Jun 02 Python
详解python的几种标准输出重定向方式
Aug 15 Python
python urllib urlopen()对象方法/代理的补充说明
Jun 29 Python
Python基于Matplotlib库简单绘制折线图的方法示例
Aug 14 Python
python将txt文件读取为字典的示例
Dec 22 Python
详解Python的循环结构知识点
May 20 Python
python+tifffile之tiff文件读写方式
Jan 13 Python
Python unittest装饰器实现原理及代码
Sep 08 Python
Windows环境下Python3.6.8 importError: DLLload failed:找不到指定的模块
Nov 01 Python
python+openCV对视频进行截取的实现
Nov 27 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
Jan 21 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 simple_html_dom.php+正则 采集文章代码
2009/12/24 PHP
php学习之function的用法
2012/07/14 PHP
PHP 类相关函数的使用详解
2013/05/10 PHP
PHP查询快递信息的方法
2015/03/07 PHP
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
jquery中ajax调用json数据的使用说明
2011/03/17 Javascript
三级下拉菜单的js实现代码
2011/05/23 Javascript
ExtJs中gridpanel分组后组名排序实例代码
2013/12/02 Javascript
Javascript的setTimeout()使用闭包特性时需要注意的问题
2014/09/23 Javascript
JavaScript中用getDate()方法返回指定日期的教程
2015/06/09 Javascript
JS实现DIV容器赋值的方法
2015/12/14 Javascript
JSON简介以及用法汇总
2016/02/21 Javascript
Angular4实现图片上传预览路径不安全的问题解决
2017/12/25 Javascript
使用 Vue 绑定单个或多个 Class 名的实例代码
2018/01/08 Javascript
vue+mousemove实现鼠标拖动功能(拖动过快失效问题解决方法)
2018/08/24 Javascript
微信小程序 简易计算器实现代码实例
2019/09/02 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
2019/09/17 Javascript
[03:36]2014DOTA2 TI小组赛综述 八强诞生进军钥匙球馆
2014/07/15 DOTA
Python学习之用pygal画世界地图实例
2017/12/07 Python
如何利用python查找电脑文件
2018/04/27 Python
利用Anaconda简单安装scrapy框架的方法
2018/06/13 Python
python使用PIL给图片添加文字生成海报示例
2018/08/17 Python
Python利用ORM控制MongoDB(MongoEngine)的步骤全纪录
2018/09/13 Python
python实现电子书翻页小程序
2019/07/23 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
2020版Python学习路线图(附学习资料)
2020/09/15 Python
Farfetch澳大利亚官网:Farfetch Australia
2020/04/26 全球购物
Java如何调用外部Exe程序
2015/07/04 面试题
物流专业大学生求职信范文
2013/10/28 职场文书
五年级数学教学反思
2014/02/11 职场文书
2014年乡镇安全生产工作总结
2014/12/02 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
钢琴师观后感
2015/06/12 职场文书
增值税发票丢失证明
2015/06/19 职场文书
CSS3点击按钮圆形进度打钩效果的实现代码
2021/03/30 HTML / CSS
PHP 技巧 * SVG 保存为图片(分享图生成)
2021/04/02 PHP