TensorFlow 加载数据及预处理的几种方式 您所在的位置:网站首页 数据处理的几种方法 TensorFlow 加载数据及预处理的几种方式

TensorFlow 加载数据及预处理的几种方式

2024-06-10 11:13| 来源: 网络整理| 查看: 265

方式一:

通过代码直接加载压缩文件获取,这里以cifar10为例。首先压缩文件应放在相应的位置,然后通过代码实现加载并获取数据。注意两点:

这种加载方式看不到图片正如代码中所提示的那样,你所加载出的数据格式为 

方式二:

通过本地加载图片数据,并对图片进行预处理来实现数据的输入。所需要解决的问题如下:

如何将压缩包中的文件转换成图片拿到真正的图片后如何对图片进行预处理(主要是实现图片与标签的绑定,成为可用的训练数据)

首先压缩包中文件格式如下:

直接上转换为可用图片的代码。只需要注意,需要转换的图片数量,文件路径,根据图片标签建立目录即可。

import pickle as p import numpy as np from PIL import Image import os def load_cifar10(filename, num): with open(filename, 'rb')as f: datadict = p.load(f, encoding='latin1') images = datadict['data'] labels = datadict['labels'] images = images.reshape(num, 3, 32, 32) labels = np.array(labels) return images, labels.tolist() def load_cifar100(filename, num): ''' 字典属性: b’firename’:图片的文件名 b’batch_label’:图片对应批次 b’fine_labels’:0~99,对应图像分类的标签 b’coarse_labels’:0~19,对应图像超类的标签 b’data’:10000X3072的NumPy数组,每行表示一个图片实例,其中每个实例都以32(长)X32(宽)X3(RGB)表示。 ''' with open(filename, 'rb')as f: datadict = p.load(f, encoding='latin1') images = datadict['data'] labels = datadict['fine_labels'] images = images.reshape(num, 3, 32, 32) labels = np.array(labels) return images, labels.tolist() def load_labels_name(filename): with open(filename, 'rb') as f: lines = [x for x in f.readlines()] print(lines) if __name__ == "__main__": # test/train/ num = 50000 # 网络上得知训练集共有50000张图片 load_labels_name("./images/cifar_100/meta") images, labels = load_cifar100("./images/cifar_100/train", num) print(labels) # 从打印结果来看,我们可以得知标签数据为[0-99] 这也就与我们下面为什么要创建与标签对应的文件夹做铺垫 print(images.shape) print("正在保存图片:") all_name = [] #创建文件夹 path = 'E:/cishi/' for i in range(100): os.mkdir(path + str(i)) with open('E:cifar100_train.txt', 'w') as f: for i in range(num): imgs = images[i] img0 = imgs[0] img1 = imgs[1] img2 = imgs[2] i0 = Image.fromarray(img0) # 从数据,生成image对象 i1 = Image.fromarray(img1) i2 = Image.fromarray(img2) img = Image.merge("RGB", (i0, i1, i2)) name = "img" + str(i) + ".png" string = str(labels[i]) # 我怎么知道这张图片放到哪个目录下呢? 这句就是拿到这张图片的标签名,相同的标签放在相同的目录下。 img.save("E:/cishi/" + string + '/'+name, "png") # 文件夹下是RGB融合后的图像 f.write('E:/cishi/' + name + '\t' + str(labels[i]) + '\n') print("保存完毕.")

运行上述代码后你会看到如下数据。

现在解决问题2;如何将上述的图片数据弄成可用的图片数据呢,重要的是让网络知道上述图片数据要有标签。

# 数据预处理 def predataset(data_path): image_paths = list(data_path.glob('*/*')) image_paths = [str(path) for path in image_paths] random.shuffle(image_paths) image_count = len(image_paths) print(image_count) print(image_paths[:1]) # # 读取图片的同时,我们也不能忘记图片与标签的对应,要创建一个对应的列表来存放图片标签,不过,这里所说的标签不是daisy,而是数字 # daisy这些具体分类名,而是整型的索引,毕竟在建模的时候y值一般都是整型数据, # 所以要创建一个字典来建立分类名与标签的对应关系: # 这里有一个排序的动作,所以出现了混乱,我要是不排序呢,虽说标签对应的不合我意,但重要的是文件夹前面的名字 label_names = sorted(item.name for item in data_path.glob("*/") if item.is_dir()) #print(label_names) label_to_index = dict((name, index) for index, name in enumerate(label_names)) #print(label_to_index) # print(label_to_index['dandelion']) # index=[0,1,2,3] 就要是0到99了 # index = [0] * 10 # i = 0 # for i in range(10): # index[i] = i #print(index) # 因为只有1类 index = 0 index_to_label = dict((index, name) for index, name in enumerate(label_names)) # 观察label_to_index和index_to_label print(index_to_label) # print(index_to_label[0]) image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in image_paths] #for image, label in zip(image_paths[:5], image_labels[:5]): #print(image, "--->", label) return image_paths, image_labels, index_to_label def load_and_preprocess_from_path_label(path, label): image = tf.io.read_file(path) # 读取图片 image = tf.image.decode_png(image, channels=3) image = tf.image.resize(image, [32, 32]) # 原始图片大小为(266, 320, 3),重设为(192, 192) image /= 255.0 # 归一化到[0,1]范围 return image, label #创建dataset #加载路径 train_data_path = pathlib.Path('./minst_train') #数据预处理 实现图片与标签的绑定 (train_image_paths, train_image_labels, index_to_label) = predataset(train_data_path) # 数据格式这样的,实现切片 ds_train = tf.data.Dataset.from_tensor_slices((train_image_paths, train_image_labels)) # train_db 即为我们可用的数据集,但类型是上面这种。 train_db = ds_train.shuffle(1000).map(load_and_preprocess_from_path_label).batch(1) test_data_path = pathlib.Path('./minst_test') (test_image_paths, test_image_labels, index_to_label1) = predataset(test_data_path) ds_test = tf.data.Dataset.from_tensor_slices((test_image_paths, test_image_labels)) test_db = ds_test.map(load_and_preprocess_from_path_label).batch(128)

