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 相关文章推荐
SublimeText 2编译python出错的解决方法(The system cannot find the file specified)
Nov 27 Python
谈谈Python进行验证码识别的一些想法
Jan 25 Python
解决Mac下首次安装pycharm无project interpreter的问题
Oct 29 Python
Python实现代码统计工具
Sep 19 Python
深入浅析python的第三方库pandas
Feb 13 Python
JupyterNotebook 输出窗口的显示效果调整方法
Apr 13 Python
Python内置异常类型全面汇总
May 28 Python
在Pytorch中使用Mask R-CNN进行实例分割操作
Jun 24 Python
django序列化时使用外键的真实值操作
Jul 15 Python
python字典通过值反查键的实现(简洁写法)
Sep 30 Python
python中K-means算法基础知识点
Jan 25 Python
使用Python解决图表与画布的间距问题
Apr 11 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
javascript之卸载鼠标事件的代码
2007/05/14 Javascript
Jquery 扩展方法
2010/05/06 Javascript
Extjs改变树节点的勾选状态点击按钮将复选框去掉
2013/11/14 Javascript
document.compatMode的CSS1compat使用介绍
2014/04/03 Javascript
JS基于VML技术实现的五角星礼花效果代码
2015/10/26 Javascript
详解JavaScript节流函数中的Throttle
2016/07/16 Javascript
漂亮实用的页面loading(加载)封装代码
2017/02/03 Javascript
为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题
2018/04/03 Javascript
详解IOS微信上Vue单页面应用JSSDK签名失败解决方案
2018/11/14 Javascript
原生js实现移动端Touch轮播图的方法步骤
2019/01/03 Javascript
vue-cli history模式实现tomcat部署报404的解决方式
2019/09/06 Javascript
vue+render+jsx实现可编辑动态多级表头table的实例代码
2020/04/01 Javascript
vue实现简易的双向数据绑定
2020/12/29 Vue.js
[06:10]6.81新信使新套装!给你一个炫酷的DOTA2
2014/05/06 DOTA
Python 调用DLL操作抄表机
2009/01/12 Python
python简单实现基数排序算法
2015/05/16 Python
Python装饰器使用实例:验证参数合法性
2015/06/24 Python
遍历python字典几种方法总结(推荐)
2016/09/11 Python
python的多重继承的理解
2017/08/06 Python
python中append实例用法总结
2019/07/30 Python
Django实现WebSSH操作物理机或虚拟机的方法
2019/11/06 Python
python else语句在循环中的运用详解
2020/07/06 Python
Python如何使用ElementTree解析xml
2020/10/12 Python
HTML5 MiranaVideo播放器 (代码开源)
2010/06/11 HTML / CSS
eVitamins日本:在线购买折扣维生素、补品和草药
2019/04/04 全球购物
俄罗斯名牌服装网上商店:UNIQUE FABRIC
2019/07/25 全球购物
社区中秋节活动方案
2014/01/29 职场文书
房产转让协议书
2014/04/11 职场文书
大学生撤销处分思想汇报
2014/09/12 职场文书
涉外离婚协议书怎么写
2014/11/20 职场文书
民事和解协议书格式
2014/11/29 职场文书
新员工试用期工作总结2015
2015/05/28 职场文书
2016感恩父亲节主题广播稿
2015/12/18 职场文书
HTML基础详解(上)
2021/10/16 HTML / CSS
Java中的随机数Random
2022/03/17 Java/Android
Spring Boot 的创建和运行示例代码详解
2022/07/23 Java/Android