深度学习笔记:tf.keras.preprocessing.image_dataset_from_directory运行错误

Posted 笨牛慢耕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度学习笔记:tf.keras.preprocessing.image_dataset_from_directory运行错误相关的知识,希望对你有一定的参考价值。

目录

1. 概要

2. 问题描述        

2.1 数据集下载和预处理

2.2 用image_dataset_from_directory加载数据

2.3 生成的三个数据集中的batch数不对?

3. 后记


1. 概要

        被tf.keras.preprocessing.image_dataset_from_directory逼疯了。。。

        昨天刚写了一个博客,记录学习使用image_dataset_from_directory从目录中加载大型数据集的过程,觉得感觉不错。今天准备正式用用这个做一个深度学习模型训练实验,自信满满地开始,然后。。。遭到了暴击。。。先记录一下这个问题,不知道有没有人碰到过同样的问题。        

2. 问题描述        

2.1 数据集下载和预处理

        实验用数据集:猫狗数据集(cats-vs-dogs)

        关于下载参见:深度学习笔记:Tensorflow BatchDataset应用示例

        原始数据包存放于cats_vs_dogs目录下,其中包含cats和dogs两个子目录

        为了迎合image_dataset_from_directory()的使用,基于以下代码处理从原始数据集中取一部分分别构成train, test和validation set,目录结构如下所示,每个下面都进一步包含cats和dogs两个子目录。 

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import utils

print(tf.__version__)

def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        src_dir = original_dir / category
        print(dir)
        os.makedirs(dir)
        fnames = [f"i.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=src_dir / fname, dst=dir / fname)
import os, shutil, pathlib

original_dir = pathlib.Path("F:\\DL\\cats-vs-dogs")
new_base_dir = pathlib.Path("F:\\DL\\cats_vs_dogs_small")

print(original_dir, new_base_dir)

if not os.path.exists(new_base_dir):
    make_subset("train", start_index=0, end_index=1000)
    make_subset("validation", start_index=1000, end_index=1500)
    make_subset("test", start_index=1500, end_index=2500)
else:
    print('0 already exists, no need to copy the data again!'.format(new_base_dir))

        运行完后会得到如下目录结构:

2.2 用image_dataset_from_directory加载数据

from tensorflow.keras.preprocessing import image_dataset_from_directory

train_dataset = image_dataset_from_directory(
    new_base_dir / "train",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    new_base_dir / "validation",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    new_base_dir / "test",
    image_size=(180, 180),
    batch_size=32)

        到此为止,一切都在掌握之中。。。 

2.3 生成的三个数据集中的batch数不对?

        接下来用train_dataset进行模型训练时,运行到中途报告错误退出了,似乎是运行到一个epoch的中途没有数据了。莫名其妙。。。百思不得其解。于是回头来查看以上image_dataset_from_directory()所生成的三个数据集的内容是否正确,我用以下代码来确认以上三个数据集中的batch数是不是正确。

k = 0
for next_batch in test_dataset:
    print('k = ', k)
    k = k + 1
print(k)

。。。

        我勒个去。。。正常来说,test目录底下由2000张照片,每个batch有32张,应该有ceil(2000/32)=63个batch,可以以上运行到k=41就出错退出了。而且报出的错误是个什么鬼嘛?

        接下来看看train_dataset什么情况:

k = 0
for next_batch in train_dataset:
    print('k = ', k)
    k = k + 1
print(k)

        运行到k=37时退出,但是报告的错误跟上面的test_dataset还不一样:

         然后是validation_dataset什么情况:

k = 0
for next_batch in validation_dataset:
    print('k = ', k)
    k = k + 1
print(k)

        这个运行到k=31正常退出,ceil(1000/32) =32符合预期(因为k是从0开始计数的)

        三个dataset有两个有问题,两个有问题的数据集所报告的错误信息还不一样。最关键的是,当我重复运行的话,每次出错的情况并不一样(test_dataset和train_dataset出错退出时的k值不一样)。。。

3. 后记

        到目前为止,我一直有一个坚定的信仰:不管你碰到什么样的问题,总可以相信一定有人已经碰到过了,并且已经给出解决方案,就在万能的互联网的某个角落。但是这次这个,各种搜索啊,墙内墙外啊,中文英文啊。。。没有找到描述同样或类似问题的博客或者论坛帖子或者任何什么。。。不敢相信居然有这么好的‘运气’。

        在做完以上记录后我想到了一种可能性:

        我从微软网站上下载的猫狗数据集本身有问题,而恰好validation中的1000张照片是全部好照片,而train/test中则包含有错误的照片,因此每次重复运行(并没有重新创建cats_vs_dog_small目录结构)以上测试代码时,validation_dataset都没有问题,而train/test_dataset由于image_dataset_from_directory的随机性处理使得问题照片出现的batch的顺序号不同。

        以上可能性有待进一步验证。

        

        

以上是关于深度学习笔记:tf.keras.preprocessing.image_dataset_from_directory运行错误的主要内容,如果未能解决你的问题,请参考以下文章

《繁凡的深度学习笔记》前言目录大纲 一文弄懂深度学习所有基础

《繁凡的深度学习笔记》前言目录大纲 一文弄懂深度学习所有基础

深度学习深度学习基础学习笔记

深度学习笔记:Encoder-Decoder模型和Attention模型

深度学习笔记:归一化问题总结

深度学习笔记:优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam)