使用TensorFlow IMAGE_DataSet_From_DIRECTORY时从数据集中获取标注 [英] Get labels from dataset when using tensorflow image_dataset_from_directory

查看:0
本文介绍了使用TensorFlow IMAGE_DataSet_From_DIRECTORY时从数据集中获取标注的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用TensorFlow(2.4版)+KERAS(3.8.3版)编写了一个简单的CNN。我正在努力优化网络,我想要更多关于它无法预测的信息。我正在尝试添加混淆矩阵,并且我需要为tensorflow.math.conflomination_Matrix()提供测试标签。

我的问题是,我不知道如何从tf.keras.preprocessing.image_dataset_from_directory()

创建的DataSet对象访问标签

我的图像被组织在以标签作为名称的目录中。文档说明该函数返回tf.data.Dataset对象。

If label_mode is None, it yields float32 tensors of shape (batch_size, image_size[0], image_size[1], num_channels), encoding

图像(有关num_Channel的规则见下文)。 否则,它将生成一个元组(图像、标签),其中图像具有形状(Batch_Size、Image_Size[0]、Image_Size[1]、Num_Channels)和 标签遵循下面描述的格式。

代码如下:

import tensorflow as tf
from tensorflow.keras import layers
#import matplotlib.pyplot as plt
import numpy as np
import random

import PIL
import PIL.Image

import os
import pathlib

#load the IMAGES
dataDirectory = '/p/home/username/tensorflow/newBirds'

