起因:学习了曹健老师的八股文tensorflow框架,希望使用自己的数据集(猫狗识别数据集)来进行多种神经网络(lenet,akexnet,vgg等网络模型)的训练,因为课程有这些模型的整个框架,所以我需要做的就是把输入数据转换为我的猫狗数据集。
原框架:采用tensorflow库自带的数据集cifar10,直接函数导入即可。
经过测试,load_data()返回的x_train为四维张量,y_train为二维张量,test同理:
输入时类型:
训练后类型:
因此,我确定了八股文结构所需的输入数据的类型。
接下来要做的就是将我的猫狗数据集里面的图片解码为四维张量,标签为二维张量。
思路一:
回到过去的自制数据集那节课中提到的方法:通过定义generateds函数,实现自定义数据集。
代码如下:
train_path = './mnist_image_label/mnist_train_jpg_60000/'
train_txt = './mnist_image_label/mnist_train_jpg_60000.txt'
x_train_savepath = './mnist_image_label/mnist_x_train.npy'
y_train_savepath = './mnist_image_label/mnist_y_train.npy'
test_path = './mnist_image_label/mnist_test_jpg_10000/'
test_txt = './mnist_image_label/mnist_test_jpg_10000.txt'
x_test_savepath = './mnist_image_label/mnist_x_test.npy'
y_test_savepath = './mnist_image_label/mnist_y_test.npy'
def generateds(path, txt):
f = open(txt, 'r') # 以只读形式打开txt文件
contents = f.readlines() # 读取文件中所有行
f.close() # 关闭txt文件
x, y_ = [], [] # 建立空列表
for content in contents: # 逐行取出
value = content.split() # 以空格分开,图片路径为value[0] , 标签为value[1] , 存入列表
img_path = path + value[0] # 拼出图片路径和文件名
img = Image.open(img_path) # 读入图片
img = np.array(img.convert('L')) # 图片变为8位宽灰度值的np.array格式
img = img / 255. # 数据归一化 (实现预处理)
x.append(img) # 归一化后的数据,贴到列表x
y_.append(value[1]) # 标签贴到列表y_
print('loading : ' + content) # 打印状态提示
x = np.array(x) # 变为np.array格式
y_ = np.array(y_) # 变为np.array格式
y_ = y_.astype(np.int64) # 变为64位整型
print(x.shape)
return x, y_ # 返回输入特征x,返回标签y_
结果输出:x_train是三维张量,标签是一维张量。结果要通过调用两次generateds函数得到train,和test值及其对应标签值。
同时该方法存在问题有:1.结果是三维张量和一维标签,不符合要求的四维张量和二维标签
2.要求的输入路径除了图片数据集路径外,还需要一个存储图片名称和对应标签的文本路径。而我的猫狗数据集只有图片路径,没有对应的标签文本。
因此该方法不可行。
思路二:找一个方法同过对图片直接解码为所需的四维张量,同时提取图片名称中的标签信息,作为对应标签存储在label列表中。
通过查找资料找到了一种队列解码图片为三维张量的方法
代码如下:
import tensorflow as tf
import numpy as np
import os
os.environ["TF_CPP_MIN_LOGO_LEVEL"] = "2"
def readIMG(file_list):
"""
:param file_list: 文件路径列表
:return: 每张图片的张量
"""
# 1.构造文件队列
file_queue = tf.train.string_input_producer(file_list, shuffle=False) # shuffle:True表示随机打乱顺序
# 2.构造图像阅读器去读取图片内容(默认读取一张图片)
reader = tf.WholeFileReader()
key, value = reader.read(file_queue) # key:文件名 value:文件内容
# 3.对读取的数据进行解码
image = tf.image.decode_jpeg(value)
# 4.处理图片的大小(使得每个样本的height,width一样)
image_resize = tf.image.resize_images(image, [100, 100])
# 5.固定样本形状[200,200,3],批处理文件时要求明确数据形状,彩色图片为3,灰度图像为1
image_resize.set_shape([100,100,3])
# 6.批处理文件
image_batch = tf.train.batch([image_resize], batch_size=32, num_threads=1, capacity=4)
return image_batch
if __name__ == '__main__':
file_name_list=os.listdir("D:/python3.6/machinelearn_project/cat-dog/cats_and_dogs_filtered/train/cat-dog/") file_list=[os.path.join("D:/python3.6/machinelearn_project/cat-dog/cats_and_dogs_filtered/train/cat-dog/", i) for i in file_name_list]
image_batch = readIMG(file_list)
print(file_name_list)
print(file_list)
print("shape:", image_batch.shape)
with tf.Session() as sess:
# 定义一个线程协调器
coord = tf.train.Coordinator()
# 开启读文件的线程
threads = tf.train.start_queue_runners(sess, coord=coord)
img_data = sess.run(image_batch)
print(img_data.shape)
coord.request_stop()#请求关闭线程
coord.join(threads)#等待线程终止
代码分析:该函数通过输入一个图片路径列表,解析图片为三维张量,并返回打包好为batch值的张量。主函数file_name_list=os.listdir得到的是每一个图片名称的列表,file_list是图片完整路径列表(包含图片名称和后缀名),最后通过sess开启会话运行。
存在问题:1.结果输出的x_train仍然只是三维张量。
- 对应标签的提取问题
由于可以通过队列将图片解码为三维张量,而四维张量是可以由多个三维张量通过堆叠实现三维张量转换为四维张量。实现的函数为tf.stack
参考链接:
https://blog.csdn.net/HiWangWenBing/article/details/119651137?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-1-119651137-null-null.pc_agg_new_rank&utm_term=tensorflow%20%E5%BC%A0%E9%87%8F%E6%8B%BC%E6%8E%A5&spm=1000.2123.3001.4430
用stack堆叠产生一个新的维度是可以的,但是存在问题就是stack的参数需要两个张量,也就是说要想将所有图片解码的三维张量堆叠在一起的话就需要遍历所有的张量,逐一堆叠在一起才行。但是上述图片解码出来的只是一个张量,不是所有三维张量的列表。所以该方法也暂时不可行。
因此,思路二如果输出结果为三维张量列表的话就可以通过遍历堆叠的方法使其转换为四维张量。但是目前我仍没有想到。
最后附上一个别人的图片处理方法,我觉得写得不错,所以也在研究当中......有兴趣的同志可以参考一下。
链接:https://www.freesion.com/article/79851206891/