距离上次的博客已经过去了半个月两周左右的时间,自己在b站和博客上学习了很多相关的知识,自我感觉自己的tensorflow的水平已经算是到了入门的水平,在博客上有相关的非tensorboard导入数据,实测有效(传送门由于时间久了,暂时找不到了,自己找一下吧)。不过通过tensorboard的可运行资料却十分少,所以自己在此记录一下自己的程序,也算是自己整理一下。
如果感觉有用,可以点一下关注哟!我会不定期更新一些自己学习的东西。
使用的IDE是vscode(python3.5),数据下载可以在其他博客中找一下。
首先工程图如下:
Data文件夹下有train和test两个文件夹,就是下载的数据集。Logs存放咱们所有的程序。
首先我们要建立创建tfrecord的文件:
首先得到文件夹train下的所有文件名称,贴出代码如下:
import tensorflow as tf
import numpy as np
import os
NumClass = 2
ImageWidth = 208
ImageHeight = 208
ImageChannel = 3
def get_files(file_dic):
cats = []
dogs = []
cats_labels = []
dogs_labels = []
for file in os.listdir(file_dic):
#得到文件下所有的文件名称,也就是cat.0jpg....
name = file.split(sep='.')
if name[0] == 'cat':
cats.append(file_dic+'/'+file)
cats_labels.append(0)
if name[0] == 'dog':
dogs.append(file_dic+'/'+file)
dogs_labels.append(1)
return cats, cats_labels, dogs, dogs_labels
cats, cats_labels, dogs, dogs_labels = get_files('G:/CatsAndDogs/data/train')
print(cats)
得到的输出为:
['G:/CatsAndDogs/data/train/cat.0.jpg', 'G:/CatsAndDogs/data/train/cat.1.jpg'...
可以看到文件名称都已导入cats等列表当中,那么接下来的操作就是把image和label的列表连接起来并打乱数据。代码贴出如下。
#将文件打乱顺序
image_list = np.hstack((cats, dogs)) #将两个列表连接起来
labels_list = np.hstack((cats_labels, dogs_labels))
temp = np.array([image_list, labels_list])
temp = temp.transpose() #转置矩阵
np.random.shuffle(temp) #打乱数据,下面的图片是temp现在的数据
##从打乱的temp中再取出list,相当于洗牌之后的重新摸牌
image_list = list(temp[:, 0])
label_list = list(temp[:, 1])
label_list = [int(i) for i in label_list] # 字符串类型转换为int类型
现在temp程序跑到这的数据结果如下图所示:
嗯,到现在为止也很成功,那我们接下来继续操作,这个时候又变成了需要对整个列表的操作,所以我们需要整个列表的长度,再把相片的解码出来。
from scipy.misc import imread,imresize #注意是得重新加载一个model
#首先要确定整个列表的长度并且初始化相片的格式
num_file = len(cats_labels) + len(dogs_labels)
images = np.zeros((num_file, ImageHeight, ImageWidth, ImageChannel), dtype = np.uint8)
for index in range(num_file):
img = imread(image_list[index])
img = imresize(img, (ImageWidth, ImageHeight))
images[index] = img
接下来我们可以把这些相片,labels等信息传入一个类中,用来建立接下来的tdrecord文件。
class ImgData(object):
pass
result = ImgData()
result.images = images
result.labels = label_list
result.num = num_file
到此我们就完成了第一个函数。此时得到了文件夹中乱序的所有照片及相应的标签,暂时完成了第一步的工作。接下来我们就开始第二部的工作,完成tfrecord文件的完成。
def convert(data, destination, destination1):
"""将图片存储为.tfrecords文件
参数:
data: 上述函数返回的ImageData对象
destination: 目标文件名
"""
images = data.images
labels = data.labels
num_examples = data.num - 3000
#使用上面使用的类进行下面的tfreord建立,照片标签以及数据
# 存储的文件名
filename = destination
#储存时的文件名(带路径的)
# 使用TFRecordWriter来写入数据
writer = tf.python_io.TFRecordWriter(filename)
#使用tfrecord进行写入
# 遍历图片
for index in range(num_examples):
# 转为二进制
image = images[index].tostring()
label = labels[index]
#直接使用上面所建立的类进行输入
# tf.train下有Feature和Features,需要注意其区别
# 层级关系为Example->Features->Feature(很重要)
#注意图片一般的类型为ByteList,其他的有Int64List和FloatList型
example = tf.train.Example(features=tf.train.Features(feature={
'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
}))
# 写入建立的example
writer.write(example.SerializeToString())
writer.close()
filename1 = destination1
writer = tf.python_io.TFRecordWriter(filename1)
for index in range(3000):
# 转为二进制
image = images[index+num_examples].tostring()
label = labels[index+num_examples]
example = tf.train.Example(features=tf.train.Features(feature={
'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
}))
writer.write(example.SerializeToString())
writer.close()
convert(result, 'G:/CatsAndDogs/logs/traintfrecord', 'G:/CatsAndDogs/logs/testtfrecord')
上面的注释很清楚,应该可以看懂,主要是有train和test两个部分,不太懂的也可以百度查一下,应该可以找到相关的资料。接下来的就是解码一下数据。
def read_and_decode(filename_queue, batch_size, capacity):
"""读取.tfrecords文件
参数:
filename_queue: 文件名, 一个列表
返回:
img, label: **单张图片和对应标签**
"""
# 创建一个图节点,该节点负责数据输入
filename_queue = tf.train.string_input_producer([filename_queue])
# tf.train.string_input_producer函数把我们需要的全部文件打包为一个tf内部的queue类型
# 之后tf开文件就从这个queue中取目录了,要注意一点的是这个函数的shuffle参数默认是True
# 所以读取的顺序可能不一样
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
# 读取前面所建立的数据目录
# 解析单个example
# 暂时不大清楚下面的操作,不过感觉应该是得到各个features
features = tf.parse_single_example(serialized_example, features={
'image': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64)
})
# tf.decode_raw函数的意思是将原来编码为字符串类型的变量重新变回来
# 这个方法在数据集dataset中很常用,因为制作图片源数据一般写进tfrecord里用to_bytes的形式,也就是字符串
# 这里将原始数据取出来,必须制定原始数据的格式,原始数据是什么格式这里解析必须是什么格式!!
# tf.cast这个函数主要用于数据类型的转变,不会改变原始数据的值还有形状的
image = tf.decode_raw(features['image'], tf.uint8)
image = tf.reshape(image, [ImageHeight, ImageWidth, ImageChannel])
image = tf.cast(image, tf.float32)
label = tf.cast(features['label'], tf.int32)
image_batch, label_batch = tf.train.batch([image, label],
batch_size=batch_size,
num_threads=64, # 线程
capacity=capacity)
return image, label
上面是解析tfrecord的函数,那么可以利用下面的程序进行train和test数据的获得。
image, label = read_and_decode('G:/CatsAndDogs/logs/traintfrecord', 16, 2000)
image1, label1 = read_and_decode('G:/CatsAndDogs/logs/testtfrecord', 16, 2000)
整体的函数如下:
import tensorflow as tf
import numpy as np
import os
from scipy.misc import imread,imresize
NumClass = 2
ImageWidth = 208
ImageHeight = 208
ImageChannel = 3
def get_files(file_dic):
cats = []
dogs = []
cats_labels = []
dogs_labels = []
#得到文件下所有的文件名称,也就是cat.0jpg....
for file in os.listdir(file_dic):
name = file.split(sep='.')
if name[0] == 'cat':
cats.append(file_dic+'/'+file)
cats_labels.append(0)
if name[0] == 'dog':
dogs.append(file_dic+'/'+file)
dogs_labels.append(1)
num_file = len(cats_labels) + len(dogs_labels)
images = np.zeros((num_file, ImageHeight, ImageWidth, ImageChannel), dtype = np.uint8)
print("There are %d cats\nThere are %d dogs" % (len(cats), len(dogs)))
#将文件打乱顺序
image_list = np.hstack((cats, dogs))
labels_list = np.hstack((cats_labels, dogs_labels))
temp = np.array([image_list, labels_list])
temp = temp.transpose()
np.random.shuffle(temp)
##从打乱的temp中再取出list(img和lab)
image_list = list(temp[:, 0])
label_list = list(temp[:, 1])
label_list = [int(i) for i in label_list] # 字符串类型转换为int类型
for index in range(num_file):
img = imread(image_list[index])
img = imresize(img, (ImageWidth, ImageHeight))
images[index] = img
class ImgData(object):
pass
result = ImgData()
result.images = images
result.labels = label_list
result.num = num_file
return result
def convert(data, destination, destination1):
"""将图片存储为.tfrecords文件
参数:
data: 上述函数返回的ImageData对象
destination: 目标文件名
"""
images = data.images
labels = data.labels
num_examples = data.num - 3000
#使用上面使用的类进行下面的tfreord建立,照片标签以及数据
# 存储的文件名
filename = destination
#储存时的文件名(带路径的)
# 使用TFRecordWriter来写入数据
writer = tf.python_io.TFRecordWriter(filename)
#使用tfrecord进行写入
# 遍历图片
for index in range(num_examples):
# 转为二进制
image = images[index].tostring()
label = labels[index]
#直接使用上面所建立的类进行输入
# tf.train下有Feature和Features,需要注意其区别
# 层级关系为Example->Features->Feature(很重要)
#注意图片一般的类型为ByteList,其他的有Int64List和FloatList型
example = tf.train.Example(features=tf.train.Features(feature={
'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
}))
# 写入建立的example
writer.write(example.SerializeToString())
writer.close()
filename1 = destination1
writer = tf.python_io.TFRecordWriter(filename1)
for index in range(3000):
# 转为二进制
image = images[index+num_examples].tostring()
label = labels[index+num_examples]
example = tf.train.Example(features=tf.train.Features(feature={
'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
}))
writer.write(example.SerializeToString())
writer.close()
convert(result, 'G:/CatsAndDogs/logs/traintfrecord', 'G:/CatsAndDogs/logs/testtfrecord')
def read_and_decode(filename_queue, batch_size, capacity):
"""读取.tfrecords文件
参数:
filename_queue: 文件名, 一个列表
返回:
img, label: **单张图片和对应标签**
"""
# 创建一个图节点,该节点负责数据输入
filename_queue = tf.train.string_input_producer([filename_queue])
# tf.train.string_input_producer函数把我们需要的全部文件打包为一个tf内部的queue类型
# 之后tf开文件就从这个queue中取目录了,要注意一点的是这个函数的shuffle参数默认是True
# 所以读取的顺序可能不一样
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
# 读取前面所建立的数据目录
# 解析单个example
# 暂时不大清楚下面的操作,不过感觉应该是得到各个features
features = tf.parse_single_example(serialized_example, features={
'image': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64)
})
# tf.decode_raw函数的意思是将原来编码为字符串类型的变量重新变回来
# 这个方法在数据集dataset中很常用,因为制作图片源数据一般写进tfrecord里用to_bytes的形式,也就是字符串
# 这里将原始数据取出来,必须制定原始数据的格式,原始数据是什么格式这里解析必须是什么格式!!
# tf.cast这个函数主要用于数据类型的转变,不会改变原始数据的值还有形状的
image = tf.decode_raw(features['image'], tf.uint8)
image = tf.reshape(image, [ImageHeight, ImageWidth, ImageChannel])
image = tf.cast(image, tf.float32)
label = tf.cast(features['label'], tf.int32)
image_batch, label_batch = tf.train.batch([image, label],
batch_size=batch_size,
num_threads=64, # 线程
capacity=capacity)
return image, label
image, label = read_and_decode('G:/CatsAndDogs/logs/traintfrecord', 16, 2000)
image1, label1 = read_and_decode('G:/CatsAndDogs/logs/testtfrecord', 16, 2000)
不过要注意先用前两个函数生成所需的tfrecord文件才能跑第三个函数。
明天继续剩下的部分。