Tensorflow: 文件读写

写文件

这里的写, 指的是把各种格式的数据(如字符, 图片等)统一转换成Tensorflow的标准支持格式TFRecord.

TFRecord是输入数据统一管理的格式, 它其实是一种二进制文件.

写入:
通过将数据填入到tf.train.Example类, Exampleprotocol buffer包含了字段的tf.train.Features, 使用数据修改Features, 实现将protocol buffer序列化成一个字符串, 再通过tf.python_io.TFRecordWriter类将序列化的字符串写入到TFRecord中.

读出:
使用tf.TFRecordReader读取器, 通过tf.parse_single_example解析器解析, parse_single_example操作可以将Example protocol buffer解析为张量, 然后用解码器 tf.decode_raw解码.

相关类/函数

  • tf.python_io.TFRecordWriter

    把记录写入到TFRecords文件的类.

    • init()
    ''' 作用: 创建一个TFRecordWriter对象, 将数据记录到指定的TFRecord文件中. 参数: path: (must)TFRecords文件的路径; options: TFRecordOptions对象; '''
    • write()
    ''' 作用: 将一条序列化字符串记录写入到文件中. 参数: record: string, 序列化字符串记录. '''
    • close()
    ''' 作用: 关闭TFRecordWriter. '''
  • tf.train.Example

    Example是使用某种规则规则化后的数据, 通过使用TFRecordWriter写入到TFRecord中.

    Example包含一个键值对数据结构(与dict相同), 使用属性features记录, 因此, 初始化时必须传入这个features参数, 它是一个tf.train.Features对象.

    • init()
    ''' 作用: 初始化一个Example. 参数: features: tf.train.Features对象, 其中每条记录的key表示数据的描述, value为固定数据类型的特殊处理的数据. '''
    • SerializeToString()
    ''' 作用: 把这个Example序列化成字符串, 将这个字符串通过TFRecordWriter写入到TFRecord中. '''
  • tf.train.Features

    协议化的描述数据信息, 结构为键值对, key为字符串, 用来描述数据, value为tf.train.Feature对象, 一个Feature包含一种数据类型的list, list中有若干数据.

    list有三种: BytesList, FloatList, Int64List

    • init()
    ''' 作用: 初始化一个Features 参数: feature: dict字典, key为数据名称, value为tf.train.Feature对象, 特殊的数据list. '''
    tf.train.Features(feature={"image_raw":tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_raw])),
                               "label":tf.train.Feature(int64_list=tf.train.Int64List(value=[train_labels_values[i]]))})
  • tf.train.Feature

    一个Feature包含一种数据类型的list, list中有若干数据.

    list类型主要有BytesList, FloatList, Int64List三种类型

    • init()
    ''' 作用: 初始化一个Feature, 内含数据队列. 参数: bytes_list: 队列数据为byte(一般是字符串)时使用, 将tf.train.BytesList赋给此参数; float_list: 队列数据为float时使用, 将tf.train.FloatList赋给此参数; int64_list: 队列数据为int64时使用, 将tf.train.Int64List赋给此参数. '''
    tf.train.Feature(int64_list = tf.train.Int64List(value = [value]))
    tf.train.Feature(bytes_list = tf.train.BytesList(value = [value]))
    tf.train.Feature(float_list = tf.train.FloatList(value = [value]))
  • tf.train.BytesList, tf.train.FloatList, tf.train.Int64List

    字符, 浮点, 整形三种数据队列

    ''' 作用: 初始化一个类型的队列, 传入数据 参数: value: 将相应类型的数据放在list中, 赋值给此参数 '''

生成TFRecord例子

读取csv文件, 并转为TFRecord

这里使用Kaggle中Getting Started级别的Digit Recognizer题目, 数据是MNIST手写数字的csv格式, 这里使用train.csv作为例子, 实现将csv文件转换为TFRecord的操作.

import numpy as np
import pandas as pd
import tensorflow as tf

train_frame=pd.read_csv(filepath_or_buffer="train.csv")
train_labels_frame=train_frame.pop(item="label")

train_values=train_frame.values
train_labels_values=train_labels_frame.values
train_size=train_values.shape[0]


writer=tf.python_io.TFRecordWriter(path="train.tfrecords")
for i in range(train_size):
    image_raw=train_values[i].tostring()

    example=tf.train.Example(
        features=tf.train.Features(
            feature={
                "image_raw":tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_raw])),
                "label":tf.train.Feature(int64_list=tf.train.Int64List(value=[train_labels_values[i]]))
            }
        )
    )
    writer.write(record=example.SerializeToString())

writer.close()

读取图片, 转换为TFRecord格式

from PIL import Image  # 这里使用PIL包读取图片

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_path, name):

    rows = 64
    cols = 64
    depth = DEPTH
    for ii in range(12):
        writer = tf.python_io.TFRecordWriter(name + str(ii) + '.tfrecords')
        for img_name in os.listdir(data_path)[ii*16384 : (ii+1)*16384]:
            img_path = data_path + img_name
            img = Image.open(img_path)
            h, w = img.size[:2]
            j, k = (h - OUTPUT_SIZE) / 2, (w - OUTPUT_SIZE) / 2
            box = (j, k, j + OUTPUT_SIZE, k+ OUTPUT_SIZE)

            img = img.crop(box = box)
            img = img.resize((rows,cols))
            img_raw = img.tobytes()
            example = tf.train.Example(features = tf.train.Features(feature = {
                                    'height': _int64_feature(rows),
                                    'weight': _int64_feature(cols),
                                    'depth': _int64_feature(depth),
                                    'image_raw': _bytes_feature(img_raw)}))
            writer.write(example.SerializeToString())
        writer.close()

