0

I'm new with tensorflow. i'm trying to run the convolutional neural network for the binary classifitication between cats and dogs.

The data is structured this way: within a directory called data, there are two subdirectories: test and train. within each subdirectory there are two (sub)subdirectories called cat and dog.

What I'm trying to do is to use tf.data.Dataset to import the images and run the CNN to classify them.

Following the approach suggested in this ref (https://towardsdatascience.com/tf-data-creating-data-input-pipelines-2913461078e2) I could import the data as a Dataset object and separate it between image and label (I'm not sure if it's right, I simply followed the approach proposed in the link above. By the way, is there any method to check if the process of separation and labeling is being correctly performed?):

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)

I have a few questions: first, when I try to run the CNN (using the script below), it's given a error message "Input 0 of layer sequential_4 is incompatible with the layer: expected ndim=4, found ndim=3. Full shape received: [None, 265, 3]".

Someone guess what am I doing wrong? Additionally, I'd like to check if the data is being correctly imported. Is there any good way to assess that?

my CNN attempt is shown below:

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)

Thanks in advance!

Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143

1 Answers1

1

You need to batch your data:

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

You might face an error because your target seems to be a string. You can use a function like this to convert the path to a label:

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

Full example:

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])>)
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
  • Many thanks for you feedback. I've implemented this function you suggested but unfortunally now another error appears: "InvalidArgumentError: WhereOp : Unhandled input dimensions: 0". I've checking in other blogs and I found the suggestion of using _.eval()_ for tf.where (i.e., ``` indices = tf.where(bool_values).eval()). But another error message appears for this new approach: " Cannot evaluate tensor using `eval()`: No default session is registered. Use `with sess.as_default()` or pass an explicit session to `eval(session=sess)`". Any guess? – Jose Augusto Devienne Dec 10 '20 at 23:27
  • Besides this error, I'm also a little confused on how to feed the CNN model with this dataset. Should I simply use ```model.fit(DATA)``` or more inputs are required to properly run the fitting? – Jose Augusto Devienne Dec 10 '20 at 23:28
  • I changed it. For your last question, yes. – Nicolas Gervais Dec 11 '20 at 01:04
  • @NicolasGervais Why have you used the value `16` in `.batch(16)`? What does it depend on? – maciejwww Jun 27 '22 at 00:03
  • You should use the largest batch size that fits on yout machine. For this code to work, you need at least 1. – Nicolas Gervais Jun 27 '22 at 11:42