Keras & Tensorflow - Layer argument as variable to be changed during prediction - python

I'm using this code to train a DCGAN model to generate images. DCGAN
I want to be able to output (predict) images at a greater resolution than the model was trained at, and I'm told this is possible if convolution is used. In the following code, which describes the generator model, if I change the stride on the Conv2DTranspose layers I can increase the output shape (therefore image resolution). How can I set the stride to a different value during training than prediction? Or is there a different way to do what I want?
# Creates the generator model. This model has an input of random noise and
# generates an image that will try mislead the discriminator.
def construct_generator():
generator = Sequential()
generator.add(Dense(units=4 * 4 * 512,
kernel_initializer='glorot_uniform',
input_shape=(1, 1, 100)))
generator.add(Reshape(target_shape=(4, 4, 512)))
generator.add(BatchNormalization(momentum=0.5))
generator.add(Activation('relu'))
generator.add(Conv2DTranspose(filters=256, kernel_size=(5, 5),
strides=(2, 2), padding='same',
data_format='channels_last',
kernel_initializer='glorot_uniform'))
generator.add(BatchNormalization(momentum=0.5))
generator.add(Activation('relu'))
generator.add(Conv2DTranspose(filters=128, kernel_size=(5, 5),
strides=(2, 2), padding='same',
data_format='channels_last',
kernel_initializer='glorot_uniform'))
generator.add(BatchNormalization(momentum=0.5))
generator.add(Activation('relu'))
generator.add(Conv2DTranspose(filters=64, kernel_size=(5, 5),
strides=(2, 2), padding='same',
data_format='channels_last',
kernel_initializer='glorot_uniform'))
generator.add(BatchNormalization(momentum=0.5))
generator.add(Activation('relu'))
generator.add(Conv2DTranspose(filters=3, kernel_size=(5, 5),
strides=(2, 2), padding='same',
data_format='channels_last',
kernel_initializer='glorot_uniform'))
generator.add(Activation('tanh'))
optimizer = Adam(lr=0.00015, beta_1=0.5)
generator.compile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=None)
return generator

Related

Why does model=None, and how am I supposed to solve it?

I keep getting an error that says
runfile('C:/Users/admin/Documents/GitHub/Self-driving-Car/convo_nn.py', wdir='C:/Users/admin/Documents/GitHub/Self-driving-Car')
------------------------------
Parameters
------------------------------
data_dir := data
test_size := 0.2
keep_prob := 0.5
nb_epoch := 10
samples_per_epoch := 20000
batch_size := 40
save_best_only := True
learning_rate := 0.0001
------------------------------
Traceback (most recent call last):
File "C:\Users\admin\Documents\GitHub\Self-driving-Car\convo_nn.py", line 233, in <module>
main()
File "C:\Users\admin\Documents\GitHub\Self-driving-Car\convo_nn.py", line 226, in main
model = build_model(args)
File "C:\Users\admin\Documents\GitHub\Self-driving-Car\convo_nn.py", line 128, in build_model
Model.add(Convolution2D(24, (5, 5), padding='same', strides=(2, 2),input_shape=INPUT_SHAPE))
AttributeError: 'NoneType' object has no attribute 'add'
Code attached below
def build_model(args):
activation_relu = 'relu'
Model = Sequential()
#Model.add(Lambda(lambda x: x / 127.5 - 1.0, input_shape=INPUT_SHAPE))
Model.add(Convolution2D(24, (5, 5), padding='same', strides=(2, 2),input_shape=INPUT_SHAPE))
Model.add(Activation(activation_relu))
Model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1)))
Model.add(Convolution2D(36, (5, 5), padding='same', strides=(2, 2)))
Model.add(Activation(activation_relu))
Model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1)))
Model.add(Convolution2D(48, (5, 5), padding='same', strides=(2, 2)))
Model.add(Activation(activation_relu))
Model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1)))
Model.add(Convolution2D(64, (3, 3), padding='same', strides=(1, 1)))
Model.add(Activation(activation_relu))
Model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1)))
Model.add(Convolution2D(64, (3, 3), padding='same', strides=(1, 1)))
Model.add(Activation(activation_relu))
Model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1)))
Model.add(Flatten())
# Next, five fully connected layers
Model.add(Dense(1164))
Model.add(Activation("tanh"))
Model.add(Dense(100))
Model.add(Activation("tanh"))
Model.add(Dense(50))
Model.add(Activation("tanh"))
Model.add(Dense(10))
Model.add(Activation("tanh"))
Model.add(Dense(nb_classes,activation="softmax"))
Model.summary()
return Model
However, if I add a clause:
if Model is not None:
...
else:
pass
the code compiles successfully. Thus I could understand that model is always equalling to None. For the full code find the link attached below:
NeuroNetwork.py
To try this run Asphalt 9, run trainer.py to get training data. Then
run NeuroNetwork.py to build a convolutional neural network. Then run AI.py on Asphalt 9, for the AI to, hypothetically play the game. I've only coded it for TouchDrive right now.
I'm relatively new to Python, so do excuse me if it's a basic error
Use case: An Asphalt-9 AI based on previous codes...
I have made a training data extraction code and a hardware keyboard sending and receiving libraries and everything else works, except this... It's supposed to be a convolutional neural network...

