Tensorflow从文件读取数据

来源:互联网 发布:淘宝卖家申诉入口 编辑:程序博客网 时间:2024/06/05 18:44

作者:曾翔钰 &&石炜贤
@曾翔钰
@石炜贤
TensorFlow程序读取数据一共有3种方法:

  • 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据。
  • 从文件读取数据: 在TensorFlow图的起始, 让一个输入管线从文件中读取数据。
  • 预加载数据: 在TensorFlow图中定义常量或变量来保存所有数据(仅适用于数据量比较小的情况)。

使用Tensorflow训练神经网络模型,首先要读取数据,宝宝参照网上几篇博客,琢磨出几种Tensorflow从文件读取数据的办法,实际上办法挺多的,怎么开心怎么来。比如可以在一个文本里面写入图片数据的地址和label,用tensorflow的read_file()可以读入图片;也可以将图片(比如图片的大小是3*32*32,其中3是通道)和label值直接存在CSV文件或者TXT文件,下面详细说明。
重点内容
(1)从字典结构的数据文件读取
(2)从bin file读入
(3)从CSV (TXT)中读取
(4)从原图读取

1.从字典结构的数据文件读取
(1)字典结构的数据文件
a).上一篇博客有提到如何得到字典结构的数据文件,即如何将自己图片以字典结构存储为数据文本
博客链接:
http://blog.csdn.net/zengxyuyu/article/details/53240463
b).cifar10数据有三种版本,分别是MATLAB,Python和bin版本
数据下载链接:
http://www.cs.toronto.edu/~kriz/cifar.html
其中Python版本的数据即是以字典结构存储的数据
(2)读入
用pickle来load字典结构的数据
代码如下:

import pickle as p#记得导入pickle,用它来加载数据import osimport tensorflow as tffilename = os.path.join("data","contact")#我把数据文本放在项目下的data文件夹下X = NoneY = Nonewith open(filename, 'rb')as f:    #从字典结构的数据文本加载数据,加载出来的数据保留了字典结构    datadict = p.load(f)    #获得所有的图像数据,是个6000*3*32*32的一维数组    X = datadict['data']    #获得所有图像的label,是个6000大小的一维数组    Y = datadict['labels']    print ("data数据X数组的大小:", X.shape)    #将6000*3*32*32一维数组转换为(6000,3*32*32)的二维数组    X = X.reshape(6000, -1)#将X加入tf队列valuequeue = tf.train.input_producer(X,shuffle=False)valuelabel = tf.train.input_producer(Y,shuffle=False)#每次出队一个value = valuequeue.dequeue()label = valuelabel.dequeue()    #label是字符串类型的,需要转成tf.int32类型result.label = tf.string_to_number(label,tf.int32)#Convert from [depth, height, width] to [height, width, depth].#value存入的时候就是数组,所以取出来就是数组,没必要像label从字符串转,现在reshape3*32*32的三维矩阵image = tf.reshape(value,[result.depth, result.height, result.width])result.uint8image = tf.transpose(image, [1, 2, 0])

2.从bin file读入
在官网的cifar的例子中就是从bin文件中读取的。bin文件需要以一定的size格式存储,比如每个样本的值占多少字节,label占多少字节,且这对于每个样本都是固定的,然后一个挨着一个存储。这样就可以使用tf.FixedLengthRecordReader 类来每次读取固定长度的字节,正好对应一个样本存储的字节(包括label)。并且用tf.decode_raw进行解析。

(1)制作bin file
如何将自己的图片存为bin file,可以看看下面这篇博客,这篇博客使用C++和opencv将图片存为二进制文件:
http://blog.csdn.net/code_better/article/details/53289759
(2)从bin file读入
下面代码摘自cifar10_input.py。在用tf.decode_raw(注意decode时使用的数据格式最好与存储是的相同)得到record_bytes后,用tf.slice抽取里面的内容,第二个输入参数表示从第几个字节开始抽取,第三个参数表示抽取的字节数。代码中的reshape是根据图片存储是的shape格式有关,具体问题具体分析。

