在训练样本的时候,希望读入的训练样本时有序的
tf.FIFOQueue 先进先出队列,按顺序出队列
tf.RandomShuffleQueue 随机出队列
FIFOQueue(capacity, dtypes, name='fifo_queue')
创建一个以先进先出的顺序对元素进行排队的队列
capacity:
整数。可能存储在此队列中的元素数量的上限;
dtypes:
DType对象列表。长度dtypes必须等于每个队列元素中的张量数,dtype的类型形状,决定了后面进队列元素形状。
常用方法:
dequeue(name=None)
enqueue(vals, name=None):
enqueue_many(vals, name=None):vals列表或者元组,返回一个进队列操作
size(name=None)
实例:完成一个出队列、+1、入队列操作(同步操作)
分析:当数据量很大时,入队操作从硬盘中读取数据,放入内存中,主线程需要等待入队操作完成,才能进行训练。会话里可以运行多个线程,实现异步读取。
同步队列实现代码:
import tensorflow as tf
import os
# 1、首先定义队列
Q = tf.FIFOQueue(3,tf.float32)
# 放入一些数据
enq_many = Q.enqueue_many([[0.1,0.2,0.3],])
# 2、取数据的过程:取数据,+1, 入队列
out_q = Q.dequeue()
data = out_q+1
en_q = Q.enqueue(data)
if __name__ == "__main__":
with tf.Session() as sess:
# 初始化队列
sess.run(enq_many)
# 处理数据
for i in range(100):
sess.run(en_q)
# 训练数据
for i in range(Q.size().eval()):
print(sess.run(Q.dequeue()))
tf.train.QueueRunner(queue, enqueue_ops=None)
创建一个QueueRunner
queue:
一个队列
enqueue_ops:
添加线程的队列操作列表,[]*2,指定两个线程
方法:
create_threads(sess, coord=None,start=False)
创建线程来运行给定会话的入队操作
start:
布尔值,如果True启动线程;如果为False调用者必须调用start()启动线程
coord:
线程协调器,后面线程管理需要用到
return:
实例:通过队列管理器来实现变量加1,入队,主线程出队列的操作,是一种异步操作。
分析:这时候有一个问题就是,入队自顾自的去执行,在需要的出队操作完成之后,程序没法结束。需要一个实现线程间的同步,终止其他线程。
tf.train.Coordinator()
线程协调员,实现一个简单的机制来协调一组线程的终止
request_stop()
should_stop()
检查是否要求停止
join(threads=None, stop_grace_period_secs=120)
等待线程终止
return
:线程协调员实例
import tensorflow as tf
# 1、定义一个队列,1000
Q = tf.FIFOQueue(1000,tf.float32)
# 2、定义要做的事情 循环取值,+1, 放入队列当中
var = tf.Variable(0.0)
# 实现一个自增 tf.assign_add
data = tf.assign_add(var,tf.constant(1.0))
en_q = Q.enqueue(data)
# 3、定义队列管理器op, 指定多少个子线程,子线程该干什么事情
qr = tf.train.QueueRunner(Q,enqueue_ops=[en_q]*2)
# 初始化变量的OP
init_op = tf.global_variables_initializer()
if __name__=="__main__":
with tf.Session() as sess:
# 初始化变量
sess.run(init_op)
# 开启线程管理器
coord = tf.train.Coordinator()
# 真正开启子线程
threads = qr.create_threads(sess,coord,start=True)
for i in range(300):
print(sess.run(Q.dequeue()))
# 回收线程
coord.request_stop()
coord.join(threads)
tf.train.string_input_producer(string_tensor,shuffle=True)
将输出字符串(例如文件名)输入到管道队列
string_tensor:
含有文件名的1阶张量
num_epochs:
过几遍数据,默认无限过数据
return:
具有输出字符串的队列
根据文件格式,选择对应的文件阅读器
class tf.TextLineReader
阅读文本文件逗号分隔值(CSV)格式,默认按行读取
return:
读取器实例
tf.FixedLengthRecordReader(record_bytes)
要读取每个记录是固定数量字节的二进制文件
record_bytes:
整型,指定每次读取的字节数
return:
读取器实例
tf.TFRecordReader
读取TfRecords
文件
有一个共同的读取方法:
read(file_queue):
从队列中指定数量内容
返回一个Tensors元组(key文件名字,value默认的内容(行,字节))
由于从文件中读取的是字符串,需要函数去解析这些字符串到张量
tf.decode_csv(records,record_defaults=None,field_delim = None,name = None)
将CSV转换为张量,与tf.TextLineReader搭配使用
records
:tensor型字符串,每个字符串是csv中的记录行
field_delim
:默认分割符”,”
record_defaults:
参数决定了所得张量的类型,并设置一个值在输入字符串中缺少使用默认值
tf.decode_raw(bytes,out_type,little_endian = None,name = None)
将字节转换为一个数字向量表示,字节为一字符串类型的张量,与函数tf.FixedLengthRecordReader搭配使用,二进制读取为uint8格式
tf.train.start_queue_runners(sess=None,coord=None)
收集所有图中的队列线程,并启动线程
sess:所在的会话中
coord:线程协调器
return:返回所有线程队列
如果读取的文件为多个或者样本数量为多个
tf.train.batch(tensors,batch_size,num_threads = 1,capacity = 32,name=None)
读取指定大小(个数)的张量
tensors:
可以是包含张量的列表
batch_size:
从队列中读取的批处理大小
num_threads:
进入队列的线程数
capacity:
整数,队列中元素的最大数量
return:
tensors
tf.train.shuffle_batch(tensors,batch_size,capacity,min_after_dequeue, num_threads=1,)
乱序读取指定大小(个数)的张量
min_after_dequeue:
留下队列里的张量个数,能够保持随机打乱
三要素:长度、宽度、通道数
目的:
1、增加图片数据的统一性
2、所有图片转换成指定大小
3、缩小图片数据量,防止增加开销
操作:
1、缩小图片大小
tf.image.resize_images(images, size)
缩小图片
images:
4-D形状[batch, height, width, channels]或3-D形状的张量[height, width, channels]的图片数据。
size:
1-D int32张量:new_height, new_width,图像的新尺寸,返回4-D格式或者3-D格式图片
图像读取器
tf.WholeFileReader
将文件的全部内容作为值输出的读取器
return
:读取器实例
read(file_queue)
:输出将是一个文件名(key)和该文件的内容(值)
图像解码器
tf.image.decode_jpeg(contents)
将JPEG编码的图像解码为uint8张量
return:uint8
张量,3-D形状[height, width, channels]
tf.image.decode_png(contents)
将PNG编码的图像解码为uint8或uint16张量
return:
张量类型,3-D形状[height, width, channels]
图片批处理案例流程:
(1)构造图片文件队列
(2)构造图片阅读器
(3)读取图片数据
(4)处理图片数据
TFRecords是Tensorflow设计的一种内置文件格式,是一种二进制文件,它能更好的利用内存,更方便复制和移动。
为了将二进制数据和标签(训练的类别标签)数据存储在同一个文件中
文件格式:*.tfrecords
写入文件内容:Example协议块
a 建立TFRecord存储器
tf.python_io.TFRecordWriter(path)
写入tfrecords文件
path:
TFRecords文件的路径
return:
写文件
方法:
write(record):
向文件中写入一个字符串记录
close():
关闭文件写入器
注:字符串为一个序列化的Example,Example.SerializeToString()
b 构造每个样本的Example协议块
tf.train.Example(features=None)
写入tfrecords文件
features:tf.train.Features
类型的特征实例
return:
example格式协议块
tf.train.Features(feature=None)构建每个样本的信息键值对
feature:字典数据,key为要保存的名字,
value为tf.train.Feature实例
return:Features类型
tf.train.Feature(**options)
**options:例如
bytes_list=tf.train. BytesList(value=[Bytes])
int64_list=tf.train. Int64List(value=[Value])
tf.train. Int64List(value=[Value])
tf.train. BytesList(value=[Bytes])
tf.train. FloatList(value=[value])
同文件阅读器流程,中间需要解析过程
解析TFRecords的example协议内存 tf.parse_single_example(serialized,features=None,name=None)
解析一个单一的Example原型
serialized:标量字符串Tensor,一个序列化的Example
features:dict字典数据,键为读取的名字,值为FixedLenFeature
return:一个键值对组成的字典,键为读取的名字
tf.FixedLenFeature(shape,dtype)
shape:输入数据的形状,一般不指定,为空列表
dtype:输入数据类型,与存储进文件的类型要一致
类型只能是float32,int64,string
1、构造存储器
2、构造每一个样本的Example
3、写入序列化的Example
1、构造TFRecords阅读器
2、解析Example
3、转换格式,bytes解码
import tensorflow as tf
import os
# 读取CSV格式文件
# 1、构建文件队列
# 2、构建读取器,读取内容
# 3、解码内容
# 4、现读取一个内容,如果有需要,就批处理内容
def csvread(filelist):
"""
读取csv文件
:param filelist:文件路径+名字的列表
:return:读取的内容
"""
# 把文件目录和文件名合并
flist = [os.path.join("./csv/",file) for file in filelist]
# 1、构造文件的队列
file_queue = tf.train.string_input_producer(flist,shuffle=False)
# 2、构造csv阅读器读取队列数据(读一行)
reader = tf.TextLineReader()
key,value = reader.read(file_queue)
record_defaults = [["null"], ["null"]]
# 3、对每行内容解码
# record_defaults:指定每一个样本的每一列的类型,指定默认值[["None"], [4.0]]
# 解码内容,按行解析,返回的是每行的列数据
example,label = tf.decode_csv(value,record_defaults=record_defaults)
# 4、想要读取多个数据,就需要批处理,从文件名队列中提取tensor,使用单个或多个线程,准备放入文件队列;
example_batch,label_batch = tf.train.batch([example,label],batch_size=9,num_threads=1,capacity=9)
with tf.Session() as sess:
# 线程协调员
coord = tf.train.Coordinator()
# 启动工作线程,启动入队线程,由多个或单个线程,按照设定规则,把文件读入Filename Queue中。
threads = tf.train.start_queue_runners(sess, coord=coord)
# 打印批处理的数据
print(sess.run([example_batch,label_batch]))
coord.request_stop()
coord.join(threads)
return None
if __name__=="__main__":
filename_list = os.listdir("./csv")
csvread(filename_list)
import tensorflow as tf
import os
# 同样图像加载与二进制文件相同。图像需要解码。输入生成器(tf.train.string_input_producer)找到所需文件,
# 加载到队列。tf.WholeFileReader 加载完整图像文件到内存,WholeFileReader.read 读取图像,
# tf.image.decode_jpeg 解码JPEG格式图像。图像是三阶张量。RGB值是一阶张量。
# 加载图像格 式为[batch_size,image_height,image_width,channels]。
# 批数据图像过大过多,占用内存过高,系统会停止响应。
# 直接加载TFRecord文件,可以节省训练时间。支持写入多个样本。
# 读取图片数据到Tensor
# 管道读端多文件内容处理
def picread(file_list):
"""
读取狗图片并转换成张量
:param filelist: 文件路径+ 名字的列表
:return: None
"""
# 构造文件队列
file_queue = tf.train.string_input_producer(file_list)
# 构造阅读器去读取图片内容(默认读取一张图片)
reader = tf.WholeFileReader()
key,value = reader.read(file_queue)
# 解码成张量形式
image_first = tf.image.decode_jpeg(value)
print(image_first)
# 缩小图片到指定长宽,不用指定通道数
image = tf.image.resize_images(image_first,[256,256])
# 设置图片的静态形状
image.set_shape([256,256,3])
print(image)
# 批处理图片数据,tensors是需要具体的形状大小
image_batch = tf.train.batch([image],batch_size=100,num_threads=1,capacity=100)
print(image_batch)
tf.summary.image("pic",image_batch)
with tf.Session() as sess:
merged = tf.summary.merge_all()
print("filewriter")
filewriter = tf.summary.FileWriter("./tmp/summary/dog/",graph=sess.graph)
print("filewriter end...")
# 线程协调器
coord = tf.train.Coordinator()
# 开启线程
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
summary = sess.run(merged)
filewriter.add_summary(summary)
coord.request_stop()
coord.join(threads)
return None
if __name__ == "__main__":
filename = os.listdir("./dog/")
file_list = [os.path.join("./dog/",file) for file in filename]
picread(file_list)
import tensorflow as tf
import os
#CIFAR-10的数据读取以及转换成TFRecordsg格式
#1、数据的读取
from tensorflow.contrib.model_pruning.examples import cifar10
FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_string("data_dir","./cifar10/cifar-10-batches-bin/","CIFAR数据目录")
tf.app.flags.DEFINE_integer("batch_size",50000,"样本个数")
tf.app.flags.DEFINE_string("records_file","./cifar10/cifar.tfrecords","tfrecords文件位置")
class CifarRead(object):
def __init__(self,filename):
self.filelist = filename
# 定义图片的长、宽、深度,标签字节,图像字节,总字节数
self.height = 32
self.width = 32
self.depth = 3
self.label_bytes = 1
self.image_bytes = self.height * self.width * self.depth
self.bytes = self.label_bytes + self.image_bytes
def readcifar_decode(self):
"""
读取数据,进行转换
:return: 批处理的图片和标签
"""
# 1、构造文件队列
file_queue = tf.train.string_input_producer(self.filelist)
# 2、构造读取器,读取内容
reader = tf.FixedLengthRecordReader(self.bytes)
key,value = reader.read(file_queue)
# 3、文件内容解码
image_label = tf.decode_raw(value,tf.uint8)
# 分割标签与图像张量,转换成相应的格式
label = tf.cast(tf.slice(image_label, [0], [self.label_bytes]), tf.int32)
image = tf.slice(image_label, [self.label_bytes], [self.image_bytes])
print(image)
# 给image设置形状,防止批处理出错
image_tensor = tf.reshape(image,[self.height,self.width,self.depth])
# print(image_tensor.eval())
# 4、处理流程
image_batch,label_batch = tf.train.batch([image_tensor,label],batch_size=10,num_threads=1,capacity=10)
return image_batch,label_batch
def convert_to_tfrecords(self, image_batch, label_batch):
"""
转换成TFRecords文件
:param image_batch: 图片数据Tensor
:param label_batch: 标签数据Tensor
:param sess: 会话
:return: None
"""
# 创建一个TFRecord存储器
writer = tf.python_io.TFRecordWriter(FLAGS.records_file)
# 构造每个样本的Example
for i in range(10):
print("---------")
image = image_batch[i]
# 将单个图片张量转换为字符串,以可以存进二进制文件
image_string = image.eval().tostring()
# 使用eval需要注意的是,必须存在会话上下文环境
label = int(label_batch[i].eval()[0])
# 构造协议块
example = tf.train.Example(features=tf.train.Features(feature={
"image":tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_string])),
"label":tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
}))
# 写进文件
writer.write(example.SerializeToString())
writer.close()
return None
def read_from_tfrecords(self):
"""
读取tfrecords
:return: None
"""
file_queue = tf.train.string_input_producer(["./cifar10/cifar.tfrecords"])
reader = tf.TFRecordReader()
key,value = reader.read(file_queue)
features = tf.parse_single_example(value,features={
"image": tf.FixedLenFeature([], tf.string),
"label": tf.FixedLenFeature([], tf.int64),
})
image = tf.decode_raw(features["image"],tf.uint8)
# 设置静态形状,可用于转换动态形状
image.set_shape([self.image_bytes])
print(image)
image_tensor = tf.reshape(image,[self.height,self.width,self.depth])
print(image_tensor)
label = tf.cast(features["label"], tf.int32)
print(label)
image_batch, label_batch = tf.train.batch([image_tensor, label], batch_size=10, num_threads=1, capacity=10)
print(image_batch)
print(label_batch)
with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
print(sess.run([image_batch, label_batch]))
coord.request_stop()
coord.join(threads)
return None
if __name__ == "__main__":
# 构造文件名字的列表
filename = os.listdir(FLAGS.data_dir)
file_list = [os.path.join(FLAGS.data_dir, file) for file in filename if file[-3:] == "bin"]
cfar = CifarRead(file_list)
# image_batch,label_batch = cfar.readcifar_decode()
cfar.read_from_tfrecords()
with tf.Session() as sess:
# 构建线程协调器
coord = tf.train.Coordinator()
# 开启线程
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# print(sess.run(image_batch))
# 存进文件
# cfar.convert_to_tfrecords(image_batch, label_batch)
coord.request_stop()
coord.join(threads)