Use part of the layers of VGG19 in Keras with TimeDistributed layer - python

I want to use the first 9 layers of the trained VGG19 model combined with TimeDistributed layers. But I get an InvalidArgumentError.
def build_vgg(in_shape):
vgg = VGG19(weights="imagenet")
vgg.outputs = [vgg.layers[9].output]
img = keras.Input(in_shape)
img_features = vgg(img)
return keras.Model(img, img_features)
vggmodel = build_vgg((50,50,3))
input_layer = keras.Input(batch_shape=(10,10,50,50,3))
h2 = keras.layers.wrappers.TimeDistributed(vggmodel)(input_layer)
model = keras.Model(input_layer,h2)
model.summary()
I'm getting this error:
InvalidArgumentError Traceback (most recent call last)
~/.conda/envs/py3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in _create_c_op(graph, node_def, inputs, control_inputs)
1566 try:
-> 1567 c_op = c_api.TF_FinishOperation(op_desc)
1568 except errors.InvalidArgumentError as e:
InvalidArgumentError: Dimensions must be equal, but are 512 and 25088 for 'time_distributed_1/vgg19/fc1/MatMul' (op: 'MatMul') with input shapes: [10,512], [25088,4096].

First, your model should not use an additional input in build_vgg. You should only take the tensors you want.
Second, you should use a compatible input shape.
Third, you can't include top if you're changing the input shape AND loading imagenet weights:
def build_vgg(in_shape):
vgg = VGG19(weights="imagenet", input_shape= in_shape, include_top = False)
outputs = vgg.layers[9].output
return keras.Model(vgg.input, outputs)
Then the rest
vggmodel = build_vgg((50,50,3))
#vggmodel.summary()
input_layer = keras.Input(batch_shape=(10,10,50,50,3))
h2 = keras.layers.wrappers.TimeDistributed(vggmodel)(input_layer)
model = keras.Model(input_layer,h2)
model.summary()
model.predict(np.ones((10,10,50,50,3)))

Related

Keras Subclassed Models Graph Disconnected Error

I'm trying to do an experiment to see if I can run multiple subclassed Keras models in a loop; and if so, check performance. Ultimately I want to see if numpy will perform better than Keras in a situation like this. The model itself is a simple linear activation function. Before I can do that however; I keep getting an error that doesn't make sense to me. It's complaining that the layers are not fully connected.
Error details are here:
ValueError Traceback (most recent call last)
<ipython-input-7-46e8d341a752> in <module>
38 for i in range(len(faces)):
39 input_layer = Input(shape=1)
---> 40 model = Model(inputs=input_layer, outputs=faces[i])
41 model.compile(optimizer='adam', loss="mean_squared_error")
42 model.fit(x=signal, y=locations, batch_size=1)
4 frames
/usr/local/lib/python3.8/dist-packages/keras/engine/functional.py in _map_graph_network(inputs, outputs)
996 for x in tf.nest.flatten(node.keras_inputs):
997 if id(x) not in computable_tensors:
--> 998 raise ValueError(
999 f'Graph disconnected: cannot obtain value for tensor {x} '
1000 f'at layer "{layer.name}". The following previous layers '
ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 1), dtype=tf.float32, name='input_7'), name='input_7', description="created by layer 'input_7'") at layer "particle_200". The following previous layers were accessed without issue: []
Code is here:
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
class particle(tf.keras.Model):
def __init__(self):
super(particle, self).__init__()
#creating layers in initializer
self.fc = Dense(units=9, activation=None, use_bias=True)
def call(self, input_tensor):
x = self.fc(input_tensor)
return x
faces = []
input_layer = Input(shape=1)
for i in range(40):
faces.append(particle()(input_layer))
locations = np.arange(9)
signal = 1
start = time.time()
for i in range(len(faces)):
input_layer = Input(shape=1)
model = Model(inputs=input_layer, outputs=faces[i])
model.compile(optimizer='adam', loss="mean_squared_error")
model.fit(x=signal, y=locations, batch_size=1)
end = time.time()
print(end - start)

How to connect a LSTM layer to a Linear layer in Pytorch