至此无论是从压缩包中加载,还是从本地图片数据加载,都完成了。

三、关于神经网络的搭建

自行写出 def __init__(self):  和 def call(self, x): 函数。然后使用modelname.comple()与modelname.fit()实现网络

关于model.fit()的用法如下:

上面我讲述了数据导入的两种方式,当我用第二种方式(本地图片处理),来使用model.fit()的时候,报错。经过一番查验,发现是数据格式的问题。

model.fit()中 x_train,y_train,x_test,y_test的数据格式为: 这种格式就是我们将的第一种数据导入方式。但我现在就是想用第二种数据格式,如何操作呢,如何转换成这种格式呢 # 创建dataset # 修改路径 train_data_path = pathlib.Path('./minst_train') (train_image_paths, train_image_labels, index_to_label) = predataset(train_data_path) ds_train = tf.data.Dataset.from_tensor_slices((train_image_paths, train_image_labels)) # train_db的格式是,是tensor的数据格式。那么我只要遍历train_db,先取出x,y,然后再将tensor转为numpy,再转为numpy.ndarray就好。 train_db = ds_train.shuffle(1000).map(load_and_preprocess_from_path_label) x_list = [] y_list = [] # 这里的step不能少,多亏了这里可以遍历train_db for step, (x, y) in enumerate(train_db): x.numpy() #tensor转为numpy y.numpy() x_list.append(x) # 列表的使用方法,追加 y_list.append(y) x_train = np.array(x_list) #list转为numpy.ndarray格式。 y_train = np.array(y_list)

上面讲述了一种网络的搭建方法。这种实现自写函数的搭建方法,使得神经网络比较灵活。下面还有一种通过容器Sequential的搭建方法。

conv_layers = [ # 5 units of conv + max pooling # unit 1 前面的这个64是啥? 参数是如何匹配的,64,128,256,,,,是啥,另外,我的输入是什么样的形式,怎么就能计算了呢? layers.Conv2D(64, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.Conv2D(64, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), # unit 2 layers.Conv2D(128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.Conv2D(128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), # unit 3 layers.Conv2D(256, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.Conv2D(256, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), # unit 4 图片中h,w会慢慢缩小,kernel会慢慢增大,而每一个像素所包含的信息量会增加 layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), # unit 5 保持512不变了,以免增大参数量 layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same') ] # sample = next(iter(train_db)) #这个sample又是干嘛的 # print('sample:', sample[0].shape, sample[1].shape, # tf.reduce_min(sample[0]), tf.reduce_max(sample[0])) #那我就建立batch,建立batch之后,我再看他的模样,解释为什么要 # 分类放在不同文件夹,是为了建立数据与标签的关系。 # [b, 32, 32, 3] => [b, 1, 1, 512] conv_net = Sequential(conv_layers) fc_net = Sequential([ layers.Dense(256, activation=tf.nn.relu), layers.Dense(128, activation=tf.nn.relu), layers.Dense(1, activation=None), ]) #没build之前的 model conv_net.build(input_shape=[None, 45, 45, 1]) # x=tf.random.normal([5,32,32,3]) # out=conv_net(x) # print(out.shape) fc_net.build(input_shape=[None, 512]) conv_net.summary() fc_net.summary() #optimizer选用Adam,参数1e-4,优化器是用来辅助梯度下降的。 #variables = conv_net.trainable_variables + fc_net.trainable_variables表示将两个网络给合并在一起,最后形成VGG13 #grads = tape.gradient(loss, variables);optimizer.apply_gradients(zip(grads, variables))中,loss选用交叉熵损失函数,对网络进行梯度求解,应用到apply_gradients方法,进行梯度下降。 optimizer = optimizers.Adam(lr=1e-4) # [1, 2] + [3, 4] => [1, 2, 3, 4] variables = conv_net.trainable_variables + fc_net.trainable_variables def trainimage(): for epoch in range(100): # 这个step是干嘛的 for step, (x, y) in enumerate(train_db): # train_db 就像切好了,一份一份的 50000/128=390 它遍历了所有的数据 # x[128,32,32,3] y[128,] with tf.GradientTape() as tape: # [b, 32, 32, 3] => [b, 1, 1, 512] out = conv_net(x) # flatten, => [b, 512] out = tf.reshape(out, [-1, 512]) # [b, 512] => [b, 100] logits = fc_net(out) # [b] => [b, 100] y_onehot = tf.one_hot(y, depth=1) # compute loss loss = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True) loss = tf.reduce_mean(loss) grads = tape.gradient(loss, variables) optimizer.apply_gradients(zip(grads, variables)) if step % 100 == 0: print(epoch, step, 'loss:', float(loss))

现在所存在的问题,对于卷积层数的设置,卷积核的数量,过滤器的数量,以及通道这些东西不了解,致使自己随意参数搭的网络根本跑不了。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有