CIFAR10数据集下载地址
cifar10_process.py
import pickle
import numpy as np
import cv2
import os
def unpickle(file:str)->str :
'''
但是这个函数是返回一个dict,其中存储着图片。
'''
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')# 用这种方式打开,还是需要额外设一个变量fo。但是逻辑更清楚一些
return dict
def unpack_image(datapath, save_path):
'''
这段代码用于读取加载处理保存用二进制pickle方式存储的数据
'''
for path in datapath:
raw_data = unpickle(path)
images = raw_data[b'data'].reshape(10000,3,32,32).transpose(0,2,3,1)
filenames = raw_data[b'filenames']
nums = np.linspace(0, images.shape[0], images.shape[0], endpoint= False).tolist()
for num, filename in zip(nums, filenames):
path_withname = os.path.join(save_path, str(filename,encoding= 'utf-8'))# 这是路径名,用于存储图片
cv2.imwrite(path_withname, images[int(num),:,:,:])
def unpack_classname(datapath:str)->dict:
'''
这段代码用于读取类文件,并做成字典
'''
raw_data = unpickle(datapath)
raw_data = raw_data[b'label_names']
length = np.linspace(0,len(raw_data),len(raw_data),endpoint=False)
return {str(i,encoding='utf-8'):int(j) for i,j in zip(raw_data, length)}
PATH_DATAROOT = '/home/kiwixu/Research/CIFAR10'
PATH_TRAIN_DATA = PATH_DATAROOT + '/train'
PATH_TEST_DATA = PATH_DATAROOT + '/test'
PATH_CLASS_DATA = PATH_DATAROOT + '/batches.meta'
files = os.listdir(PATH_DATAROOT)
if not os.path.exists(PATH_TRAIN_DATA):
os.makedirs(PATH_TRAIN_DATA)
if not os.path.exists(PATH_TEST_DATA):
os.makedirs(PATH_TEST_DATA)
# 存放待解压文件路径
path_traindatas = []
class_names = []
path_testdatas = []
# 从文件夹下读文件名字
for file in files:
if file.endswith(('0','1','2','3','4','5','6','7','8','9')):
path_traindatas.append(file)
if file.endswith('meta'):
class_names.append(file)
if file.endswith('batch'):
path_testdatas.append(file)
'''
我为什么要这么写代码:
因为train已经执行过了,而test还没执行。我想要
再跑一次这段代码,但是换成test。封装成函数就可
以只修改少量的变量而复用代码。这样我只要在下方
注释掉traindata那一行,我就可以避免再跑一次
train数据集的代码了。
'''
path_traindata = [os.path.join(PATH_DATAROOT,x) for x in path_traindatas]
path_testdata = [os.path.join(PATH_DATAROOT,x) for x in path_testdatas]
unpack_image(path_traindata,PATH_TRAIN_DATA)
unpack_image(path_testdata,PATH_TEST_DATA)
class_dict = unpack_classname(PATH_CLASS_DATA)
print(class_dict.items())
这次的代码书写过程有体验很明显的再封装过程:先书写了unpack_image的函数体主体,最后封装成一个函数,修改参数,方便多次调用。这是个代码书写的合理过程。
CIFAR10的二进制数据解码后得到的data字典和label字典并不像doc里描述的那样,而是有更多的key。通过增量更新的方式写代码,配合sys.exit()可以减少很多bug,让代码写起来更愉快。