How to select top-k elements of a keras dense layer? - python-3.x

I'm trying to perform a k-max pooling in order to select top-k elements of a dense with shape (None, 30). I tried a MaxPooling1D layer but it doesn't work, since keras pooling layers require at least a 2d input shape. I'm using the following Lambda layer, but I got the following error:
layer_1.shape
(None, 30)
layer_2 = Lambda(lambda x: tf.nn.top_k(x, k=int(int(x.shape[-1])/2),
sorted=True,
name="Top_k_final"))(layer_1)
Error: File
"/usr/local/lib/python3.5/dist-packages/keras/engine/base_layer.py",
line 474, in call
output_shape = self.compute_output_shape(input_shape) File "/usr/local/lib/python3.5/dist-packages/keras/layers/core.py", line
652, in compute_output_shape
return K.int_shape(x) File "/usr/local/lib/python3.5/dist-packages/keras/backend/tensorflow_backend.py",
line 591, in int_shape
return tuple(x.get_shape().as_list()) AttributeError: 'TopKV2' object has no attribute 'get_shape'

Based on this example, I solved the problem. In fact, I solved the problem by adding .values to get the tensor values from the tf.nn.top_k, as follows. But I'm not sure if my solution is correct or not.
layer_2 = Lambda(lambda x: tf.nn.top_k(x, k=int(int(x.shape[-1])/2),
sorted=True,
name="Top_k_final").values)(layer_1)

Related

Obtaining hidden layer outputs in a denoising autoencoder using Keras

I have built a Sequential Keras model with three layers: A Gaussian Noise layer, a hidden layer, and the output layer with the same dimension as the input layer. For this, I'm using the Keras package that comes with Tensorflow 2.0.0-beta1. Thus, I'd like to get the output of the hidden layer, such that I circumvent the Gaussian Noise layer since it's only necessary in the training phase.
To achieve my goal, I followed the instructions in https://keras.io/getting-started/faq/#how-can-i-obtain-the-output-of-an-intermediate-layer, which are pretty much described in Keras, How to get the output of each layer? too.
I have tried the following example from the official Keras documentation:
from tensorflow import keras
from tensorflow.keras import backend as K
dae = keras.Sequential([
keras.layers.GaussianNoise( 0.001, input_shape=(10,) ),
keras.layers.Dense( 80, name="hidden", activation="relu" ),
keras.layers.Dense( 10 )
])
optimizer = keras.optimizers.Adam()
dae.compile( loss="mse", optimizer=optimizer, metrics=["mae"] )
# Here the fitting process...
# dae.fit( ยท )
# Attempting to retrieve a decoder functor.
encoder = K.function([dae.input, K.learning_phase()],
[dae.get_layer("hidden").output])
However, when K.learning_phase() is used to create the Keras backend functor, I get the error:
Traceback (most recent call last):
File "/anaconda3/lib/python3.6/contextlib.py", line 99, in __exit__
self.gen.throw(type, value, traceback)
File "/anaconda3/lib/python3.6/site-packages/tensorflow_core/python/keras/backend.py", line 534, in _scratch_graph
yield graph
File "/anaconda3/lib/python3.6/site-packages/tensorflow_core/python/keras/backend.py", line 3670, in __init__
base_graph=source_graph)
File "/anaconda3/lib/python3.6/site-packages/tensorflow_core/python/eager/lift_to_graph.py", line 249, in lift_to_graph
visited_ops = set([x.op for x in sources])
File "/anaconda3/lib/python3.6/site-packages/tensorflow_core/python/eager/lift_to_graph.py", line 249, in <listcomp>
visited_ops = set([x.op for x in sources])
AttributeError: 'int' object has no attribute 'op'
The code works great if I don't include K.learning_phase(), but I need to make sure that the output from my hidden layer is evaluated over an input that is not polluted with noise (i.e. in "test" mode -- not "training" mode).
I know my other option is to create a model from the original denoising autoencoder, but can anyone point me into why my approach from the officially documented functor creation fails?
Firstly, ensure your packages are up-to-date, as your script works fine for me. Second, encoder won't get the outputs - continuing from your snippet after # Here is the fitting process...,
x = np.random.randn(32, 10) # toy data
y = np.random.randn(32, 10) # toy labels
dae.fit(x, y) # run one iteration
encoder = K.function([dae.input, K.learning_phase()], [dae.get_layer("hidden").output])
outputs = [encoder([x, int(False)])][0][0] # [0][0] to index into nested list of len 1
print(outputs.shape)
# (32, 80)
However, as of Tensorflow 2.0.0-rc2, this will not work with eager execution enabled - disable via:
tf.compat.v1.disable_eager_execution()

Conv2D + LSTM network giving errors