读文件

Tensorflow中, 有三种主要的读取数据文件的读写器类, 有共用的操作文件的Ops.

tf.TextLineReader 用于读取csv文件, 配合tf.decode_csv()方法使用;
tf.FixedLengthRecordReader 用于读取二进制编码文件, 配合tf.decode_raw()解码器方法使用;
tf.TFRecordReader 用于读取TFRecord文件, 配合tf.parse_single_example()解析器和tf.decode_raw()解码器方法使用.

三个类均继承于父类tf.ReaderBase, 常用的方法有:

read()

FixedLengthRecordReader

  • init()
''' 作用: 生成一个每次读取固定长度数据的读取器. 参数: record_bytes: (must)整数, 固定的读取长度; header_bytes: 整数, 头数据长度, 默认为0; footer_bytes: 整数, 尾数据长度, 默认为0; name: Op的名字; '''

使用例子见Tensorflow: 队列操作章节中最后的读取数据的例子.

TextLineReader

  • init()
''' 作用: 生成一个每次读取一行内容的读取器 参数: skip_header_lines: 整数, 需要跳过的头行数, 默认为0; name: Op的名称. '''

使用例子:

filename_queue = tf.train.string_input_producer(["file0.csv", "file1.csv"])

reader = tf.TextLineReader()
key, value = reader.read(filename_queue)

# Default values, in case of empty columns. Also specifies the type of the
# decoded result.
record_defaults = [[1], [1], [1], [1], [1]]
col1, col2, col3, col4, col5 = tf.decode_csv(
    value, record_defaults=record_defaults)
features = tf.concat(0, [col1, col2, col3, col4])

with tf.Session() as sess:
  # Start populating the filename queue.
  coord = tf.train.Coordinator()
  threads = tf.train.start_queue_runners(coord=coord)

  for i in range(1200):
    # Retrieve a single instance:
    example, label = sess.run([features, col5])

  coord.request_stop()
  coord.join(threads)

每次read的执行都会从文件中读取一行内容, decode_csv() 操作会解析这一行内容并将其转为张量列表. 如果输入的参数有缺失, record_default参数可以根据张量的类型来设置默认值.

TFRecordReader

  • init()
''' 作用: 生成一个每次从TFRecord中读取一个Features数据的读取器 参数: name: Op的名称; options: TFRecordOptions; '''

使用例子

def read_and_decode(filename):
    #根据文件名生成一个队列
    filename_queue = tf.train.string_input_producer([filename])

    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)   #返回文件名和文件
    features = tf.parse_single_example(serialized_example,
                                       features={
                                           'label': tf.FixedLenFeature([], tf.int64),
                                           'img_raw' : tf.FixedLenFeature([], tf.string),
                                       })

    img = tf.decode_raw(features['img_raw'], tf.uint8)
    img = tf.reshape(img, [224, 224, 3])
    img = tf.cast(img, tf.float32) * (1. / 255) - 0.5
    label = tf.cast(features['label'], tf.int32)

    return img, label

辅助读取文件数据的函数

  • tf.decode_csv()
''' 作用: 将读取的csv记录(字符串)解析并转换成Tensor, csv文件中的每一列将会对应一个Tensor. 参数: records: (must)string类型的Tensor, 里面每个string代表csv中的一行, 代表一条记录; record_defaults: (must)list of Tensor, 每个Tensor对应一列, 当列中的数据为空时, 使用对应的Tensor填补输出结果; field_delim: string, 指明一条记录(一行)之间各列的分界符, 默认为','; name: op的名称. 输出: list of tensor, list长度与record_defaults相同, 各个tensor的shape相同. '''
  • tf.decode_raw()
''' 作用: 将bytes of string转换为指定类型的数据. 参数: bytes: (must)string类型的Tensor, 所有的元素长度相同; out_type: (must)指明输出数据的类型, tf.DType; little_endian: (不明)bool, 默认为True, 无视out_type参数, 将数据转为单字节格式, 类似uint8; name: op的名称. 输出: out_type类型的Tensor, 维度比bytes入参Tensor多一维; 多出的一维的值等于将bytes中单个string元素, 用out_type分割后产生的数据的长度. '''
  • tf.parse_single_example()
''' 作用: 将一个Example proto 转为features指定格式的key: Tensor数据. 参数: serialized: (must)只含一条string元素的Tensor, 代表一条序列化的Example数据; features: (must)dict, 类似于存储时的features, key为字符串描述, 但value为tf.FixedLenFeature对象. name: op的名称; example_names: 只含一条string元素的Tensor, 表示Example的名称. 输出: dict, key为features参数中的key, value为转换出来的Tensor, 类型为string. '''
  • tf.FixedLenFeature
''' 作用: 固定长度Feature(tf.train.Feature)解析配置类, 用来描述Feature的属性, 以供tf.parse_single_example()方法解析. 参数: (继承于collections.namedtuple("FixedLenFeature",["shape", "dtype", "default_value"])类.) 第一: 数据的shape, 指定为[], 表示不指明; 第二: 数据的类型dtype, tf.DType; 第三: 数据缺失时默认的填补数据default_value, 必须与shape和dtype适应. '''
tf.FixedLenFeature([], tf.int64)
tf.FixedLenFeature([], tf.string)

你可能感兴趣的:(tensorflow)