【问题标题】:How to feed CNN with tf.data.Dataset如何为 CNN 提供 tf.data.Dataset
【发布时间】:2020-12-10 19:42:29
【问题描述】:

我是张量流的新手。我正在尝试为猫和狗之间的二元分类运行卷积神经网络。

数据的结构是这样的:在名为 data 的目录中,有两个子目录:testtrain。在每个子目录中都有两个(子)子目录,分别称为 catdog

我要做的是使用 tf.data.Dataset 导入图像并运行 CNN 对它们进行分类。

按照此 ref (https://towardsdatascience.com/tf-data-creating-data-input-pipelines-2913461078e2) 中建议的方法,我可以将数据作为 Dataset 对象导入并将其在图像和标签之间分开(我不确定它是否正确,我只是按照链接中提出的方法顺便问一下,有没有什么方法可以检查分离和贴标的过程是否正确执行?):

from glob import glob
import tensorflow as tf

IMAGE_PATH_LIST = glob('/Users/josea/Desktop/Deep_Learning/cats_dogs/training/*/*.jpg')
DATA = tf.data.Dataset.list_files(IMAGE_PATH_LIST)

def load_images(path):
    
    image = tf.io.read_file(path)
    image = tf.io.decode_image(image)
    label = tf.strings.split(path, os.path.sep)[-2]
    return image, label

DATA= DATA.map(load_images)

我有几个问题:首先,当我尝试运行 CNN 时(使用下面的脚本),它给出了一条错误消息“层序 4 的输入 0 与层不兼容:预期 ndim=4,发现 ndim= 3. 收到的完整形状:[None, 265, 3]"。

有人猜我做错了什么?此外,我想检查数据是否正确导入。有什么好的方法来评估吗?

我的 CNN 尝试如下所示:

model = Sequential()

model.add(Conv2D(64, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size = (2,2)))

model.add(Conv2D(64, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size = (2,2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))

model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])

model.fit(DATA)

提前致谢!

【问题讨论】:

    标签: python tensorflow keras conv-neural-network tf.data.dataset


    【解决方案1】:

    您需要批量处理数据:

    DATA= DATA.map(load_images).batch(16)
    

    您可能会遇到错误,因为您的目标似乎是一个字符串。您可以使用这样的函数将路径转换为标签:

    def load_images(path):
        image = tf.io.read_file(path)
        image = tf.io.decode_jpeg(image)
        image = tf.image.convert_image_dtype(image, tf.float32)
        image = tf.image.resize(image, (224, 224))
    
        parts = tf.strings.split(path, os.path.sep)
        bool_values = tf.equal(parts[-2], 'cats')
        indices = tf.cast(bool_values, tf.int32)
        return image, indices
    

    完整示例:

    import tensorflow as tf
    import os
    os.chdir('pictures')
    
    files = tf.data.Dataset.list_files('*jpg')
    
    def load_images(path):
        image = tf.io.read_file(path)
        image = tf.io.decode_jpeg(image)
        image = tf.image.convert_image_dtype(image, tf.float32)
        image = tf.image.resize(image, (224, 224))
    
        parts = tf.strings.split(path, os.path.sep)
        bool_values = tf.equal(parts[-2], 'cats')
        indices = tf.cast(bool_values, tf.int32)
        return image, indices
    
    ds = files.map(load_images).batch(1)
    
    next(iter(ds))
    
    (<tf.Tensor: shape=(1, 224, 224, 3), dtype=float32, numpy=
     array([[[[0.75831336, 0.8016107 , 0.72746104],
              [0.8311225 , 0.87016815, 0.79833937],
              [0.79161674, 0.8425971 , 0.77475995],
              ...,
              [0.08725347, 0.10316982, 0.11867575],
              [0.09943968, 0.1140053 , 0.1350136 ],
              [0.1064626 , 0.12102822, 0.14707875]]]], dtype=float32)>,
     <tf.Tensor: shape=(1,), dtype=int32, numpy=array([0])>)
    

    【讨论】:

    • 非常感谢您的反馈。我已经实现了你建议的这个功能,但不幸的是现在出现了另一个错误:“InvalidArgumentError:WhereOp:未处理的输入尺寸:0”。我查看了其他博客,发现建议将 .eval() 用于 tf.where(即 ``` indices = tf.where(bool_values).eval())。但是这种新方法会出现另一条错误消息:“无法使用eval()评估张量:未注册默认会话。使用with sess.as_default()或将显式会话传递给eval(session=sess)”。有什么猜测吗?
    • 除了这个错误,我对如何用这个数据集输入 CNN 模型也有点困惑。我应该简单地使用model.fit(DATA) 还是需要更多输入才能正确运行配件?
    • 我改了。对于你的最后一个问题,是的。
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 2018-10-14
    • 2021-10-26
    • 2020-09-16
    • 2020-08-28
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    相关资源
    最近更新 更多