import tensorflow as tfimage_bytes = result.height * result.width * result.depthrecord_bytes = label_bytes + image_bytes#record_bytes为3073reader = tf.FixedLengthRecordReader(record_bytes=record_bytes)#每次读取的大小为3073result.key, value = reader.read(filename)  # Convert from a string to a vector of uint8 that is record_bytes long.  record_bytes = tf.decode_raw(value, tf.uint8)  # The first bytes represent the label, which we convert from uint8->int32.  label = tf.cast(      tf.slice(record_bytes, [0], [label_bytes]), tf.int32)  # The remaining bytes after the label represent the image, which we reshape  # from [depth * height * width] to [depth, height, width].  depth_major = tf.reshape(tf.slice(record_bytes, [label_bytes], [image_bytes]),                           [result.depth, result.height, result.width])  # Convert from [depth, height, width] to [height, width, depth].  uint8image = tf.transpose(depth_major, [1, 2, 0])

最后自然还需要用shuffle_batch 生成batch。

3.从CSV (TXT)中读取
有的时候在数据量不是很大的时候,可以从CSV或者TXT文件进行读取。
(1)制作CSV(TXT)数据文本
CSV (TXT)一般是一行存一个样本(包括样本值和label),用逗号隔开。用python的普通文本写入即可。
(2)读取的时候tf.TextLineReader 类来每次读取一行,并使用tf.decode_csv来对每一行进行解析。
这里主要介绍一下 tf.decode_csv(records, record_defaults, field_delim=None, name=None)
首先records与第二种方法中相同,为reader读到的内容,这里为CSV (TXT)的一行。一般一行里面的值会用逗号或者空格隔开,这里第三个输入参数就是指定用什么来进行分割,默认为逗号。第二个输入参数是指定分割后每个属性的类型,比如分割后会有三列,那么第二个参数就应该是[[‘int32’], [], [‘string’]], 可见不指定类型(设为空[])也可以。如果分割后的属性比较多,比如有100个,可以用[ []*100 ]来表示
col= tf.decode_csv(records, record_defaults=[ [ ]*100 ], field_delim=‘ ’, name=None)
返回的col是长度为100的list。
需要注意的是,当数据量比较大的时候,存成CSV或TXT文件要比BIN文件大的多,因此在TF中读取的速度也会慢很多。因此尽量不要读取大的CSV的方式来输入。

filename_queue = tf.train.string_input_producer(["file0.csv", "file1.csv"])#每次一行reader = tf.TextLineReader()key, value = reader.read(filename_queue)#解析每次的一行,默认以逗号分开image_v, label = tf.decode_csv(    value, record_defaults=record_defaults)result.label = tf.string_to_number(label,tf.int32)image= tf.string_to_number(image_v,tf.int32)image = tf.reshape(image,[result.depth, result.height, result.width])# Convert from [depth, height, width] to [height, width, depth].  result.uint8image = tf.transpose(image, [1, 2, 0])

TF 官方还推荐了他自己的一种文件格式https://www.tensorflow.org/versions/r0.10/how_tos/reading_data/index.html#standard-tensorflow-format, 我还 没用过,大家可以自己看看。

4.从原图读取
(1)制作数据路径文件
一行一例,每例包括该样本的地址和label,用逗号分割开,用python普通文件写入即可
(2) 读取
很多情况下我们的图片训练集就是原始图片本身,并没有像cifar dataset那样存成bin等格式。因此我们需要根据一个train_list列表,去挨个读取图片。这里我用到的方法是首先将train_list.txt中的image list(也就是每一行有图片的路劲和label组成)读入队列中,那么对每次dequeue的内容中可以提取当前图片的路劲和label

filename = os.path.join(data_dir, trainfilename)      with open(filename) as fid:          content = fid.read()      content = content.split('\n')      content = content[:-1]      valuequeue = tf.train.string_input_producer(content,shuffle=True)      value = valuequeue.dequeue()      dir, labels = tf.decode_csv(records=value, record_defaults=[["string"], [""]], field_delim=" ")      labels = tf.string_to_number(labels, tf.int32)      imagecontent = tf.read_file(dir)      image = tf.image.decode_png(imagecontent, channels=3, dtype=tf.uint8)      image = tf.cast(image, tf.float32)      #将图片统一为32*32大小的    image = tf.image.resize_images(image,[32,32])    image = tf.reshape(image,[result.depth, result.height, result.width])    # Convert from [depth, height, width] to [height, width, depth].    result.uint8image = tf.transpose(image, [1, 2, 0])

不过这个方法对电脑输入输出要求比较高,如果机械硬盘有坏道,就会报Input/Output error,出现这种情况,要修复机械硬盘坏道。

1 1
原创粉丝点击