TensorFlow框架-tensorflow IO流程

tensorflow IO流程

  • 一、队列
    • 1、队列与队列管理器
      • (1)队列
      • (2)队列管理器
  • 二、文件读取
    • 1、文件读取流程
    • 2、文件读取API
      • (1)文件队列构造
      • (2)文件阅读器
      • (3)文件内容解码器
  • 三、图片处理
    • 1、图像基本知识
    • 2、图像读取API
    • 3、 TFRecords分析、存取
      • (1)TFRecords存储
      • (2)TFRecords读取方法
      • (3)Cart-10数据批处理结果存入tfrecords流程
      • (4)读取tfrecords流程
  • 四 、实战
    • 1.csv文件读取
    • 2.图像文件读取
    • 3.records读取

一、队列

1、队列与队列管理器

在训练样本的时候,希望读入的训练样本时有序的

(1)队列

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、入队列操作(同步操作)
TensorFlow框架-tensorflow IO流程_第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()))

运行结果:
在这里插入图片描述

(2)队列管理器

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:线程协调员实例
TensorFlow框架-tensorflow IO流程_第2张图片

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)

二、文件读取

1、文件读取流程

TensorFlow框架-tensorflow IO流程_第3张图片

2、文件读取API

(1)文件队列构造

tf.train.string_input_producer(string_tensor,shuffle=True) 将输出字符串(例如文件名)输入到管道队列
string_tensor:含有文件名的1阶张量
num_epochs:过几遍数据,默认无限过数据
return:具有输出字符串的队列

(2)文件阅读器

根据文件格式,选择对应的文件阅读器
class tf.TextLineReader 阅读文本文件逗号分隔值(CSV)格式,默认按行读取
return:读取器实例

tf.FixedLengthRecordReader(record_bytes) 要读取每个记录是固定数量字节的二进制文件
record_bytes:整型,指定每次读取的字节数
return:读取器实例

tf.TFRecordReader 读取TfRecords文件

有一个共同的读取方法:
read(file_queue):从队列中指定数量内容
返回一个Tensors元组(key文件名字,value默认的内容(行,字节))

(3)文件内容解码器

由于从文件中读取的是字符串,需要函数去解析这些字符串到张量

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、图像基本知识

三要素:长度、宽度、通道数
TensorFlow框架-tensorflow IO流程_第4张图片
TensorFlow框架-tensorflow IO流程_第5张图片
目的:
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格式图片

2、图像读取API

图像读取器
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)处理图片数据

3、 TFRecords分析、存取

TFRecords是Tensorflow设计的一种内置文件格式,是一种二进制文件,它能更好的利用内存,更方便复制和移动。
为了将二进制数据和标签(训练的类别标签)数据存储在同一个文件中
文件格式:*.tfrecords
写入文件内容:Example协议块

(1)TFRecords存储

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])

(2)TFRecords读取方法

同文件阅读器流程,中间需要解析过程

解析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

(3)Cart-10数据批处理结果存入tfrecords流程

1、构造存储器

2、构造每一个样本的Example

3、写入序列化的Example

(4)读取tfrecords流程

1、构造TFRecords阅读器

2、解析Example

3、转换格式,bytes解码

四 、实战

1.csv文件读取

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)

2.图像文件读取

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)

3.records读取

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)

你可能感兴趣的:(tensorflow)