Keras softmax probabilities - keras

I'm trying to get softmax probabilities from a net whose last layer is a softmax layer and when I use model.predict() I get classes instead probabilities. Could anyone tell how to get probabilities.
model = Sequential()
model.add(Convolution2D(32, 3, 3,input_shape=(32, 32, 3)))
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.5))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.5))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(43))
model.add(Activation('softmax'))

Your model's outputs will be values between 0 and 1.
Your model should give a vector of size 43 and the sum of all outputs will add to one.
Depending on your training, these "probabilities" will often be almost one for the selected class if similar to the training examples, showing that the model was well trained.

Related

Can a Keras CNN predict multiple classes?

I made a keras CNN model to predict different hand poses, and the model was not predicting the correct output. I had 10 classes. But for some images it was showing results like [0, 1, 0, 0, 1, 0, 0, 0, 0, 0]. My question is why is this happening.
My Architecture.
model = Sequential()
model.add(Conv2D(32, (5,5), input_shape=x.shape[1:]))
model.add(Conv2D(32, (5,5), input_shape=x.shape[1:]))
model.add(Conv2D(32, (5,5), input_shape=x.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(2,2))
model.add(Conv2D(64, (3,3), input_shape=x.shape[1:]))
model.add(Conv2D(64, (3,3), input_shape=x.shape[1:]))
model.add(Conv2D(64, (3,3), input_shape=x.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(2,2))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer = 'adam',
metrics = ['accuracy']
)
model.fit(x, y, epochs=10)
You are using binary_crossentropy loss which should be used for binary classification problems. For multiclass problems you should be using categorical_crossentropy. You might also want to change the activation on the last layer to softmax
This is the obvious engineering issue I can see; having said that, you probably will have to experiment with the number of layers, epochs, learning rates etc to get a working model.

How to increase the accuracy of the keras model and prevent overfitting

I am trying to train
model.add(Conv2D(32, (3, 3), kernel_initializer='random_uniform', activation='relu', input_shape=(x1, x2, depth)))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.4))
model.add(Conv2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(3, activation='softmax'))
Here's how I'm compiling it:
sgd = optimizers.SGD(lr=0.1, decay=0.0, momentum=0.05, nesterov=True)
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])
I've tried various learning rates and different optimizers. But the accuracy doesn't seem to go beyond 50% as shown below:
My images are properly normalized around 0 with STD as 1.
Is there something I am missing? How can I improve the accuracy of the model?
EDIT:
Hey, when I use the following data generator:
train_datagen = ImageDataGenerator(
featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(featurewise_center=True,
featurewise_std_normalization=True)
train_generator = train_datagen.flow(np.array(X_train), batch_size=batchsize)
valid_generator = test_datagen.flow(np.array(X_test), batch_size = batchsize)
history = model.fit_generator(train_datagen.flow(np.array(X_train), y_train_cat, batch_size=batchsize),
steps_per_epoch=len(X_train) // batchsize, epochs=epochs,
validation_data= valid_generator,
validation_steps=len(X_test) // batchsize)
I get the following error:
TypeError: '>' not supported between instances of 'int' and 'str'
I used to solve this by either updating numpy or uninstalling it and installing it again, but this time, it's not working with either. Can you help me with it?
You have already captured things like tweaking learning rates, dropouts, batchnormalization etc - which is a good starting point to tweak.
Have you tried regularization?
Check out
https://cambridgespark.com/content/tutorials/neural-networks-tuning-techniques/index.html
If it doesnt help, you might need to look at how the input is structured and see if there are other ways that more helpful for the network to converge. This includes making sure that train and validation has same level of variance in data etc. This is however, more domain specific to what you are trying to solve.

automatically determine best filter size to use in keras CNN Conv2D layers

model.add(Conv2D(32, (5, 5),
padding='same',
data_format='channels_last',
input_shape=input_shape))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(num_classes))
model.add(Activation('softmax'))
This is what my current keras model looks like, which is completely borrowed from here.
My question has two parts,
1. How do I automatically determine whether to use model.add(Conv2D(32, (3, 3))) or model.add(Conv2D(32, (5,5))) or model.add(Conv2D(32, (4,4))) ?
2. except the first line of the model, If I change the rest of the conv2D(64, (3,3)) models to (5,5) I get `negative dimension obtained by subtracting 5 from 3) . why is that?
I looked at these two questions : Selecting number of strides and filters in CNN (Keras) and Conv2D layer output shape in keras
according to them experimenting is the only way to find out, but I was wondering if there is an automatic way to do it.
Because there are so many parameters such as value of dropout , kernel_size() and then value of Dense() should it be 512/356 or how much is the best.
PS:
Running different models with different parameters is becoming computationally expensive, and comparing all these results is becoming another painful process.
My laptop has a 2GB nvidia graphic card with 5.0 compute capability.
The kernels dimensions are hyper parameters that you can automatically optimize using a number of strategies. Here are a couple of tips for that
The output height/width of a convolutional layer follows the equation size = ((input_size - kernel_size) / stride) + 1. So you're using too many convolutional layers for an image that is too small. At some point size will be negative and you can't have a negative shaped output

Keras trained mode always predicts 0

I'm trying to build a model to predict wether a picture has text in it using keras with Tensorflow backend.
This is my Model:
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(image_size, image_size, 3))) # 32?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # 0.5?
model.add(Conv2D(32, (3, 3))) # again, 32?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # again, 0.5?
model.add(Conv2D(64, (3, 3))) # again, 64?
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5)) # again, 0.5?
model.add(Flatten())
model.add(Dense(96))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1)) # binary
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
I've tried image sizes 128, 256, 384.
I train it with 9000 images, 4500 of cat 1 and 4500 of cat 2.
the training accuracy goes as high as 0.90.
but when I load the model and use it to predict the category of images of the two categories that I haven't trained it with, it always gives the score 0.
Any ideas why this is happenning?
p.s. cat 1 is images with text and cat 2 is images without text.
also this is my code for testing the model:
model = load_model(model_path)
test_data_generator = ImageDataGenerator(rescale=1. / 255)
test_generator = test_data_generator.flow_from_directory(
test_data_dir,
target_size=(image_size, image_size),
batch_size=batch_size,
class_mode=None,
shuffle=False)
prediction = model.predict_generator(
test_generator,
use_multiprocessing=True,
verbose=1) # verbose=1 makes it show a progress bar.
dst = []
for pred in prediction:
if int(round(pred)) == 0:
dst += [0]
else:
dst += [1]
dst is all 0's.
Apparently the problem was that I used keras' generators to feed the images I was testing and used shutil to iterate over them. So I'd get the predictions and iterate over them and the files in the directory using two different things and the order of them wasn't the same. shutil would list them in some random order whereas the generator would list them in ascending order by name. so I wasn't putting a label on the file it was generated for.

How can I train on video data using Keras? "transfer learning"

I want to train my model on video data for gesture recognition, proposed using LSTM's and TimeDistributed layers. Would this be ideal way to tackle my problem?
# Convolution
pool_size = 4
# LSTM
lstm_output_size = 1
print('Build model...')
model = Sequential()
model.add(TimeDistributed(Dense(62), input_shape=(img_width, img_height,3)))
model.add(Conv2D(32, (3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(32, (3, 3)))
model.add(MaxPooling2D(pool_size=pool_size))
# model.add(Dense(1))
model.add(TimeDistributed(Flatten()))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(lstm_output_size))
model.add(Dense(units = 1, activation = 'sigmoid'))
print('Train...')
model.summary()
# Run epochs of sampling data then training
For temporal sequence data LSTM networks are generally the right choice. If you want to analyze video then a combination with 2d convolutions sounds reasonable to me. However, you have to apply TimeDistributed on all layers which dont expect sequence data. In your example that means all laysers expect LSTM.
# Convolution
pool_size = 4
# LSTM
lstm_output_size = 1
print('Build model...')
model = Sequential()
model.add(TimeDistributed(Dense(62), input_shape=(img_width, img_height,3)))
model.add(TimeDistributed(Conv2D(32, (3, 3))))
model.add(Dropout(0.25))
model.add(TimeDistributed(Conv2D(32, (3, 3))))
model.add(TimeDistributed(MaxPooling2D(pool_size=pool_size)))
# model.add(Dense(1))
model.add(TimeDistributed(Flatten()))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(256, return_sequences=True))
model.add(CuDNNLSTM(lstm_output_size))
model.add(Dense(units = 1, activation = 'sigmoid'))
print('Train...')
model.summary()
# run epochs of sampling data then training
The last Dense Layer can stay this way because the final lstm doesnt output a sequence.

Resources