读书笔记《Deep Learning for Computer Vision with Python》- 第二卷 第8章 使用HDF5和大型数据集

下载地址

链接:https://pan.baidu.com/s/1hqtBQf6jRJINx4AgB8S2Tw 
提取码:zxkt 

        第二卷 第八章 使用HDF5和大型数据集

        到目前为止,在本书中,我们只使用了适合我们机器主内存的数据集。对于小数据集,这是一个合理的假设——我们只需加载每个单独的图像,对其进行预处理,并允许它通过我们的网络馈送。然而,对于大规模深度学习数据集(例如ImageNet),我们需要创建一次只访问数据集的一部分(即小批量)的数据生成器,然后允许该批次通过网络。

        幸运的是,Keras附带的方法允许您使用磁盘上的原始文件路径作为训练过程的输入。您不必将整个数据集存储在内存中——只需将图像路径提供给Keras数据生成器,您的图像将分批加载并通过网络馈送。

        然而,这种方法效率极低。驻留在磁盘上的每个图像都需要I/O操作,这会给训练管道带来延迟。训练深度学习网络已经足够慢了——我们会尽可能地避免I/O瓶颈。

        一个更优雅的解决方案是为原始图像生成HDF5数据集,就像我们在第3章关于迁移学习和特征提取中所做的那样,只是这次我们存储图像本身而不是提取的特征。HDF5不仅能够存储海量数据集,而且还针对I/O操作进行了优化,尤其是从文件中提取批次(称为“切片”)。正如我们将在本书的其余部分看到的那样,采取额外步骤将驻留在磁盘上的原始图像打包到HDF5文件中,这使我们能够构建一个深度学习框架,该框架可用于快速构建数据集和训练深度学习网络在他们之上。

        在本章的其余部分,我将演示如何为Kaggle Dogs vs Cats比赛构建HDF5数据集。然后,在下一章中,我们将使用这个HDF5数据集来训练AlexNet架构,最终在下一章的排行榜上获得较好的位置。

        1、下载Kaggle:狗与猫

        要下载Kaggle Dogs vs Cats数据集,您首先需要在kaggle.com上创建一个帐户。从那里,前往Dogs vs Cats主页。

Dogs vs. Cats | Kagglehttps://www.kaggle.com/c/dogs-vs-cats/data        需要下载train.zip。不要下载test1.zip。test1.zip中的图片仅用于计算预测并提交给Kaggle评估服务器。由于我们需要类标签来构建我们自己的训练和测试分割,因此我们只需要train.zip。提交您自己的预测结果超出了本书的范围,但可以通过按照sampleSubmission.csv中概述的文件格式在test1.zip上编写您的预测来轻松完成。

        下载train.zip后,将其解压缩,您将找到一个名为train的目录——该目录包含我们的实际图像。标签本身可以通过检查文件名获得。我已经包含了以下文件名的示例:

读书笔记《Deep Learning for Computer Vision with Python》- 第二卷 第8章 使用HDF5和大型数据集_第1张图片

        2、创建一个配置文件

        这里是Kaggle Dogs vs.Cats项目的目录结构(其中一些python脚本再下一张会介绍):

读书笔记《Deep Learning for Computer Vision with Python》- 第二卷 第8章 使用HDF5和大型数据集_第2张图片

         先来说Dogs_vs_cats_config.py的配置文件,主要包含以下内容:

        1.输入图像的路径。

        2.类标签的总数。

        3.有关训练、验证和测试拆分的信息。

        4.HDF5数据集的路径。

        5.输出模型、绘图、日志等的路径。

        使用Python文件而不是JSON文件允许我包含Python代码片段并使配置文件更有效地使用(一个很好的例子是使用os.path模块操作文件路径)。我建议您养成在自己的深度学习项目中使用基于Python的配置文件的习惯,因为这将大大提高您的工作效率,并允许您通过单个文件控制项目中的大部分参数。

        参考代码如下:

# define the paths to the images directory
IMAGES_PATH = "../datasets/kaggle_dogs_vs_cats/train"

# since we do not have validation data or access to the testing
# labels we need to take a number of images from the training
# data and use them instead
NUM_CLASSES = 2
NUM_VAL_IMAGES = 1250 * NUM_CLASSES
NUM_TEST_IMAGES = 1250 * NUM_CLASSES

# define the path to the output training, validation, and testing
# HDF5 files
TRAIN_HDF5 = "../datasets/kaggle_dogs_vs_cats/hdf5/train.hdf5"
VAL_HDF5 = "../datasets/kaggle_dogs_vs_cats/hdf5/val.hdf5"
TEST_HDF5 = "../datasets/kaggle_dogs_vs_cats/hdf5/test.hdf5"

# path to the output model file
MODEL_PATH = "output/alexnet_dogs_vs_cats.model"

# define the path to the dataset mean
DATASET_MEAN = "output/dogs_vs_cats_mean.json"

# define the path to the output directory used for storing plots,
# classification reports, etc.
OUTPUT_PATH = "output"

        在第2行,我定义了包含狗和猫图像的目录的路径——这些是我们将在本章后面打包到HDF5数据集的图像。

        第7-9行定义了类别标签的总数(两个:一个用于狗,另一个用于猫)以及验证和测试图像的数量(每个为2,500)。

        第13-15行为训练、验证和测试拆分指定输出HDF5文件的路径。

        配置文件的后半部分定义了输出序列化权重的路径、数据集均值以及用于存储图、分类报告、日志等的路径。

        DATASET_MEAN文件将用于存储整个(训练)数据集的平均红色、绿色和蓝色像素强度值。当我们训练我们的网络时,我们将从图像中的每个像素中减去平均RGB值(测试和评估也是如此)。该方法中,所谓的平均减法,是一种类型的数据归一化技术的和更常用比缩放的像素强度的范围[0,1],因为它对大数据集和更深的神经网络更有效。

        3、构建dataset

        现在我们的配置文件已经定义,让我们继续实际构建我们的HDF5数据集。打开一个新文件,命名为build_dogs_vs_cats.py,如下代码:

