本教程参考Kevin的视频教程:Youtube
数据集下载地址为:点击打开链接
Kevin知乎:点击打开链接
1.数据描述:
CIFAR10共有10个类,60000张图片,其中50000张彩色图像用于训练,大小为32*32;10000张用于测试。在官网下载二进制数据,这个类型的数据是分批次的,不会一起加入内存。版本为Binary version
类别如下:
数据的存储格式很特别,需要注意一下:
也就是说,将标签和图像存在一起,第一位是标签,剩余的32*32*3=3072位是图像。
2.数据步骤:
#对数据的处理主要步骤如下:
#1.读取的数据
#2.加入队列用tf.train.string_input_producer()
#3.用tf.FixedLengthRecordReader读取队列的内容,这个读取数据需要数据是等尺寸的,刚好适用这个CIFAR的读取
#4.解码,因为原始image是二进制形式的,解码成unit8
#5.重构图像的size,为img_depth, img_height, img_width
3.整个实验主要包括数据的处理、训练以及评估,这一部分主要讲数据的处理。
4.整个项目内容:
--------------------------------进入代码分解部分--------------------------------------------------------
1.导入各种需要的包
import tensorflow as tf
import numpy as np
import os
2.创建一个函数read_cifar10(),读取数据并进行分批次:
# Reading data
def read_cifar10(data_dir, is_train, batch_size, shuffle):
"""Read CIFAR10
Args:
data_dir: CIFAR10数据地址
is_train: boolen 是训练数据还是测试数据,true为训练数据
batch_size:
shuffle: 是否打乱顺序
Returns:
label: 1D tensor, tf.int32 标签
image: 4D tensor, [batch_size, height, width, 3], tf.float32 图像size
"""
img_width = 32
img_height = 32
img_depth = 3
# 设定标签占一位,图像占32*32*3位
label_bytes = 1
image_bytes = img_width * img_height * img_depth
with tf.name_scope('input'):
# 如果是训练就读训练文件(这里要分批次),是测试就读测试文件
if is_train:
filenames = [os.path.join(data_dir, 'data_batch_%d.bin' %ii)
for ii in np.arange(1, 6)]
else:
filenames = [os.path.join(data_dir, 'test_batch.bin')]
filename_queue = tf.train.string_input_producer(filenames)
# 加入队列,注意:猫狗数据大战加入队列用的是slice_input_producer([]),这个函数是传入列表,因为它的label和image不在一个文件里面
# 而这个数据是在一个里面
# 读取队列内容
reader = tf.FixedLengthRecordReader(label_bytes + image_bytes)
key, value = reader.read(filename_queue)
# 解码
record_bytes = tf.decode_raw(value, tf.uint8)
# 获得标签:从record_bytes切出来再转换成tf.int32
label = tf.slice(record_bytes, [0], [label_bytes])
label = tf.cast(label, tf.int32)
# 获得图像:从record_bytes切出来再重构size,并且转换成tf能识别的类型
image_raw = tf.slice(record_bytes, [label_bytes], [image_bytes])
image_raw = tf.reshape(image_raw, [img_depth, img_height, img_width])
image = tf.transpose(image_raw, (1, 2, 0)) # convert from D/H/W to H/W/D
image = tf.cast(image, tf.float32)
# # data argumentation(这里没做增强)
# image = tf.random_crop(image, [24, 24, 3])# randomly crop the image size to 24 x 24
# image = tf.image.random_flip_left_right(image)
# image = tf.image.random_brightness(image, max_delta=63)
# image = tf.image.random_contrast(image,lower=0.2,upper=1.8)
# 标准化数据,用了之后图像会很奇怪,用为值是0-1,要看原始图像需要注释掉这句
image = tf.image.per_image_standardization(image) # substract off the mean and divide by the variance
# 根据打乱顺序与否进行不同的batch
if shuffle:
images, label_batch = tf.train.shuffle_batch(
[image, label],
batch_size=batch_size,
num_threads=16,
capacity=2000,
min_after_dequeue=1500)
else:
images, label_batch = tf.train.batch(
[image, label],
batch_size=batch_size,
num_threads=16,
capacity=2000)
# 如果不用one-hot,就把这个return打开
label_batch = tf.reshape(label_batch, [batch_size])
return images, label_batch
# 注意:这后面的代码全被我注释掉了,是因为用one-hot编码的数据会在评估阶段发生错误,其他地方运行是没有问题的
# ## ONE-HOT,用下面的return。
# # 由于原始的标签是0-9的10个类别,将他换成one-hot编码
# n_classes = 10
# label_batch = tf.one_hot(label_batch, depth=n_classes)
# label_batch = tf.reshape(label_batch, [batch_size, n_classes])
# return images, label_batch
2.到这一部分,数据的处理就完了,我们可以测试一下函数有没有问题。但是需要注意的是这一步会出现很多问题,稍后将我遇到的问题分享给大家,先上代码。
###测试,训练的时候需要注释掉下面的:快捷注释的方法,1.把要注释的折叠起来,选中然后Ctrl + '/'就ok
## 2.鼠标选中要注释的块,然后Ctrl + '/'。注意:网上很多说这种方法是Ctrl + shift+ '/',我试过不行
## 块注释有了,怎么块取消注释呢,很简单同注释的方法一样,再操作一下就好了
import matplotlib.pyplot as plt
data_dir = 'D:/Python/neural network/CIFAR10-Guoqingxu/data/'
BATCH_SIZE = 2
image_batch, label_batch = read_cifar10(data_dir,
is_train=True,
batch_size=BATCH_SIZE,
shuffle=True)
with tf.Session() as sess:
i = 0
#用coord和threads监控队列
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
try:
while not coord.should_stop() and i<1:
img, label = sess.run([image_batch, label_batch])
# just test one batch
for j in np.arange(BATCH_SIZE):
print('label: {}'.format(label[j]))
# 视频用的%d,会出错
plt.imshow(img[j,:,:,:])
plt.show()
i+=1
except tf.errors.OutOfRangeError:
print('done!')
finally:
coord.request_stop()
coord.join(threads)
好了,这一部分数据的处理就完了。
不用one-hot结果:只测试了2张
大家看这里有警告,没法解决,解决了的也可以告诉我啊,互相学习!!
用了ont-hot的结果:
3.错误解析:
3.1 TypeError: %d format: a number is required, not numpy.ndarray
这里在代码里已经提到过,出错点在
建议大家用format.
3.2 ValueError: Floating point image RGB values must be in the 0..1 range.
另外图像是空白:
注意我们之前这里是警告。现在这是值错误,我并没有改上述代码的任何地方,只要换个环境运行就可以解决,我也不知道为什么,知道的可以告诉我哦。可能是tensorflow不同的版本造成的,我环境的版本不一样。
最后为了照顾比较懒的朋友,粘贴我的全部代码。
#########################################################
#输入数据
#CIFAR10共有60000张图片,其中50000张彩色图像用于训练,大小为32*32;10000张用于测试。在官网下载二进制数据,
# 这个类型的数据是分批次的,不会一起加入内存。地址http://www.cs.toronto.edu/~kriz/cifar.html,版本为Binary version
#数据的存放格式如https://zhuanlan.zhihu.com/p/26141396描述
# 一张图像占了3073位,第一位是标签,其余的32*32*3=3072位是图像像素,注意代码会根据这个来提取标签和图像size
#对数据的处理主要步骤如下:
#1.读取的数据
#2.加入队列用tf.train.string_input_producer()
#3.用tf.FixedLengthRecordReader读取队列的内容,这个读取数据需要数据是等尺寸的,刚好适用这个CIFAR的读取
#4.解码,因为原始image是二进制形式的,解码成unit8
#5.重构图像的size,为img_depth, img_height, img_width
##########################################################################
import tensorflow as tf
import numpy as np
import os
# Reading data
def read_cifar10(data_dir, is_train, batch_size, shuffle):
"""Read CIFAR10
Args:
data_dir: CIFAR10数据地址
is_train: boolen 是训练数据还是测试数据,true为训练数据
batch_size:
shuffle: 是否打乱顺序
Returns:
label: 1D tensor, tf.int32 标签
image: 4D tensor, [batch_size, height, width, 3], tf.float32 图像size
"""
img_width = 32
img_height = 32
img_depth = 3
# 设定标签占一位,图像占32*32*3位
label_bytes = 1
image_bytes = img_width * img_height * img_depth
with tf.name_scope('input'):
# 如果是训练就读训练文件(这里要分批次),是测试就读测试文件
if is_train:
filenames = [os.path.join(data_dir, 'data_batch_%d.bin' %ii)
for ii in np.arange(1, 6)]
else:
filenames = [os.path.join(data_dir, 'test_batch.bin')]
filename_queue = tf.train.string_input_producer(filenames)
# 加入队列,注意:猫狗数据大战加入队列用的是slice_input_producer([]),这个函数是传入列表,因为它的label和image不在一个文件里面
# 而这个数据是在一个里面
# 读取队列内容
reader = tf.FixedLengthRecordReader(label_bytes + image_bytes)
key, value = reader.read(filename_queue)
# 解码
record_bytes = tf.decode_raw(value, tf.uint8)
# 获得标签:从record_bytes切出来再转换成tf.int32
label = tf.slice(record_bytes, [0], [label_bytes])
label = tf.cast(label, tf.int32)
# 获得图像:从record_bytes切出来再重构size,并且转换成tf能识别的类型
image_raw = tf.slice(record_bytes, [label_bytes], [image_bytes])
image_raw = tf.reshape(image_raw, [img_depth, img_height, img_width])
image = tf.transpose(image_raw, (1, 2, 0)) # convert from D/H/W to H/W/D
image = tf.cast(image, tf.float32)
# # data argumentation(这里没做增强)
# image = tf.random_crop(image, [24, 24, 3])# randomly crop the image size to 24 x 24
# image = tf.image.random_flip_left_right(image)
# image = tf.image.random_brightness(image, max_delta=63)
# image = tf.image.random_contrast(image,lower=0.2,upper=1.8)
# 标准化数据,用了之后图像会很奇怪,用为值是0-1,要看原始图像需要注释掉这句
image = tf.image.per_image_standardization(image) # substract off the mean and divide by the variance
# 根据打乱顺序与否进行不同的batch
if shuffle:
images, label_batch = tf.train.shuffle_batch(
[image, label],
batch_size=batch_size,
num_threads=16,
capacity=2000,
min_after_dequeue=1500)
else:
images, label_batch = tf.train.batch(
[image, label],
batch_size=batch_size,
num_threads=16,
capacity=2000)
# 如果不用one-hot,就把这个return打开
# label_batch = tf.reshape(label_batch, [batch_size])
# return images, label_batch
# ONE-HOT,用下面的return。
#由于原始的标签是0-9的10个类别,将他换成one-hot编码
n_classes = 10
label_batch = tf.one_hot(label_batch, depth=n_classes)
label_batch = tf.reshape(label_batch, [batch_size, n_classes])
return images, label_batch
###测试,训练的时候需要注释掉下面的:快捷注释的方法,1.把要注释的折叠起来,选中然后Ctrl + '/'就ok
## 2.鼠标选中要注释的块,然后Ctrl + '/'。注意:网上很多说这种方法是Ctrl + shift+ '/',我试过不行
## 块注释有了,怎么块取消注释呢,很简单同注释的方法一样,再操作一下就好了
import matplotlib.pyplot as plt
data_dir = 'D:/Python/neural network/CIFAR10-Guoqingxu/data/'
BATCH_SIZE = 2
image_batch, label_batch = read_cifar10(data_dir,
is_train=True,
batch_size=BATCH_SIZE,
shuffle=True)
with tf.Session() as sess:
i = 0
#用coord和threads监控队列
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
try:
while not coord.should_stop() and i<1:
img, label = sess.run([image_batch, label_batch])
# just test one batch
for j in np.arange(BATCH_SIZE):
#print('label: %d' %label[j])
print('label: {}'.format(label[j]))
# 视频用的%d,会出错
plt.imshow(img[j,:,:,:])
plt.show()
i+=1
except tf.errors.OutOfRangeError:
print('done!')
finally:
coord.request_stop()
coord.join(threads)