I have a list of matrices called charMatrixList, of length 40744. I convert this list to numpy array, and the shape changes to (40744,32,30). This numpy array is passed as an input to the neural network.
The errors I'm getting are related to the shape of the Conv2D layer output, when passed as an input into an LSTM layer.
from keras.models import Sequential
from keras.layers import Embedding,LSTM,Flatten,Conv2D,Reshape
import numpy as np
def phase22(charMatrixList ):
model = Sequential()
model.add(Conv2D(32, (3, 3), strides=(1,1) , padding="same", activation="relu",input_shape=(40744,32,30)))
model.add(LSTM(16, return_sequences=True))
model.add(LSTM(16, return_sequences=True))
model.add(Flatten())
model.compile('rmsprop', 'mse')
input_array = charMatrixList
model.compile('rmsprop', 'mse')
output_array = model.predict(input_array)
return output_array
p2out = phase22(charMatrixList)
I'm getting the below error :
Traceback (most recent call last):
File "<ipython-input-56-f615f91b6704>", line 1, in <module>
p2out = phase22(np.array(charMatrixList) )
File "<ipython-input-55-9a4fd292a04f>", line 4, in phase22
model.add(LSTM(16, return_sequences=True))
File "C:\Users\Kishore\Anaconda3\lib\site-packages\keras\engine\sequential.py", line 185, in add
output_tensor = layer(self.outputs[0])
File "C:\Users\Kishore\Anaconda3\lib\site-packages\keras\layers\recurrent.py", line 500, in __call__
return super(RNN, self).__call__(inputs, **kwargs)
File "C:\Users\Kishore\Anaconda3\lib\site-packages\keras\engine\base_layer.py", line 414, in __call__
self.assert_input_compatibility(inputs)
File "C:\Users\Kishore\Anaconda3\lib\site-packages\keras\engine\base_layer.py", line 311, in assert_input_compatibility
str(K.ndim(x)))
ValueError: Input 0 is incompatible with layer lstm_11: expected ndim=3, found ndim=4
Keras ignores the first dimension when defining input size because that is just the number of training examples, m. Keras is able to work with any m, so it only cares about the actual input dimensions. That is why Kears sees (40744,32,30) as 4 dimensions.
I'm confused by the dimensions of your input, is 40744 the number of training examples? If it is do input_size = (32, 30).
If your input has 3 dimensions include number of training examples in your input, ie. charMatrixList = (m, 40744,32,30)

Struggle with LSTM and RNN using Keras

I'm working on a speech recognition problem running on Colab using LSTM. The audio files were converted into spectrograms and then normalized. There are 6840 spectrograms in total and the shape of each one is (288, 864, 4).
I already tried a few examples with RNN and CNN and they worked, but when I try an example using a LSTM I get shape errors, every time either there is one more or one less dimension than expected. Here are some of these cases :
rnn = keras.Sequential()
rnn.add(keras.layers.SimpleRNN(500, input_shape = (864, 4)))
rnn.add(keras.layers.LSTM(500, return_sequences = True))
rnn.add(keras.layers.Dropout(0.2))
rnn.add(keras.layers.LSTM(500, return_sequences = True))
rnn.add(keras.layers.Dropout(0.2))
rnn.add(keras.layers.LSTM(500, return_sequences = True))
rnn.add(keras.layers.Dropout(0.2))
rnn.add(keras.layers.Dense(212, activation = 'softmax'))
rnn.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy',metrics = ['accuracy'])
rnn.fit(X_train, y_train, epochs = 5, validation_data=(X_test, y_test))
scores = rnn.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', '%.2f' % (scores[1] * 100), '%')
The following error is raised on the first LSTM layer : ValueError: Input 0 of layer lstm_54 is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 500]
If I remove the SimpleRNN line and feed the input directly to the first LSTM like this
rnn.add(keras.layers.LSTM(500, return_sequences = True, input_shape = (288, 864, 4)))
I get : ValueError: Input 0 of layer lstm_56 is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: [None, 288, 864, 4]
I tried reshaping the images to (4, 288 * 864) and got the same error when trying to use the RNN layer, but with just the LSTM I got InvalidArgumentError: Incompatible shapes: [32] vs. [32,4].
No idea where the 32 came from, though.
One last thing, not really an issue but more of a request, is there any library that can resize images the simple way? 288x864 is too big for Colab, so I'll have to do it eventually to be able to load all 6840 images and feed it to the neural network. Right now I'm just using 100 samples to test.
Feel free to leave suggestions about other methods, cabalistic number of nodes/layers or anything like that.
LSTM input is 3 dimensions [n_samples, n_timesteps, n_features], so your first line also need to enable return sequences:
rnn.add(keras.layers.SimpleRNN(500, return_sequences = True, input_shape = (864, 4)))
Next, your Dense layer will complain from wrong input size, so you want to remove return_sequence on the last LSTM network:
rnn.add(keras.layers.LSTM(500))
If you still want to keep the return_sequences = True on the last LSTM layer, you might want to wrap the Dense layer in a TimeDistributed.
I tried it on the following input and they seems to work
X_train = np.random.rand(100, 864, 4)
y_train = np.random.rand(100, 1)
The PIL from pillow package has plenty of image manipulation methods.

