How to load fine-tuned keras model - tensorflow

I am following this tutorial to try fine-tuning using VGG16 model, I trained the model and saved .h5 file using model.save_weights and
vgg_conv = VGG16(include_top=False, weights='imagenet', input_shape=(image_size, image_size, 3))
# Freeze the layers except the last 4 layers
for layer in vgg_conv.layers[:-4]:
layer.trainable = False
model = Sequential()
model.add(vgg_conv)
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(11, activation='softmax'))
I then tried to rebuild the architecture and load weights using the below
def create_model(self):
model = Sequential()
vgg_model = VGG16(include_top=False, weights='imagenet', input_shape=(150, 150, 3))
model.add(vgg_model)
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(11, activation='softmax'))
model.load_weights(self.top_model_weights_path) # throws error
return model
but it then throws this error
ValueError: Cannot feed value of shape (512, 512, 3, 3) for Tensor 'Placeholder:0', which has shape '(3, 3, 3, 64)'
what am I doing wrong?

I am not sure how to intepret the error but you could try saving the model architecture and the weights together model.save("model.h5") after fine tuning.
To load the model you can type
model = load_model('model.h5')
# summarize model.
model.summary()
I think this has the benefeit of not having to rebuild the model and requires only one line to acomplish the same purpose.

The problem comes from the trainable difference between the two models. If you freeze the 4 last layers in the create_model function, it will work.
But as said by Igna, model.save and model.load_model is simpler.

Related

SageMaker Predictor only outputs 0 and 1, i need the float between 0 and 1

I have trained a TensorFlow model on Amazon SageMaker with the following architecture:
_, timesteps, features = X_train.shape
ACTIVATION = 'relu'
EPOCHS = 50
model = Sequential()
model.add(Masking(mask_value=np.nan, input_shape=(timesteps, features)))
model.add(LSTM(64, activation=ACTIVATION, return_sequences=True))
model.add(LSTM(64, activation=ACTIVATION, return_sequences=True))
model.add(LSTM(64, activation=ACTIVATION))
model.add(BatchNormalization())
model.add(Dense(64, activation=ACTIVATION))
model.add(Dense(64, activation=ACTIVATION))
model.add(Dense(64, activation=ACTIVATION))
model.add(BatchNormalization())
model.add(Dropout(0.1))
model.add(Dense(64, activation=ACTIVATION))
model.add(Dense(1, activation='sigmoid'))
adam_low = Adam(learning_rate = 0.0001)
model.compile(optimizer=adam_low,
loss='binary_crossentropy',
metrics=['accuracy'])
If I trained this in my local machine and do a prediction it will output float between 0 and 1.
But when I trained the same exact architecture with SageMaker with TensorFlow container, after deploying the saved model on an endpoint and calling prediction = predictor.predict(x_predict) the output is always either 0 or 1 only. Is there a way to force the prediction to output 0-1 float?
The predictor doesn't do any processing of the output data other than deserialize it with the deserializer of your choosing. There are couple thing I would try to debug this
1, Download the trained model from S3 and do some local predictions to make sure the model is trained correctly.
2, Make some prediction requests to the sagemaker endpoint using boto3 or the aws cli directly without the SageMaker Python SDK.
try adding the last dense layer's activation as "softmax"

Keras input shape mismatch error for multi-feature CNN classification model

Here is my code:
model = Sequential()
model.add(Conv1D(32, kernel_size=3,
activation='relu',
input_shape=(14,1)))
model.add(MaxPooling1D(pool_size=1))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='softmax'))
model.summary()
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(X_train.values, y_train.values,
batch_size=4,
epochs=1,
verbose=2,
validation_data=(X_test.values,y_test.values))
And error is:
Error when checking input: expected conv1d_35_input to have 3 dimensions, but got array with shape (13166, 14)
As suggested by other posts, I tweaked with flatten layer before output layer but that did not work.
My X_train.values.shape gives (13166, 14)
Any suggestion how should I fix this?
You need to reshape the X_train.values from (13166, 14) to (13166, 14, 1) as your input shape of CNN network is (None, 14, 1).
This may solve your problem:
X_train.values.reshape([-1,14,1])

How to customise a CNN layers with TensorFlow 2, Feed new inputs at Dense Layers of CNN [duplicate]

