TFRecord格式存储数据与队列读取实例
程序员文章站
2022-10-11 20:46:16
tensor flow官方网站上提供三种读取数据的方法
1. 预加载数据:在tensor flow图中定义常量或变量来保存所有数据,将数据直接嵌到数据图中,当训练数据较大时,很消耗...
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文件,过程分三步
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格式存储数据与队列读取实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。