0
votes

I am doing a simple image classification, in which I wish to put images into one of 16 classes. My labels are 16-long, one-hot ndarrays.

When I call fit(), it becomes clear that the model is expecting 16 samples, not one label consisting of one array of size 16. I am at a loss to understand what magic I need to tell Keras what I am feeding it.

Code and spew follows. Try to ignore the irrelevant sizes passed to Dense(), this is just a toy project. I am intentionally passing in batches of one sample at a time.

def main():
FLAGS, unparsed = ut.parseArgs()
print(FLAGS)
# TEST_DATA_PATH      = FLAGS.test_data_path
SAMPLE_FILE = FLAGS.train_data_path + FLAGS.sample
IMG_SHAPE   = ut.get_image_shape(filename=SAMPLE_FILE, scale=FLAGS.scale, show=FLAGS.show)
img = ut.read_image(filename=SAMPLE_FILE, show=False)
img = np.array(img)
IMG_SHAPE=img.shape
(x_train, y_train), (x_test, y_test)=load_data(numclasses=FLAGS.numclasses, train_path=FLAGS.train_data_path, sample_file=SAMPLE_FILE, onehot=True)


model = tf.keras.models.Sequential()


print(f'IMG_SHAPE:{IMG_SHAPE},  y_train shape:{y_train[0].shape}')

model.add(tf.keras.layers.Dense(256,activation='relu',input_shape=IMG_SHAPE, name='d1'))
model.add(tf.keras.layers.Dense(64, activation='sigmoid', name='d2'))
model.add(tf.keras.layers.Flatten(data_format='channels_last'))
model.add(tf.keras.layers.Dense(32, activation='softmax', name='d3'))

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

model.summary()
for nx in range(len(x_train)):
    file = x_train[nx]
    img = ut.read_image(filename=FLAGS.train_data_path+file, show=False)
    img=np.array(img)
    img = np.expand_dims(img, axis=0)
    model.fit(x=img, y=y_train[nx],verbose=2)

Here is the puke:

"C:\Users\WascallyWabbit\AppData\Local\Programs\Python\Python36\python.exe" "C:/Users/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py" Namespace(batch_size=4, epochs=1, learning_rate=0.01, numclasses=16, sample='0cdf5b5d0ce1_01.jpg', scale=1.0, show=False, target='mnist', tb_dir='/Users/WascallyWabbit/tensorlog/', test_data_path='/Users/WascallyWabbit/Downloads/carvana/test/', train_data_path='/Users/WascallyWabbit/Downloads/carvana/train/') IMG_SHAPE:(1280, 1918, 2), y_train shape:(16,) _________________________________________________________________ Layer (type) Output Shape Param #
================================================================= d1 (Dense) (None, 1280, 1918, 256) 768
_________________________________________________________________ d2 (Dense) (None, 1280, 1918, 64) 16448
_________________________________________________________________ flatten (Flatten) (None, 157122560) 0
_________________________________________________________________ d3 (Dense) (None, 32) 732954656 ================================================================= Total params: 732,971,872 Trainable params: 732,971,872 Non-trainable params: 0 _________________________________________________________________ Traceback (most recent call last): File "C:/Users/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py", line 113, in main() File "C:/Users/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py", line 74, in main model.fit(x=img, y=y_train[nx],verbose=2) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 1536, in fit validation_split=validation_split) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 992, in _standardize_user_data class_weight, batch_size) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 1169, in _standardize_weights training_utils.check_array_lengths(x, y, sample_weights) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training_utils.py", line 426, in check_array_lengths 'and ' + str(list(set_y)[0]) + ' target samples.') ValueError: Input arrays should have the same number of samples as target arrays. Found 1 input samples and 16 target samples.

Process finished with exit code 1

Still stuck, sorry.

I have cut the problem down to the bare bones:

import tensorflow as tf
import numpy as np
in_shape=(128,128,3)
a=np.zeros(shape=in_shape,dtype='float32')
np.fill_diagonal(a[:,:,0],1.)
np.fill_diagonal(a[:,:,1],1.)
np.fill_diagonal(a[:,:,2],1.)

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(64, input_shape=in_shape, activation=tf.nn.relu, batch_size=1,name='d0'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(16, activation=tf.nn.softmax,name='d1')
])

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

Y=np.empty(16)
Y.fill(1.)
#forgot to make one of them 'hot' , does not matter now

#this line barfs
model.fit(x=np.expand_dims(a, axis=0), y=np.expand_dims(Y, axis=0),steps_per_epoch=1)

Output is:

"C:\Users\WascallyWabbit\AppData\Local\Programs\Python\Python36\python.exe" "C:/Users/WascallyWabbit/.PyCharmCE2018.2/config/scratches/scratch_39.py" Traceback (most recent call last): File "C:/Users/WascallyWabbit/.PyCharmCE2018.2/config/scratches/scratch_39.py", line 28, in model.fit(x=np.expand_dims(a, axis=0), y=np.expand_dims(Y, axis=0),steps_per_epoch=1) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 1536, in fit validation_split=validation_split) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 992, in _standardize_user_data class_weight, batch_size) File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training.py", line 1154, in _standardize_weights exception_prefix='target') File "C:\Users\WascallyWabbit\AppData\Roaming\Python\Python36\site-packages\tensorflow\python\keras\engine\training_utils.py", line 332, in standardize_input_data ' but got array with shape ' + str(data_shape)) ValueError: Error when checking target: expected d1 to have shape (1,) but got array with shape (16,)

I want a 16 element array of probabilities to 'softmax' against the 16 element label array. Faffing around with np.expand_dims(...,axis=) has brought no joy.

What am I failing to see?

1
The final Dense layer needs to have the same number of nodes as your classes. In this case, 16 nodes. The softmax activation will give you probability scores for those 16 nodes (ie classes)amityadav
The problem is not the number of classes, the error clearly says that x_train has one sample, and y_train has 16 samples, these numbers should be equal. For instance, the first dimension of x_train and y_train has to be the same.Dr. Snoopy

1 Answers

0
votes

If using sparse_categorical_crossentropy, then y value should be provided as an integer hence the error expected shape(1,) is observed. Providing y in one-hot encoded form is when the loss function is categorical_crossentropy.

This link has a nice illustration. https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/

So, the fix is

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

Also, np.expand_dims or y_train[nx][None] can be used to create the batch dimension.

model.fit(x=img, y = np.expand_dims(y_train[nx], 0), verbose=2)