I have 1D sequences which I want to use as input to a Keras VGG classification model, split in x_train and x_test. For each sequence, I also have custom features stored in feats_train and feats_test which I do not want to input to the convolutional layers, but to the first fully connected layer.
A complete sample of train or test would thus consist of a 1D sequence plus n floating point features.
What is the best way to feed the custom features first to the fully connected layer? I thought about concatenating the input sequence and the custom features, but I do not know how to make them separate inside the model. Are there any other options?
The code without the custom features:
x_train, x_test, y_train, y_test, feats_train, feats_test = load_balanced_datasets()
model = Sequential()
model.add(Conv1D(10, 5, activation='relu', input_shape=(timesteps, 1)))
model.add(Conv1D(10, 5, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Dropout(0.5, seed=789))
model.add(Conv1D(5, 6, activation='relu'))
model.add(Conv1D(5, 6, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Dropout(0.5, seed=789))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5, seed=789))
model.add(Dense(2, activation='softmax'))
model.compile(loss='logcosh', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=20, shuffle=False, verbose=1)
y_pred = model.predict(x_test)
Sequential model is not very flexible. You should look into the functional API.
I would try something like this:
from keras.layers import (Conv1D, MaxPool1D, Dropout, Flatten, Dense,
Input, concatenate)
from keras.models import Model, Sequential
timesteps = 50
n = 5
def network():
sequence = Input(shape=(timesteps, 1), name='Sequence')
features = Input(shape=(n,), name='Features')
conv = Sequential()
conv.add(Conv1D(10, 5, activation='relu', input_shape=(timesteps, 1)))
conv.add(Conv1D(10, 5, activation='relu'))
conv.add(MaxPool1D(2))
conv.add(Dropout(0.5, seed=789))
conv.add(Conv1D(5, 6, activation='relu'))
conv.add(Conv1D(5, 6, activation='relu'))
conv.add(MaxPool1D(2))
conv.add(Dropout(0.5, seed=789))
conv.add(Flatten())
part1 = conv(sequence)
merged = concatenate([part1, features])
final = Dense(512, activation='relu')(merged)
final = Dropout(0.5, seed=789)(final)
final = Dense(2, activation='softmax')(final)
model = Model(inputs=[sequence, features], outputs=[final])
model.compile(loss='logcosh', optimizer='adam', metrics=['accuracy'])
return model
m = network()

Error when checking target: expected dense_18 to have shape (1,) but got array with shape (10,)

Y_train = to_categorical(Y_train, num_classes = 10)#
random_seed = 2
X_train,X_val,Y_train,Y_val = train_test_split(X_train, Y_train, test_size = 0.1, random_state=random_seed)
Y_train.shape
model = Sequential()
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy',metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size = 86, epochs = 3,validation_data = (X_val, Y_val), verbose =2)
I have to classify the MNIST data into 10 classes. I am converting the Y_train into one hot encoded array. I have gone through a number of answers but none have helped. Kindly guide me in this regard as I am a novice in ML and neural network.
It seems there is no need to use model.add(Flatten()) in your first layer. Instead of doing so, you can use a dense layer with a specific input size like: model.add(Dense(64, input_shape=your_input_shape, activation="relu").
To ensure this issue happens because of the layers, you can check whether to_categorical() function works alone with jupyter notebook.
Updated Answer
Before the model, you should reshape your model. In that case 28*28 to 784.
train_images = train_images.reshape((-1, 784))
test_images = test_images.reshape((-1, 784))
I also suggest to normalize the data that could be done by simply dividing the images to 255
After that step you should create your model.
model = Sequential([
Dense(64, activation='relu', input_shape=(784,)),
Dense(64, activation='relu'),
Dense(10, activation='softmax'),
])
Have you noticed input_shape=(784,) That is the shape of your flattened input.
Last step, compiling and fitting.
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'],
)
model.fit(
train_images,
train_labels,
epochs=10,
batch_size=16,
)
What you do is you have just flattened the input layer without feeding the network with an input. That's why you experience an issue. The point is you should manually reshape your inputs and feed forward to the Dense() layers with parameter input_shape

Input dimension mismatch between dense layers and conv layers of imagenet while attempting transfer learning

I am trying to train dense layers on top of the conv layers of InceptionV3.
But I'm unable to initialize the fully connected model. I'm getting a ValueError.
model_inc = applications.InceptionV3(weights='imagenet',
include_top=False)
model = Sequential()
model.add(Flatten(input_shape=model_inc.output_shape[1:]))
model.add(Dense(256, activation= 'relu', kernel_initializer='he_normal'))
model.add(Dropout(0.5))
model.add(Dense(9, activation='softmax'))
I expected the model to compile successfully but I get "ValueError: The shape of the input to "Flatten" is not fully defined (got (None, None, 2048). Make sure to pass a complete "input_shape" or "batch_input_shape" argument to the first layer in your model."
You want your input to go to your model_inc so you have to define the input_shape there. Something like the following should work
model_inc = applications.InceptionV3(input_shape=(224,224,3), weights='imagenet',
include_top=False)
model = Sequential()
# you need to add your base model
model.add(model_inc)
model.add(Flatten())
model.add(Dense(256, activation= 'relu', kernel_initializer='he_normal'))
model.add(Dropout(0.5))
model.add(Dense(9, activation='softmax'))