dataDirectory = pathlib.Path(dataDirectory)
imageCount = len(list(dataDirectory.glob('*/*.jpg')))
print('Image count: {0}
'.format(imageCount))

#test display an image
# osprey = list(dataDirectory.glob('OSPREY/*'))
# ospreyImage = PIL.Image.open(str(osprey[random.randint(1,100)]))
# ospreyImage.show()

# nFlicker = list(dataDirectory.glob('NORTHERN FLICKER/*'))
# nFlickerImage = PIL.Image.open(str(nFlicker[random.randint(1,100)]))
# nFlickerImage.show()

#set parameters
batchSize = 32
height=224
width=224

(trainData, trainLabels) = tf.keras.preprocessing.image_dataset_from_directory(
    dataDirectory,
    labels='inferred',
    label_mode='categorical',
    validation_split=0.2,
    subset='training',
    seed=324893,
    image_size=(height,width),
    batch_size=batchSize)

testData = tf.keras.preprocessing.image_dataset_from_directory(
    dataDirectory,
    labels='inferred',
    label_mode='categorical',
    validation_split=0.2,
    subset='validation',
    seed=324893,
    image_size=(height,width),
    batch_size=batchSize)

#class names and sampling a few images
classes = trainData.class_names
testClasses = testData.class_names
#plt.figure(figsize=(10,10))
# for images, labels in trainData.take(1):
#     for i in range(9):
#         ax = plt.subplot(3, 3, i+1)
#         plt.imshow(images[i].numpy().astype("uint8"))
#         plt.title(classes[labels[i]])
#         plt.axis("off")
# plt.show()

#buffer to hold the data in memory for faster performance
autotune = tf.data.experimental.AUTOTUNE
trainData = trainData.cache().shuffle(1000).prefetch(buffer_size=autotune)
testData = testData.cache().prefetch(buffer_size=autotune)

#augment the dataset with zoomed and rotated images
#use convolutional layers to maintain spatial information about the images
#use max pool layers to reduce
#flatten and then apply a dense layer to predict classes
model = tf.keras.Sequential([
    #layers.experimental.preprocessing.RandomFlip('horizontal', input_shape=(height, width, 3)),
    #layers.experimental.preprocessing.RandomRotation(0.1),
    #layers.experimental.preprocessing.RandomZoom(0.1),
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(height, width, 3)),
    layers.Conv2D(16, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(64, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(128, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(256, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    # layers.Conv2D(512, 3, padding='same', activation='relu'),
    # layers.MaxPooling2D(),
    #layers.Conv2D(1024, 3, padding='same', activation='relu'),
    #layers.MaxPooling2D(),
    #dropout prevents overtraining by not allowing each node to see each datapoint
    #layers.Dropout(0.5),
    layers.Flatten(),
    layers.Dense(512, activation='relu'),
    layers.Dense(len(classes))
    ])

model.compile(optimizer='adam',
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.summary()
    
epochs=2
history = model.fit(
    trainData,
    validation_data=testData,
    epochs=epochs
    )

#create confusion matrix
predictions = model.predict_classes(testData)
confusionMatrix = tf.math.confusion_matrix(labels=testClasses, predictions=predictions).numpy()

我尝试使用(foo,foo1)=tf.keras.preprocessing.image_dataset_from_directory(dataDirectory,等),但得到 (Train Data,Train Labels)=tf.keras.preprocessing.image_dataset_from_directory( ValueError:要解包的值太多(应为%2)

如果我尝试作为一个变量返回,然后按如下方式拆分它:

train = tf.keras.preprocessing.image_dataset_from_directory(
    dataDirectory,
    labels='inferred',
    label_mode='categorical',
    validation_split=0.2,
    subset='training',
    seed=324893,
    image_size=(height,width),
    batch_size=batchSize)
trainData = train[0]
trainLabels = train[1]

我遇到TypeError:‘BatchDataset’对象不可订阅

我可以通过testClass=testData.CLASS_NAMES访问标签,但我得到:

2020-11-03 14:15:14.643300:W TensorFlow/core/framework/op_kernel.cc:1740]op_Requires在以下位置失败 Cast_op.cc:121:未实现:不支持将字符串转换为int64 回溯(最近一次调用):文件;BirdFake.py;第115行,在 ConfusionMatrix=tf.math.convension_Matrix(Labels=测试类,Predictions=预测).numpy()文件 ";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py";, 第201行,包装中 返回目标(*args,**kwargs)文件";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/ops/confusion_matrix.py";, 第159行,在混淆矩阵中 Label=Math_ops.cast(Labels,dtyes.int64)文件";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py";, 第201行,包装中 返回目标(*args,**kwargs)文件";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/ops/math_ops.py";, 第966行,演员阵容 X=gen_ath_ops.cast(x,base_type,";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/ops/gen_math_ops.py";,=名称)文件类型 第1827行,演员阵容 _ops.raise_from_not_ok_Status(e,名称)文件";/p/home/username/miniconda3/lib/python3.8/site-packages/tensorflow/python/framework/ops.py";, 第6862行,状态为RAISE_FROM_NOT_OK_STATUS Six.raise_from(core._status_to_exception(e.code,消息),无)文件,第3行,RAISE_FROM中 Tensorflow.python.framework.errors_impl.UnimplementedError:Cast 不支持int64的字符串[Op:Cast]

我对任何将这些标签放入混淆矩阵的方法持开放态度。任何关于我所做的事情为什么不起作用的想法也将不胜感激。

更新:我尝试了Alexandre Catalano提出的方法,得到以下错误

回溯(最近一次调用):文件";./BirdFake.py";,第118行, 在……里面 Labels=np.comatenate([Labels,np.argmax(y.numpy(),axis=-1)])文件&;<;ARRAY_Function内部,第5行,串联 ValueError:所有输入数组的维度必须相同, 但索引0处的数组具有1维,而索引1处的数组 有0个维度

我打印了标签数组的第一个元素,它是零

推荐答案

如果我是您,我会迭代整个测试数据,一路上保存预测和标签,最后构建混淆矩阵。

testData = tf.keras.preprocessing.image_dataset_from_directory(
    dataDirectory,
    labels='inferred',
    label_mode='categorical',
    seed=324893,
    image_size=(height,width),
    batch_size=32)


predictions = np.array([])
labels =  np.array([])
for x, y in testData:
  predictions = np.concatenate([predictions, model.predict_classes(x)])
  labels = np.concatenate([labels, np.argmax(y.numpy(), axis=-1)])

tf.math.confusion_matrix(labels=labels, predictions=predictions).numpy()

,结果为

Found 4 files belonging to 2 classes.
array([[2, 0],
       [2, 0]], dtype=int32)

这篇关于使用TensorFlow IMAGE_DataSet_From_DIRECTORY时从数据集中获取标注的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