# -*- coding: utf-8 -*-
"""
Created on Sat Nov 17 08:40:21 2018
@author: shenfangyuan
"""
# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
'''
1,tensorflow中为了充分利用GPU,减少GPU等待数据的空闲时间,
使用了"两个"线程分别执行数据读入和数据计算。
2,一个线程源源不断的将硬盘中的图片数据读入到一个"内存队列"中,
另一个线程负责计算任务,所需数据直接从内存队列中获取。
3,tf在内存队列之前,还设立了一个文件名队列,文件名队列存放的是参与训练的文件名,
要训练 N个epoch,则文件名队列中就含有N个批次的所有文件名。 示例图如下:
'''
'''
np.ones([2, 5, 4, 3]) 看看这个张量对应的python存储方式
1,每个最内层括号内包含3个数据
2,4个内层括号组成倒数第二层括号
3,5个倒数第二层的括号,组成倒数第三层的数据结构
4,2个内层中括号则合成最外层.
[ [ [ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
]
[ [ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
[ [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] [1. 1. 1.] ]
]
'''
tf.reset_default_graph()
# 样本个数
sample_num=2
# 设置迭代次数
epoch_num = 2
# 设置一个批次中包含样本个数
batch_size = 2 #试验的时候,可以把这个值改动一下,例如:
#3,对应的batch数据和标签维度为 :(3, 224, 224, 3) [0 1 2]
#4,对应的batch数据和标签维度为 :(4, 224, 224, 3) [4 5 6 7]
# 计算每一轮epoch中含有的batch个数
batch_total = int(sample_num/batch_size)+1
print('batch_total = ',batch_total)
# 生成4个数据和标签
def generate_data(sample_num=sample_num):
labels = np.asarray(range(0, sample_num)) #用随机数产生标签:0--sample_num
# print('labels',labels)
# images = np.random.random([sample_num, 5, 4, 3]) #用随机数产生 测试图片数据,每张图片数据是:[224,224,3]
images = np.ones([sample_num, 5, 4, 3]) #用随机数产生 测试图片数据,每张图片数据是:[224,224,3]
print('images',images)
#打印 数据的shape
print('image size {},label size :{}'.format(images.shape, labels.shape))
return images,labels
def get_batch_data(batch_size=batch_size):
images, label = generate_data() #用随机数产生标签和对应的图片数据.
# 数据类型转换为tf.float32
images = tf.cast(images, tf.float32) #数据转换为float32
label = tf.cast(label, tf.int32) #标签数据转换为整型数
#从tensor列表中按顺序或随机抽取一个tensor
#这里的tensor列表是:[images, label],该列表的元素为images和label
#这两个元素images和label也都是列表,他们的第一个维度必须相等,
#一般这两个列表的第一维对应的shape值 labels.shape[0]==images.shape[0],就是样本数量.
'''
tf.train.slice_input_producer是一个tensor生成器,作用是按照设定,
每次从一个tensor列表中按顺序或者随机抽取出一个tensor放入文件名队列。
这个函数的输出input_queue实质上也是一个"复合"结构,这个函数输入的tensor_list列表
中包含两个元素:images,label,那么input_queue就对应两个"子队列",分别是:
input_quque[0]和input_queue[1]
'''
input_queue = tf.train.slice_input_producer([images, label], shuffle=False)
'''
tf.train.batch是一个tensor队列生成器,作用是按照给定的tensor顺序,
把batch_size个tensor推送到文件队列,作为训练一个batch的数据,
等待tensor出队执行计算。
tf.train.batch是一个tensor队列生成器,作用是按照给定的tensor顺序,
把batch_size个tensor推送到文件队列,作为训练一个batch的数据,
等待tensor出队执行计算。
第一个参数tensors:tensor序列或tensor字典,可以是含有单个样本的序列;
第二个参数batch_size: 生成的batch的大小;
第三个参数num_threads:执行tensor入队操作的线程数量,可以设置使用多个线程同时并行执行,提高运行效率,但也不是数量越多越好;
第四个参数capacity: 定义生成的tensor序列的最大容量;
第五个参数enqueue_many: 定义第一个传入参数tensors是多个tensor组成的序列,还是单个tensor;
第六个参数shapes: 可选参数,默认是推测出的传入的tensor的形状;
第七个参数dynamic_pad: 定义是否允许输入的tensors具有不同的形状,设置为True,会把输入的具有不同形状的tensor归一化到相同的形状;
第八个参数allow_smaller_final_batch: 设置为True,表示在tensor队列中剩下的tensor数量不够一个batch_size的情况下,允许最后一个batch的数量少于batch_size, 设置为False,则不管什么情况下,生成的batch都拥有batch_size个样本;
第九个参数shared_name: 可选参数,设置生成的tensor序列在不同的Session中的共享名称;
第十个参数name: 操作的名称;
'''
#从队列中读取指定batch_size个样本数据
image_batch, label_batch = tf.train.batch(input_queue, batch_size=batch_size, num_threads=1, capacity=64)
return image_batch, label_batch
image_batch, label_batch = get_batch_data(batch_size=batch_size)
with tf.Session() as sess:
coord = tf.train.Coordinator()
'''
tf.train.start_queue_runners 函数来启动执行文件名队列填充的线程,
之后计算单元才可以把数据读出来,否则文件名队列为空的,
计算单元就会处于一直等待状态,导致系统阻塞。
'''
threads = tf.train.start_queue_runners(sess, coord) #启动队列,读取数据到队列
try:
for i in range(epoch_num): # 每一轮迭代
# print( '************')
#在每轮中,把所有样本按照batch_size大小为一组,遍历每个组,逐个组进行训练
for j in range(batch_total):
# print ('--------')
# 获取每一个batch中batch_size个样本和标签,这一步等价于从内存队列里面读取数据进行计算
image_batch_v, label_batch_v = sess.run([image_batch, label_batch])
# for k in
print(image_batch_v.shape, label_batch_v)
#这里打印的是:image_batch_v的维度shape,而label_batch_v打印的是原始数据
except tf.errors.OutOfRangeError:
print("done")
finally:
coord.request_stop()
coord.join(threads)
===============================================================================================
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 17 08:09:49 2018
@author: shenfangyuan
"""
import tensorflow as tf
tf.reset_default_graph()
images = ['img1', 'img2', 'img3', 'img4', 'img5']
labels= [1,2,3,4,5]
epoch_num=8
#f = tf.train.slice_input_producer([images, labels],num_epochs=None,shuffle=False)
f1 = tf.train.slice_input_producer([images, labels],num_epochs=None,shuffle=True)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
for epoch in range(epoch_num):
k = sess.run(f1)
print ('************************')
print ('epoch = ',epoch )
print('f = ',k)
coord.request_stop()
coord.join(threads)
===========================================================================================
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 17 10:39:30 2018
@author: shenfangyuan
"""
'''
准备tf训练集的流程:
1,使用操作系统os中的方法,得到训练图片和标注(图片)的"文件名字列表",
相当于在给训练文件集合(库)建立起来一套"索引(名字)"
image_filename_lists
image_filename
这两个列表结构的第一个维度必须一样,也就是:有多少条样本数据(行)就有对应的标签数据(行)
2,调用tf.train.slice_input_producer()函数,依据名字(索引列表),建立一个队列
filename_queue=tf.train.slice_input_producer([image_filename_lists,label_filename_lists])
该函数返回image_filename_lists和label_filename_lists对应的队列:queue列表
filename_queue[0]与image_filename对应;
filename_queue[1]与image_filename对应
使用队列的理由是:可以对这些名字列表中的元素进行随机化处理;
第二个理由是,可以使用多线程机制.
3,我们可以以队列的filename_queue[i]为基础,定义tf数据读取的操作符:例如:
image_contents = tf.read_file(input_queue[0]) #定义读取内容的操作符
image = tf.image.decode_jpeg(image_contents, channels=1) #图像预处理操作符
这一步就相当于:利用索引从数据库中获取对应的内容.执行数据库的底层读写操作.
4,上面定义了对从库中读取内容后的预处理操作符,接下来,把利用索引从库中读取的内容,
按照batch_size的要求"封装,打包",也就是把batch_size个预处理后的图片内容,
放在一个张量中,也相当于:从总表中得到包含batch_size这么多"行"的"子表".
这个运算符是由image_batch = tf.train.batch()函数完成的
image_batch = tf.train.batch([image], batch_size=batch_size)
这个操作的输入参数是上一步对文件内容进行预处理得到的结果的操作符:image
函数返回的是:获得一组(batch_size个)数据的操作符.
5,使用控制台的run函数,就可以得到一组batch_size数据:
picture_batch = sess.run(image_batch)
需要强调的是:以上的操作都是定义的在tf中将要执行的一些列操作符号,在定义操作符的时候,
这些操作并没有被执行,他们相当于用语言,描绘一张tf使用的运行流程图
直到最后的sess.run(op操作符),才执行该流程图中定义的一些列关联的运算.
'''
import tensorflow as tf
import numpy as np
import os
import matplotlib.pyplot as plt
tf.reset_default_graph()
def show_image(image):
#显示单张图片
image = np.transpose(image,(2,0,1)) #需要改变一下维度
plt.imshow(image[0],cmap='Greys_r')
plt.show()
def show_batch_image(batch_image):
#显示一个batch的图片
for i in range(batch_size):
image = batch_image[i]
show_image(image)
image_W = 16
image_H = 16
train_dir = "..\\test_data\\" #文件所在的路径
image_list = []
for file in os.listdir(train_dir):
image_list.append(os.path.join(train_dir, file))
for i in range(len(image_list)):
print(image_list[i])
sample_num = len(image_list) #样本的总数量
epoch_num = 3 #用全部样本迭代的次数
batch_size = 5 #
batch_total = int(sample_num/batch_size)+1 #一个epoch有的batch数目
#给予列表,产生"文件名字"队列,这里只有一个元素image_list,那也得用[]括起来
input_queue = tf.train.slice_input_producer([image_list],shuffle = False) #生成文件名队列,由于shuffle = True,随机产生一个文件名路径
#从文将名字队列的输出端口,读取文件名字并调用tf.read_file(队列端口),读取文件内容数据
image_contents = tf.read_file(input_queue[0]) #根据上面的文件名路径,读取样本(处于编码下)
#把读取的内容进行jpg解码
image = tf.image.decode_jpeg(image_contents, channels=1) #进行解码,由于读取的为灰度图,channels=1
#crop_image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H) #采用切割的方式改变大小
#对图片进行裁切
crop_image = tf.image.resize_images(image, [image_W,image_H],method=0) #采用放缩的方式改变大小,method=0为双线性插值
#对图片规范化
standard_image = tf.image.per_image_standardization(crop_image) # 标准化数据
#把从文件名队列,到文件内容,再到用文件内容构造成训练batch数据,相当于
#上面的操作定义了tf中文件读取的操作,下面定义了构造batch的操作.
image_batch = tf.train.batch([crop_image], batch_size=batch_size, num_threads=2, capacity=64, allow_smaller_final_batch=False) #生成batch
with tf.Session() as sess:
coord = tf.train.Coordinator() #创建线程管理器
threads = tf.train.start_queue_runners(sess, coord) #启动线程
try:
for i in range(epoch_num): # 每一轮迭代
print ('epoch is %d'%(i+1))
for j in range(batch_total): #batch遍历,在所有样本中选择batch_size个
#print ('batch num is %d'%(j+1))
#print ('input_queue:%s'%(sess.run(input_queue)))
#print ('image_contents:%s'%(sess.run(image_contents)))
#picture, crop_picture,standard_picture = sess.run([image,crop_image,standard_image])
#show_image(picture)
#show_image(crop_picture)
#show_image(standard_picture)
picture_batch = sess.run(image_batch) #让tf执行以上定义的操作
print(picture_batch.shape) #打印从tf返回到py环境的结果,这里返回shape
#(3, 64, 64, 1) 3是batch_size,也就是说,返回的结果包含batch_size张图片
#每张图片是:64x64x1的图片
# show_batch_image(picture_batch )
except tf.errors.OutOfRangeError: #如果读取到文件队列末尾会抛出此异常
print("done! now lets kill all the threads……")
finally:
# 协调器coord发出所有线程终止信号
coord.request_stop()
print('all threads are asked to stop!')
coord.join(threads) #把开启的线程加入主线程,等待
---------------------
作者:yanlizhong62
来源:CSDN
原文:https://blog.csdn.net/yanlizhong62/article/details/84475812
版权声明:本文为博主原创文章,转载请附上博文链接!