I am doing a classification task of MFCC (time-series data) using LSTM.
I have input (16,60,40) (Batch,step,features)
class model(nn.Module):
def __init__(self,ninp,num_layers,class_num,nhid=128):
super().__init__()
self.lstm_nets = nn.LSTM(input_size=ninp,hidden_size=nhid,num_layers=num_layers,
batch_first=True,dropout=0.2,bidirectional=False)
self.FC = nn.Linear(nhid,class_num)
self.tanh = nn.Tanh()
self.softmax = nn.LogSoftmax(1)
def forward(self,X):
device = 'cuda:0'
out, (ht, ct) = self.lstm_nets(X)
# out = ht.contiguous().view(16,-1)
out = self.tanh(out)
out = self.FC(out)
Out = self.softmax(out)
return Out
model = model(ninp=X.shape[2],num_layers=1,class_num=32,nhid=128)
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.5e-4)
If I have out = ht.contiguous().view(16,-1) that flattens the LSTM output, I got error
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-96-a7e2ba68dcd9> in <module>()
11
12 optimizer.zero_grad()
---> 13 y_pred = model(X)
14 # calculate loss function
15 loss = loss_function(y_pred, y)
3 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/modules/linear.py in forward(self, input)
101
102 def forward(self, input: Tensor) -> Tensor:
--> 103 return F.linear(input, self.weight, self.bias)
104
105 def extra_repr(self) -> str:
RuntimeError: mat1 and mat2 shapes cannot be multiplied (16x32 and 128x32)
If I have out = out.contiguous().view(16,-1) that flattens the LSTM output, I got error RuntimeError: mat1 and mat2 shapes cannot be multiplied (16x7680 and 128x32)
If I remove the Flatten Step, I got such an error. RuntimeError: Expected target size [16, 32], got [16]
In addition, I found examples online do not flatten the output of LSTM
Thanks for any help.
In each timestep of an LSTM the input goes through a simple neural network and the output gets passed to the next timestep.
The output out of function
out, (ht, ct) = self.lstm_nets(X)
contains a list of ALL outputs (i.e the output of the neural networks of every timestep). Yet, in classification, you mostly only really care about the LAST output. You can get it like this:
out = out[:, -1]
This output has now the shape (hidden-size, 1).
So in your case your forward function should look like this:
def forward(self,X):
device = 'cuda:0'
out, (ht, ct) = self.lstm_nets(X)
out = out[: ,-1]
out = self.tanh(out)
out = self.FC(out)
Out = self.softmax(out)
return Out

Layer count mismatch when loading weights from file. Model expected 106 layers, found 4 saved layers

I have this network (from SimClR paper):
base_model = tf.keras.applications.ResNet50(include_top=False, weights=None, input_shape=(224, 224, 3))
base_model.trainable = True
#inputs = Input((224, 224, 3))
inputs = Input((224, 224, 3))
h = base_model(inputs, training=True)
h = GlobalAveragePooling2D()(h)
projection_1 = Dense(256)(h)
projection_1 = Activation("relu")(projection_1)
projection_2 = Dense(128)(projection_1)
projection_2 = Activation("relu")(projection_2)
projection_3 = Dense(50)(projection_2)
resnet_simclr = Model(inputs, projection_3)
thane after training the model, I saved it:
resnet_simclr.save_weights(filename)
However, after trying to load the weight in ResNet50 like this:
inputs = tf.keras.layers.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3), name="input_image")
Resmodel = tf.keras.applications.ResNet50(input_tensor=inputs, weights=weights_path, include_top=False)
I got this error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-92-cb642379c2ae> in <module>()
3 from keras.utils.vis_utils import plot_model
4 inputs = tf.keras.layers.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3), name="input_image")
----> 5 Resmodel = tf.keras.applications.ResNet50(input_tensor=inputs, weights=weights_path, include_top=False) # weights="imagenet"
6 #Resmodel.load_weights(weights_path)
7 Resmodel.summary()
3 frames
/usr/local/lib/python3.7/dist-packages/keras/saving/hdf5_format.py in load_weights_from_hdf5_group(f, model)
718 if len(layer_names) != len(filtered_layers):
719 raise ValueError(
--> 720 f'Layer count mismatch when loading weights from file. '
721 f'Model expected {len(filtered_layers)} layers, found '
722 f'{len(layer_names)} saved layers.')
ValueError: Layer count mismatch when loading weights from file. Model expected 106 layers, found 4 saved layers.
EDIT
The issue I'm trying to do transfer learning (down stream) from RestNet50 with have also 3 projection layer to RestNet50 ( part of Unet backbone) but this Rasnet do not have project head like the trained model. I'm not sure how to fix that.
Try Saving the model again
resnet_simclr.layers[1].save_weights(filename)

ValueError: total size of new array must be unchanged (Reshape from keras)