# import the necessary packages
import sys, os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  
# __file__获取执行文件相对路径,整行为取上一级的上一级目录
sys.path.append(BASE_DIR)

import dogs_vs_cats_config as config
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from customize.tools.aspectawarepreprocessor import AspectAwarePreprocessor
from hdf5DatasetWriter import HDF5DatasetWriter
from imutils import paths
import numpy as np
import progressbar
import json
import cv2

# grab the paths to the images
trainPaths = list(paths.list_images(config.IMAGES_PATH))
# 这里要注意路径是否正确,不要得到不正确的label
# 我之前就因为vscode环境问题,导致得到的标签不正确,浪费了很久才找到原因
trainLabels = [p.split(os.path.sep)[2].split(".")[0]
    for p in trainPaths]
le = LabelEncoder()
trainLabels = le.fit_transform(trainLabels)

# perform stratified sampling from the training set to build the
# testing split from the training data
split = train_test_split(trainPaths, trainLabels, test_size=config.NUM_TEST_IMAGES, stratify=trainLabels, random_state=42)
(trainPaths, testPaths, trainLabels, testLabels) = split

# perform another stratified sampling, this time to build the
# validation data
split = train_test_split(trainPaths, trainLabels, test_size=config.NUM_VAL_IMAGES, stratify=trainLabels, random_state=42)
(trainPaths, valPaths, trainLabels, valLabels) = split

# construct a list pairing the training, validation, and testing
# image paths along with their corresponding labels and output HDF5
# files
datasets = [
("train", trainPaths, trainLabels, config.TRAIN_HDF5),
("val", valPaths, valLabels, config.VAL_HDF5),
("test", testPaths, testLabels, config.TEST_HDF5)]

# initialize the image preprocessor and the lists of RGB channel
# averages
aap = AspectAwarePreprocessor(256, 256)
(R, G, B) = ([], [], [])

# loop over the dataset tuples
for (dType, paths, labels, outputPath) in datasets:
    # create HDF5 writer
    print("[INFO] building {}...".format(outputPath))
    writer = HDF5DatasetWriter((len(paths), 256, 256, 3), outputPath)

    # initialize the progress bar
    widgets = ["Building Dataset: ", progressbar.Percentage(), " ", progressbar.Bar(), " ", progressbar.ETA()]
    pbar = progressbar.ProgressBar(maxval=len(paths), widgets=widgets).start()

    # loop over the image paths
    for (i, (path, label)) in enumerate(zip(paths, labels)):
        # load the image and process it
        image = cv2.imread(path)
        image = aap.preprocess(image)

        # if we are building the training dataset, then compute the
        # mean of each channel in the image, then update the
        # respective lists
        if dType == "train":
            (b, g, r) = cv2.mean(image)[:3]
            R.append(r)
            G.append(g)
            B.append(b)

        # add the image and label # to the HDF5 dataset
        writer.add([image], [label])
        pbar.update(i)

    # close the HDF5 writer
    pbar.finish()
    writer.close()

# construct a dictionary of averages, then serialize the means to a
# JSON file
print("[INFO] serializing means...")
D = {"R": np.mean(R), "G": np.mean(G), "B": np.mean(B)}
f = open(config.DATASET_MEAN, "w")
f.write(json.dumps(D))
f.close()

        运行代码,会生成hdf5文件。 

读书笔记《Deep Learning for Computer Vision with Python》- 第二卷 第8章 使用HDF5和大型数据集_第3张图片

         生成的hdf5文件,train.hdf5,30个G,主要是将图像解压缩到原始数据(JPEG和PNG等原始图像文件格式应用数据压缩算法来保持较小的图像文件大小)。缺乏压缩会大大增加我们的存储成本,但也有助于加快我们的训练时间,因为我们不必浪费处理器时间来解码图像——我们可以直接从HDF5数据集访问图像,对其进行预处理,然后通过我们的网络。        同时还生成了dogs_vs_cats_mean.json文件,包含如下内容,这个RGB是所有图像的RGB平均像素值。我们将构建一个新的图像预处理器,通过在输入图像通过我们的网络之前从输入图像中减去这些RGB平均值来规范化我们的图像。这种均值归一化有助于将数据“集中”在零均值附近。通常,这种归一化使我们的网络能够更快地学习,这也是我们在更大、更具挑战性的数据集上使用这种类型的归一化(而不是[0,1]缩放)的原因。

{"R": 125.03920054779053, "G": 115.98626419296265, "B": 106.16002079620361}

        4、小结

        在本章中,我们学习了如何将原始图像序列化为适合训练深度神经网络的HDF5数据集。我们在训练时将原始图像序列化为HDF5文件而不是简单地访问磁盘上的小批量图像路径的原因是由于I/O延迟——对于磁盘上的每个图像,我们必须执行I/O操作才能读取图片。这种微妙的优化似乎没什么大不了的,但I/O延迟是深度学习管道中的一个大问题——训练过程已经足够慢了。

        相反,如果我们将所有图像序列化为一个高效打包的HDF5文件,我们可以利用非常快的阵列切片来提取我们的小批量,从而显着降低I/O延迟并帮助加快训练过程。

        每当您使用Keras库并处理太大而无法放入内存的数据集时,请务必先考虑将数据集序列化为HDF5格式——正如我们将在下一章中发现的那样,它使您的网络训练变得更容易(和更有效)任务。

你可能感兴趣的:(#,读书笔记,深度学习,python,hdf5,数据集,神经网络)