I did a neural network machine learning on colored images (3 channels). It worked but now I want to try to do it in grayscale to see if I can improve accuracy.
Here is the code:
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary',
shuffle=True)
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
color_mode='grayscale',
class_mode='binary',
shuffle=True)
model = tf.keras.Sequential()
input_shape = (img_width, img_height, 1)
model.add(Conv2D(32, 2, input_shape=input_shape, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(32, 2, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Conv2D(64, 2, activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Flatten())
model.add(Dense(128))
model.add(Dense(len(classes)))
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(train_generator,
validation_data=validation_generator,
epochs=EPOCHS)
You can see that I have changed the input_shape to have 1 single channel for grayscale.
I'm getting an error:
Node: 'sequential_26/conv2d_68/Relu' Fused conv implementation does not support grouped convolutions for now. [[{{node sequential_26/conv2d_68/Relu}}]] [Op:__inference_train_function_48830]
Any idea how to fix this?
Your train_generator does not seem to have the colormode='grayscale'. Try:
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary',
colormode='grayscale',
shuffle=True)
This error arises when the no. channel differs from the model. Maybe due to the input_shape, you've given a 3d shape tensor. This MAY help you.:)
input_shape = (img_width, img_height, 1)
Related
I am implementing resnet-50 on Kaggle and I am getting a value error. Kindly help me out
train_dir='../input/project/data/train'
test_dir='../input/project/data/test'
train_datagen=ImageDataGenerator(rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = train_datagen.flow_from_directory(
train_dir,
color_mode='grayscale',
target_size=(28,28),
class_mode='binary',
batch_size=32,
)
test_generator = test_datagen.flow_from_directory(
test_dir,
color_mode='grayscale',
target_size=(28,28),
class_mode='binary',
batch_size=32,
shuffle='False',
)
model = Sequential()
model.add(ResNet50(include_top=False, pooling='avg', weights=resnet_weights_path,input_tensor=Input(shape=(224,224,3))))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(2048, activation='relu'))
model.add(BatchNormalization())
model.add(Dense(1024, activation='relu'))
model.add(BatchNormalization())
model.add(Dense(2, activation='sigmoid'))
model.layers[0].trainable = False
I am training a binary classifier and I am getting the error below
ValueError: Cannot assign to variable conv3_block1_0_conv/kernel:0 due to variable shape (1, 1, 256, 512) and value shape (512, 128, 1, 1) are incompatible
You have given input_tensor=Input(shape=(224,224,3)) while defining the ResNet50 base model. But you are giving target_size=(28,28) in your train_generator and test_generator. The training image shape which ResNet50 receiving i.e. target_size is different from what it expects i.e. input_tensor. Change your target_size to match with the shape mentioned in the input_tensor. Also, ResNet50 expects color_mode to be rgb rather grayscale.
This is because of weights which you are using(weights=resnet_weights_path). You've to use latest trained model. Input Image size can be any as per pre-trained model guidelines
Below worked for me
n_h, n_w, n_c =(256, 256, 3)
weights_path = '../input/d/aeryss/keras-pretrained- models/ResNet50_NoTop_ImageNet.h5'
ResNet50 = keras.applications.ResNet50(weights=weights_path ,include_top=False, input_shape=(n_h, n_w, n_c))
It looks like you are using pre-trained weights on your model. You should set the skip_mismatch=True keyword on the model.load_weights function. After returning the model variable, please set the following code:
model.load_weights(weights, by_name=True, skip_mismatch=True)
Where weight is your pre-trained model weight. It should ignore any mismatch of your model and the pre-trained weights.
I am planning to use CNN+LSTM for image classification into 4 categories.
I am not really familiar on how to combining CNN and LSTM.
I faced an error: You must compile your model before using it. when I am trying to compile CNN+LSTM.
The data sets are a series of medical images. I am able to get roughly 70% accuracy by using CNN alone (small sample size of around 300 samples only), so I decided to combine LSTM to see if there will be a boost in accuracy.
from keras.optimizers import RMSprop
from keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import Sequential
from tensorflow.keras.layers import (LSTM, Dense, Embedding, Dropout, Conv2D, BatchNormalization, Activation,
MaxPooling2D, Flatten, TimeDistributed, SpatialDropout1D)
train_datagen = ImageDataGenerator(rescale=1. / 255, shear_range=0.2, zoom_range=0.2, rotation_range=45,
horizontal_flip=True, vertical_flip=True, validation_split=.2)
validation_datagen = ImageDataGenerator(rescale=1. / 255, validation_split=.2)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(directory=r'', target_size=(224, 224), color_mode="rgb",
batch_size=32, class_mode='categorical', shuffle=True, seed=42)
validation_generator = validation_datagen.flow_from_directory(directory=r'', target_size=(224, 224), color_mode="rgb",
batch_size=32, class_mode='categorical', shuffle=True,
seed=42)
test_generator = test_datagen.flow_from_directory(directory=r'', target_size=(224, 224), color_mode="rgb",
batch_size=1, class_mode=None, shuffle=False, seed=42)
num_classes = 4
input_shape = (224, 224, 3)
# input image dimensions
img_rows, img_cols = 224, 224
model = Sequential()
# define CNN model
model.add(TimeDistributed(Conv2D(32, (3, 3), padding='same', input_shape=input_shape)))
model.add(TimeDistributed(BatchNormalization()))
model.add(TimeDistributed(Activation('relu')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Conv2D(64, (3, 3))))
model.add(TimeDistributed(BatchNormalization()))
model.add(TimeDistributed(Activation('relu')))
model.add(TimeDistributed(MaxPooling2D(pool_size=(2, 2))))
model.add(TimeDistributed(Dropout(0.25)))
model.add(TimeDistributed(Flatten()))
model.add(TimeDistributed(Dense(256)))
model.add(TimeDistributed(BatchNormalization()))
model.add(TimeDistributed(Activation('relu')))
model.add(TimeDistributed(Dropout(0.25)))
# define LSTM model
model.add(LSTM(100, input_shape=(5, 1), return_sequences=True))
model.add(LSTM(Embedding(8192, 256)))
model.add(LSTM(SpatialDropout1D(0.3)))
model.add(LSTM(256, dropout=0.3, recurrent_dropout=0.3))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(5, activation='softmax'))
model.compile(loss=keras.losss.categorical_crossentropy, optimizer=RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0),
metrics=['accuracy'])
STEP_SIZE_TRAIN = train_generator.n // train_generator.batch_size
STEP_SIZE_VALID = validation_generator.n // validation_generator.batch_size
model.fit_generator(generator=train_generator, steps_per_epoch=50, validation_data=validation_generator,
validation_steps=STEP_SIZE_VALID, epochs=30)
You can simply move the input_shape=input_shape out from Conv2D and put it in TimeDistributed. i.e.
model.add(TimeDistributed(Conv2D(32, (3, 3), padding='same'), input_shape=input_shape))
I have problem with my image classification model using keras.
This is the code which have binary class.
tried to set the number of images in datasets as equal.
this is a code for Keras model
train_data_dir = 'path'
validation_data_dir = 'path'
nb_train_samples = 2000
nb_validation_samples = 800
epochs = 10
batch_size = 16
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (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(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
model.load_weights('second_try.h5')
and the model saved well.
so I run the test code
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
# dimensions of our images
img_width, img_height = 150, 150
# load the model we saved
model = load_model('modelpath')
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
#predicting multiple images at once
img = image.load_img('imgpath', target_size=(img_width, img_height))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
y = image.img_to_array(img)
y = np.expand_dims(y, axis=0)
images = np.vstack([x, y])
classes = model.predict_classes(images, batch_size=10)
print(classes)
and both images from different classes are printed as 1.
Why does this happening?
You should be saving the model or model weights after your training, rather than doing load_weights after fit(). So, 2 ways to do this
After model.fit(), do model.save_weights('second_try.hdf5') which only saves weights. To load the weights, you should first compile your model, and then call load_weights on the model as model.load_weights('second_try.hdf5')
After model.fit(), do model.save('model.hdf5') which saves the weights and the model structure to a single HDF5 file. Then you can use that HDF5 file with load() to reconstruct the whole model, including weights.
model = load_model('model.hdf5')
Also, do check if your test data is being prepared correctly. As your training loop uses a generator to prepare the data, you should use a similar generator for preparing the test data as well.
I am working on a glaucoma detection CNN and I'm getting the following error
ValueError: Error when checking target: expected activation_1 to have shape (2,) but got array with shape (1,) for any other number at the final Dense layer except 1. Since the number of classifications is 2, I need to give Dense(2) before the activation function. But whenever I run the code with Dense(1), I get a good accuracy but during testing, everything is predicted to be from the same class. How do I solve this error without changing my Dense layer back to Dense(1)
This is the code:
img_width, img_height = 256, 256
input_shape = (img_width, img_height, 3)
train_data_dir = "data/train"
validation_data_dir = "data/validation"
nb_train_samples = 500
nb_validation_samples = 50
batch_size = 10
epochs = 10
model = Sequential()
model.add(Conv2D(3, (11, 11), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Conv2D(96, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(192, (3, 3)))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(Dropout(0.5))
model.add(Conv2D(192, (3, 3)))
model.add(Flatten())
model.add(Dense(2))
model.add(Activation('softmax'))
model.summary()
model.compile(loss="binary_crossentropy", optimizer=optimizers.Adam(lr=0.001, beta_1=0.9,
beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False), metrics=["accuracy"])
# Initiate the train and test generators with data Augumentation
train_datagen = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
rotation_range=30)
test_datagen = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
rotation_range=30)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode="binary")
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
class_mode="binary")
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size
)
model.save('f1.h5')
Any help will be much appreciated.
That is because you specify class_mode='binary' in your image generators which means two classes will be encoded as 0 or 1 rather than [1,0] or [0,1]. You can easily solve this by changing your final layer to:
model.add(Dense(1, activation='sigmoid'))
# No need for softmax activation
model.compile(loss='binary_crossentropy', ...)
Binary cross-entropy on 0-1 is mathematically equivalent to 2 class softmax with cross-entropy so you achieve the same thing.
I write a code for image classification(2 categories, 'good'&'bad') in python using Keras, the accuracy on training data is about 99%, and on validation data is about 95%. (the image is 60 times 30 pixels grayscale png file)
img_width, img_height = 60, 30
nb_train_samples = 4000
nb_validation_samples = 600
epochs = 30
batch_size = 32
if K.image_data_format() == 'channels_first':
input_shape = (1, img_width, img_height)
else:
input_shape = (img_width, img_height, 1)
model = Sequential()
model.add(Conv2D(16, (3, 3), input_shape=input_shape,padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3),padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['binary_accuracy'])
train_datagen = ImageDataGenerator(rescale= 1. /255)
validation_datagen = ImageDataGenerator(rescale= 1. /255)
train_generator = train_datagen.flow_from_directory(
'/home/admin/Desktop/dataset/train',
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary',
color_mode='grayscale')
validation_generator = validation_datagen.flow_from_directory(
'/home/admin/Desktop/dataset/validation',
target_size=(img_width, img_height),
batch_size= batch_size,
class_mode='binary',
color_mode='grayscale')
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
model.save_weights('test_weights.h5')
now I want to make prediction for all the 600 images in validation directory, using this code.
path='/home/admin/Desktop/dataset/validation/good'
for file in os.listdir(path):
im=cv2.imread(os.path.join(path,file))
im=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
im=np.reshape(im,[1, img_width,img_height,1])*(1. /255)
result=model.predict_classes(im)
However, the result for 300 images in 'bad' directory is 9[1] with 291[0], and for 300 images in 'good' directory is 42[1] with 258[0], this is obviously wrong.
I think my way for data processing is different from ImageDataGenerator and flow_from_directory, which leads to the bug, but I'm not sure.
********update********
When I use the following code, the result is correct
predict_data=ImageDataGenerator(rescale=1. / 255).flow_from_directory(
'/home/admin/Desktop/dataset/validation/good',
target_size=(img_width, img_height),
batch_size= 300,
class_mode=None,
color_mode='grayscale')
result=model.predict_generator(
predict_data,
steps=1)
But I still don't know where the bug is.