For this toy model:
from keras.layers import Input, Dense, Reshape
from keras.models import Model
# this is the size of our encoded representations
compression = 10
input_img = Input(shape=(28,28, ), name= "28x28")
encoded = Dense(int(np.floor(28*28/compression)), activation='relu',
name= "encoder_" + str(compression))(input_img)
decoded = Dense(units = 28*28, activation='sigmoid',
name = "28.28_decoder")(encoded)
reshape = Reshape(target_shape = (28,28), name = "28x28_reshape")(decoded)
autoencoder = Model(input_img, reshape)
I get the error:
ValueError Traceback (most recent call last)
<ipython-input-27-04b835543369> in <module>
12 decoded = Dense(units = 28*28, activation='sigmoid',
13 name = "28.28_decoder")(encoded)
---> 14 reshape = Reshape(target_shape = (28,28), name = "28x28_reshape")(decoded)
15 autoencoder = Model(input_img, reshape)
16
~/.local/lib/python3.6/site-packages/keras/engine/base_layer.py in __call__(self, inputs, **kwargs)
472 if all([s is not None
473 for s in to_list(input_shape)]):
--> 474 output_shape = self.compute_output_shape(input_shape)
475 else:
476 if isinstance(input_shape, list):
~/.local/lib/python3.6/site-packages/keras/layers/core.py in compute_output_shape(self, input_shape)
396 # input shape known? then we can compute the output shape
397 return (input_shape[0],) + self._fix_unknown_dimension(
--> 398 input_shape[1:], self.target_shape)
399
400 def call(self, inputs):
~/.local/lib/python3.6/site-packages/keras/layers/core.py in _fix_unknown_dimension(self, input_shape, output_shape)
384 output_shape[unknown] = original // known
385 elif original != known:
--> 386 raise ValueError(msg)
387
388 return tuple(output_shape)
ValueError: total size of new array must be unchanged
I have been trying to figure out why but I do not get it. Looking at the help page it rather straightforward, since the previous layer is the adequate shape to perform the reshape.
Your decoded dense layer has 28*28 units, this will be make its output dim to be (,28,784) which won't reshape to 28*28.
Based on what you want to do, you are supposed to flatten the array beforehand. This should work:
flatten = Flatten()(input_img)
encoded = Dense(int(np.floor(28*28/compression)), activation='relu', name= "encoder_" + str(compression))(flatten)
decoded = Dense(units = 28*28, activation='sigmoid', name = "28.28_decoder" (encoded)
reshape = Reshape(target_shape = (28,28), name = "28x28_reshape")(decoded)
autoencoder = Model(input_img, reshape)
I assume that the initial reshape didn't work because you are passing 3D tensor through a dense layer, and the initial dimension gets messed up. Therefore, you can get it back into the initial shape.

Keras Lambda layer throws ndim error in functional API, but not in Sequential

I'm trying to get the output from an LSTM layer per time step, and at the last time step only (step output and the context vector) separately, so I found that the solution to do that is to make a lambda layer that extracts the context vector from the LSTM with return_sequences=True. In the Sequential model it worked fine, but when I'm trying to implement it in the functional API it is suddenly not accepting the dimensions anymore, stating that everything is of ndim=1 even though it is not.
code:
def ContextVector(x):
return x[-1][-1]
def ContextVectorOut(input_shape):
print([None, input_shape[-1]])
print((input_shape[::2]))
print(input_shape)
return list((None, input_shape[-1]))
input_layer = Input(shape=(10, 5))
LSTM_layer = LSTM(5, return_sequences=True)(input_layer)
context_layer = Lambda(ContextVector, output_shape=ContextVectorOut)(LSTM_layer)
repeat_context_layer = RepeatVector(10, name='context')(context_layer)
timed_dense = TimeDistributed(Dense(10))(LSTM_layer)
connected_dense = Dense(2)
connect_dense_context = connected_dense(repeat_context_layer)
connect_dense_time = connected_dense(timed_dense)
concat_out = concatenate([connect_dense_context, connect_dense_time])
output_dense = Dense(5)(concat_out)
model = Model(inputs = [input_layer], output = output_dense)
#model.add(LSTM(20, input_shape = (10, 5), return_sequences=True))
#model.add(Lambda(ContextVector, output_shape=ContextVectorOut))
#model.add(Dense(1))
model.summary()
Error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-74-016b4a976d40> in <module>()
10 LSTM_layer = LSTM(5, return_sequences=True)(input_layer)
11 context_layer = Lambda(ContextVector, output_shape=ContextVectorOut)(LSTM_layer)
---> 12 repeat_context_layer = RepeatVector(10, name='context')(context_layer)
13 timed_dense = TimeDistributed(Dense(10))(LSTM_layer)
14 connected_dense = Dense(2)
C:\ProgramData\Miniconda3\lib\site-packages\keras\engine\base_layer.py in __call__(self, inputs, **kwargs)
412 # Raise exceptions in case the input is not compatible
413 # with the input_spec specified in the layer constructor.
--> 414 self.assert_input_compatibility(inputs)
415
416 # Collect input shapes to build layer.
C:\ProgramData\Miniconda3\lib\site-packages\keras\engine\base_layer.py in assert_input_compatibility(self, inputs)
309 self.name + ': expected ndim=' +
310 str(spec.ndim) + ', found ndim=' +
--> 311 str(K.ndim(x)))
312 if spec.max_ndim is not None:
313 ndim = K.ndim(x)
ValueError: Input 0 is incompatible with layer context: expected ndim=2, found ndim=1
I found my mistake. I was returning x[-1][-1], where I should've returned x[-1] only. The ndim error is from the Lambda layer, not the previous layer.

Categories