LSTM - Incompatible layer, dimension mismatch?

I'm trying to set up an LSTM model with Keras. The training data has the dimension [7165, 27], and with my current setup it throws the following error:
File "C:\Users\Eier\Anaconda3\lib\site-packages\keras\models.py", line 441, in __init__
self.add(layer)
File "C:\Users\Eier\Anaconda3\lib\site-packages\keras\models.py", line 497, in add
layer(x)
File "C:\Users\Eier\Anaconda3\lib\site-packages\keras\layers\recurrent.py", line 500, in __call__
return super(RNN, self).__call__(inputs, **kwargs)
File "C:\Users\Eier\Anaconda3\lib\site-packages\keras\engine\topology.py", line 575, in __call__
self.assert_input_compatibility(inputs)
File "C:\Users\Eier\Anaconda3\lib\site-packages\keras\engine\topology.py", line 474, in assert_input_compatibility
str(K.ndim(x)))
ValueError: Input 0 is incompatible with layer lstm_64: expected ndim=3, found ndim=4
I know this error is fairly common, but none of the many different solutions found online have worked for me yet. I have already trying reshaping the training data to a 3D matrix, fooling around with different layer combinations, explictly stating batch size, using Flatten() and more to no avail. Would be very grateful if someone could push me in the right direction for fixing this.
Code snippet:
input_dim = 27
units = 5
timesteps = 1
samples = X_train.shape[0]
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1]))
model = Sequential([
LSTM(units, return_sequences=True, stateful = True, input_shape=(samples,timesteps,input_dim)),
Dropout(0.2),
LSTM(units,return_sequences=False),
Dropout(0.2),
Dense(1),
Activation('softmax'),
])
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
model.fit(X_train, y_train, batch_size = 32, epochs = 60)
As pointed out by #ShubhamPanchal in comments you don't need to specify samples dimension. LSTM layer expects input to have shape [batch_size, time_steps, channels), so when you pass input_shape argument you have to pass tuple specifying time_steps and channels dimension.
LSTM(32, return_sequences=True, stateful = True, input_shape=(time_steps, input_dim))
Since you are using stateful lstm you need to specify the batch_size argument also. So the full code for the model would be,
model = Sequential([
LSTM(units, return_sequences=True, stateful = True, input_shape=(timesteps,input_dim), batch_size=batch_size),
Dropout(0.2),
LSTM(units,return_sequences=False),
Dropout(0.2),
Dense(1),
Activation('softmax'),
])

Working on using Keras VGG16 -- Trouble output shapes

I am trying to train the VGG16 model (from keras.applications) from scratch and I get a weird error
X_train shape is (73257, 48, 48, 3)
Y_train shape is (73257, 10)
I have no idea what's going on... I assume it has to do with the conv layer before it but since I'm importing the model directly from keras I'm having issues figuring out where I went wrong.
My dataset is comprised of 73,257 images which have (48,48,3) shape. I am essentially trying to do character recognition (think mnist flavor) but I am getting hung up on feeding this through the model (with weights set to 0).
model = keras.applications.vgg16.VGG16(include_top=False,
weights=None,
input_shape=(48, 48, 3),
input_tensor=None, pooling='avg', classes=10)
sgd = SGD(lr=.1)
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])
print('X_train shape is {}'.format(X_train.shape))
print('Y_train shape is {}'.format(y_train.shape))
model.fit(X_train, y_train,
epochs=20,
batch_size=128)
score = model.evaluate(X_test, y_test, batch_size=128)
This is the error I am getting
File "/home/codebrotherone/PycharmProjects/Computer Vision/deep_neural/dnn.py", line 169, in VGG16
batch_size=128)
File "/home/codebrotherone/anaconda2/envs/tensorflow/lib/python3.4/site-packages/keras/engine/training.py", line 1574, in fit
batch_size=batch_size)
File "/home/codebrotherone/anaconda2/envs/tensorflow/lib/python3.4/site-packages/keras/engine/training.py", line 1411, in _standardize_user_data
exception_prefix='target')
File "/home/codebrotherone/anaconda2/envs/tensorflow/lib/python3.4/site-packages/keras/engine/training.py", line 141, in _standardize_input_data
str(array.shape))
ValueError: Error when checking target: expected block5_pool to have 4 dimensions, but got array with shape (73257, 10)
Ideally, for classification problems, you should have include_top=True and classes=10.
This is enough. Since you're not including top, and are using a global pooling, you should end up with something like (73257,512). But the message you're getting suggests that you have not used the pooling in this attempt. Something is not quite matching.
Anyway, go with this:
model = keras.applications.vgg16.VGG16(include_top=True,
input_shape=(48, 48, 3),
classes=10)

Resources