Conversion from VGG19 to ResNet in Keras - python

I have the following code which works on pre-trained VGG model but fails on ResNet and Inception model.
vgg_model = keras.applications.vgg16.VGG16(weights='imagenet')
type(vgg_model)
vgg_model.summary()
model = Sequential()
for layer in vgg_model.layers:
model.add(layer)
Now, changing the model to ResNet as follows:
resnet_model=keras.applications.resnet50.ResNet50(weights='imagenet')
type(resnet_model)
resnet_model.summary()
model = Sequential()
for layer in resnet_model.layers:
model.add(layer)
gives the following error:
ValueError: Input 0 is incompatible with layer res2a_branch1: expected axis -1 of input shape to have value 64 but got shape (None, 56, 56, 256)

The problem is due to the fact that unlike VGG, Resnet does not have a sequential architecture (e.g. some layers are connected to more than one layers, there are skip connections, etc.). Therefore you cannot iterate over the layers in the model one after another and connect each layer to the previous one (i.e. sequentially). You can plot the architecture of the model using plot_model() to have a better understanding of this point.

Related

is keras LSTM supposed to work without an input_shape parameter?

I am using an LSTM for fake news detection and added an embedding layer to my model.
It is working fine without adding any input_shape in the LSTM function, but I thought the input_shape parameter was mandatory. Could someone help me with why there is no error even without defining input_shape? Is it because the embedding layer implicitly defines the input_shape?
Following is the code:
model=Sequential()
embedding_layer = Embedding(total_words, embedding_dim, weights=[embedding_matrix], input_length=max_length)
model.add(embedding_layer)
model.add(LSTM(64,))
model.add(Dense(1,activation='sigmoid'))
opt = SGD(learning_rate=0.01,decay=1e-6)
model.compile(loss = "binary_crossentropy", optimizer = opt,metrics=['accuracy'])
model.fit(data,train['label'], epochs=30, verbose=1)
You only need to provide an input_length to the Embedding layer. Furthermore, if you use a sequential model, you do not need to provide an input layer. Avoiding an input layer essentially means that your models weights are only created when you pass real data, as you did in model.fit(*). If you wanted to see the weights of your model before providing real data, you would have to define an input layer before your Embedding layer like this:
embedding_input = tf.keras.layers.Input(shape=(max_length,))
And yes, as you mentioned, your model infers the input_shape implicitly when you provide the real data. Your LSTM layer does not need an input_shape as it is also derived based on the output of your Embedding layer. If the LSTM layer were the first layer of your model, it would be best to specify an input_shape for clarity. For example:
model = tf.keras.Sequential()
model.add(tf.keras.layers.LSTM(32, input_shape=(10, 5)))
model.add(tf.keras.layers.Dense(1))
where 10 represents the number of time steps and 5 the number of features. In your example, your input to the LSTM layer has the shape(max_length, embedding_dim). Also here, if you do not specify the input_shape, your model will infer the shape based on your input data.
For more information check out the Keras documentation.

The input shape and fitting in Keras LSTM model