Adding layers to CNN model (MobileNetV2)

Hello I have created a MobileNetV2 model i want to add layers onto it.
However, i kept getting this error:
"One of the dimensions in the output is <= 0 due to downsampling in conv2d_22. Consider increasing the input size. Received input shape [None, 3, 3, 1280] which would produce output shape with a zero or negative value in a dimension."
this is my code so far:
base_model = tf.keras.applications.MobileNetV2(input_shape=(96,96,3),
include_top=False,
weights='imagenet')
model = tf.keras.Sequential()
model.add(base_model)
model.add(layers.Conv2D(60, kernel_size=(5, 5), strides=(1, 1),
activation='relu',
input_shape=(96,96,3))) #error was highlighted on this line
model.add(layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(layers.Conv2D(64, kernel_size=(5, 5), strides=(1, 1), activation='relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(500, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
i have tried changing the channel first and last ((96,96,3) and (3,96,96)) on the line that has problem and both produced the same error error.
Appreciate anyone who can help with this thanks.
You cannot downsample a tensor (None, 3, 3, 1280) with a kernel size of (5, 5). Think about what a 2D convolutional layer is actually doing. You could try first flattening the output of the base model and then reshaping the output with the dense and reshape layers:
import tensorflow as tf
base_model = tf.keras.applications.MobileNetV2(input_shape=(96,96,3),
include_top=False,
weights='imagenet')
model = tf.keras.Sequential()
model.add(base_model)
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64 * 64 * 3)) # just an example --> choose what you want
model.add(tf.keras.layers.Reshape((64, 64, 3)))
model.add(tf.keras.layers.Conv2D(60, kernel_size=(5, 5), strides=(1, 1),
activation='relu',
input_shape=(96,96,3))) #error was highlighted on this line
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(tf.keras.layers.Conv2D(64, kernel_size=(5, 5), strides=(1, 1), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(500, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
You also use an Upsampling layer to get the dimensions you want, but that is up to you.

set_weights() in Tensorflow model

I have pretrained weights as np.array of shape (3, 3, 3, 64). I want to initialize this Tensorflow CNN with those weights using set_weights() like I show below.
However, when I try that, the following error pops up: ValueError: You called set_weights(weights) on layer "conv2d_3" with a weight list of length 3, but the layer was expecting 2 weights. Provided weights: [[[[-0.15836713 -0.178757 0.16782044 ...
model = models.Sequential()
model.add(layers.Conv2D(64, (3, 3), activation='relu', input_shape=(224, 224, 3)))
model.layers[0].set_weights(weights)
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(512, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(512, (3, 3), activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(4, activation='softmax'))
print(model.summary())
adam = optimizers.Adam(learning_rate=0.0001, amsgrad=False)
model.compile(loss='categorical_crossentropy',
optimizer=adam,
metrics=['accuracy'])
history = model.fit_generator(
train_generator,
steps_per_epoch=np.ceil(nb_train_samples/batch_size),
epochs=epochs,
validation_data=validation_generator,
validation_steps=np.ceil(nb_validation_samples / batch_size),
class_weight=class_weight
)
My question is: how do I pass those (3, 3, 3, 64) shaped weights to initialize that CNN? I have already checked the weight shapes required for each layer and the shapes I am trying to pass and the required shape match.
You could just use kernel_initializer and bias_initializer arguments like this:
import numpy as np
# init_kernel and init_bias are initialization weights that you have
init_kernel = np.random.normal(0, 1, (3, 3, 3, 64))
init_bias = np.zeros((64,))
kernel_initializer = tf.keras.initializers.constant(init_kernel)
bias_initializer = tf.keras.initializers.constant(init_bias)
conv_layer = tf.keras.layers.Conv2D(64, (3, 3),
activation='relu',
input_shape=(224, 224, 3),
kernel_initializer=kernel_initializer,
bias_initializer=bias_initializer)
Note the kernel's and bias' shapes that I've chosen. The values with which you initialise your layer must have the exact same shapes.

CNN architecture predicts always the same class

I am using this CNN architecture :
def createModel():
model = Sequential()
model.add(Conv2D(96, (11, 11), strides=(4,4), padding='same', activation='relu', input_shape=(224,224,3))) #, input_shape=input_shape
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2,2), padding='same'))
model.add(Conv2D(256, (5, 5), strides=(1,1), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2,2), padding='same'))
model.add(Conv2D(384, (3, 3), strides=(1,1), padding='same', activation='relu'))
model.add(Conv2D(384, (3, 3), strides=(1,1), padding='same', activation='relu'))
model.add(Conv2D(256, (3, 3), strides=(1,1), padding='same', activation='relu'))
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
return model
At the total, it makes 226,065,795 trainable parameters... I train my model on a quite small dataset. Indeed, I have three classes, each one contains 1000 images, that are split between training and validation set. I used OneHotEncoding.
However, when I train the model, the overall accuracy tends to a very low result : 32%. I am using categorical_crossentropy loss function. When looking deeper, it seems that the model always predicts 1,0,0 vector, i.e. the first class and never the others, even for the trained data that thus have been shown to the model.
What's the problem there ? Why do I have poor results ? My dataset is balanced tough. Is it because my number of parameters is too high compared to the amount of data? I don't understand...
EDIT : removing Dropout still keeps the bad thing

Keras Reshape doesn't seem to run

I have a simple convolutional autoencoder in keras. My original inputs are flat arrays from a csv, so I want to reshape them from (196,) to (14,14,1). Following the keras docs, I did:
autoencoder = Sequential()
# first, reshape our (csv) inputs from (196,) to (14,14,1)
autoencoder.add(Reshape((14,14,1), input_shape=(196,)))
# encoding stage
autoencoder.add(Conv2D(16, (3,3), activation='relu', padding='same'))
autoencoder.add(MaxPooling2D((2, 2), padding='same'))
autoencoder.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
autoencoder.add(MaxPooling2D((2, 2), padding='same'))
autoencoder.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
autoencoder.add(MaxPooling2D((2, 2), padding='same'))
# decoding stage
autoencoder.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
autoencoder.add(UpSampling2D((2, 2)))
autoencoder.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
autoencoder.add(UpSampling2D((2, 2)))
autoencoder.add(Conv2D(16, (2, 2), activation='relu'))
autoencoder.add(UpSampling2D((2, 2)))
autoencoder.add(Conv2D(1, (3, 3), activation='sigmoid', padding='same'))
optimizer = optimizers.Adagrad(lr=0.01, epsilon=None, decay=0.001)
autoencoder.compile(optimizer=optimizer, loss='binary_crossentropy')
But I get the error: ValueError: Error when checking target: expected conv2d_35 to have 4 dimensions, but got array with shape (2870, 196)
So it seems to be ignoring the Reshape entirely. Am I making some obvious mistake?
The problem is not the input but the target so the y values you give are not reshaped. The final output of your network is a 4D tensor where you give instead (2870, 196).
Double check the your target array (y values) that you pass onto fit function.

Categories

Resources