I am learning the LSTM model to fit the data set to the multi-class classification, which is eight genres of music, but unsure about the input shape in the Keras model.
I've followed the tutorials here:
How to reshape input data for LSTM model
Multi-Class Classification Tutorial with the Keras Deep Learning Library
Sequence Classification with LSTM Recurrent Neural Networks in Python with Keras
My data is like this:
vector_1,vector_2,...vector_30,genre
23.5 20.5 3 pop
.
.
.
(7678)
I transformed my data shape into (7678,1,30), which is 7678 pieces of music, 1 timestep, and 30 vectors. For the music genre, I used train_labels = pd.get_dummies(df['genre'])
Here is my model:
# build a sequential model
model = Sequential()
# keras convention to use the (1,30) from the scaled_train
model.add(LSTM(32,input_shape=(1,30),return_sequences=True))
model.add(LSTM(32,return_sequences=True))
model.add(LSTM(32))
# to avoid overfitting
model.add(Dropout(0.3))
# output layer
model.add(Dense(8,activation='softmax'))
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
Fitting the model
model.fit(scaled_train,train_labels,epochs=5,validation_data=(scaled_validation,valid_labels))
But when trying to fit the model, I got the error ValueError: Shapes (None, 8) and (None, 1, 8) are incompatible. Is there anything I did wrong in the code? Any help is highly appreciated.
The shape of my data
print(scaled_train.shape)
print(train_labels.shape)
print(scaled_validation.shape)
print(valid_labels.shape)
(7678, 1, 30)
(7678, 8)
(450, 30)
(450, 8)
EDIT
I've tried How to stack multiple lstm in keras?
But still, get the error ValueError: Input 0 of layer sequential_21 is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 30]
As the name suggests, return_sequences=True will return a sequence (with a time step), That's why your output shape is (None, 1, 8): the time step is maintained. It doesn't flatten automatically when it goes through the dense layer. Try:
model = Sequential()
model.add(LSTM(32,input_shape=(1,30),return_sequences=False))
model.add(Dense(32,activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(8,activation='softmax'))
I guess this doesn't happen if you uncomment the second LSTM layer?

Keras how to change trainable layers of a loaded model

I built and trained a network based on vgg16 network. In the original network I froze all the layers of vgg16 and trained only the last 4 layers which I added at the end of vgg16. Now I want to load and re-train this model by changing the trainable layers to use my own weights instead of ImageNet weights. Initially I tried to build the same model by changing the trainable layers of vgg16 and model weights with the following code.
# Load the VGG model
vgg_conv = VGG16(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
# Freeze n number of layers from the last
for layer in vgg_conv.layers[:-8]: layer.trainable = False
# Check the trainable status of the individual layers
for layer in vgg_conv.layers: print(layer, layer.trainable)
# Create and compile the model
model = createModel()
trained_model = keras.models.load_model(trained_dir)
model.set_weights(trained_model.get_weights())
model.compile(loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=lr), metrics=['acc'])
But this gives me this error:
ValueError: Cannot feed value of shape (3, 3, 3, 64) for Tensor 'Placeholder_869:0', which has shape '(3, 3, 256, 512)'
When I check the weights of the original and new networks I see that shapes of some weights are different. I also tried to change the trainable layers of the original network but for layer in trained_model.layers: print(layer, layer.trainable) shows only the last layers that I added. So how can change the trainable layers of my own trained_model? Or is there another way to get the same result?
This might be the possible solution. I created a vgg16 based model with above code. Then I changed weights of the last layers by running this code: model.layers[1].set_weights(trained_model.layers[1].get_weights()). Since I added 4 layers to vgg16 I executed this code by changing the layer index from 1 to 4. I have not tried the model yet. If this is not a correct solution I would be glad to read your answers.

Unexpected output from Embedding layer

I've been trying to implement an LSTM in Keras for several hours (using a sequential model with an embedding layer, two LSTM layers, and a dense layer), but I wind up getting different error messages.
From what I can tell, the problem is that the output of the embedding layer has two dimensions instead of three, because I get this value error (ValueError: Input 0 is incompatible with layer lstm_2: expected ndim=3, found ndim=2) when adding the second LSTM layer, and I get the error assert len(input_shape) >= 3 AssertionError when I delete the line for adding the second LSTM layer (which means the dense layer has the same issue).
These error occurs before I call the model's "train" method.
My code is here.
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
from keras.layers import Embedding
from keras.layers import TimeDistributed
from keras.preprocessing import text
from keras.preprocessing.sequence import pad_sequences
# The data in X was preprocessed using Keras' built in pad_sequences.
# Before preprocessing, it consisted of plain lists of integers (which
# were just integers wit a one-to-one map to plain words as strings)
X = pad_sequences(X)
model = Sequential()
model.add(Embedding(batch_size=32, input_dim=len(filtered_vocabulary)+1, output_dim=256, input_length=38))
model.add(LSTM(128))
model.add(LSTM(128)) # error occurs in this line
model.add(TimeDistributed(Dense(len(filtered_vocabulary)+1, activation="softmax")))
model.compile(optimizer = "rmsprop", loss="categorical_crossentropy", metrics=["accuracy"])
model.fit(X, X, epochs=60, batch_size=32)
I'd be glad if any of you could help me out with this.
The error occurs because the first LSTM layer only returns the last output because you haven't specified return_sequences=True in the LSTM layers. This looks like a multi-output setup so you would need to return the LSTM output at every time step using that argument for both layers.
Just to be clear, without return_sequences=True the shape is (None, 128); with the shape is (None, 38, 128).

merging recurrent layers with dense layer in Keras

I want to build a neural network where the two first layers are feedforward and the last one is recurrent.
here is my code :
model = Sequential()
model.add(Dense(150, input_dim=23,init='normal',activation='relu'))
model.add(Dense(80,activation='relu',init='normal'))
model.add(SimpleRNN(2,init='normal'))
adam =OP.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(loss="mean_squared_error", optimizer="rmsprop")
and I get this error :
Exception: Input 0 is incompatible with layer simplernn_11: expected ndim=3, found ndim=2.
model.compile(loss='mse', optimizer=adam)
It is correct that in Keras, RNN layer expects input as (nb_samples, time_steps, input_dim). However, if you want to add RNN layer after a Dense layer, you still can do that after reshaping the input for the RNN layer. Reshape can be used both as a first layer and also as an intermediate layer in a sequential model. Examples are given below:
Reshape as first layer in a Sequential model
model = Sequential()
model.add(Reshape((3, 4), input_shape=(12,)))
# now: model.output_shape == (None, 3, 4)
# note: `None` is the batch dimension
Reshape as an intermediate layer in a Sequential model
model.add(Reshape((6, 2)))
# now: model.output_shape == (None, 6, 2)
For example, if you change your code in the following way, then there will be no error. I have checked it and the model compiled without any error reported. You can change the dimension as per your need.
from keras.models import Sequential
from keras.layers import Dense, SimpleRNN, Reshape
from keras.optimizers import Adam
model = Sequential()
model.add(Dense(150, input_dim=23,init='normal',activation='relu'))
model.add(Dense(80,activation='relu',init='normal'))
model.add(Reshape((1, 80)))
model.add(SimpleRNN(2,init='normal'))
adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
model.compile(loss="mean_squared_error", optimizer="rmsprop")
In Keras, you cannot put a Reccurrent layer after a Dense layer because the Dense layer gives output as (nb_samples, output_dim). However, a Recurrent layer expects input as (nb_samples, time_steps, input_dim). So, a Dense layer gives a 2-D output, but a Recurrent layer expects a 3-D input. However, you can do the reverse, i.e., put a Dense layer after a Recurrent layer.

Categories