How deal with variable length LSTM NN? - tensorflow

I'm analyzing sequences of coordinates with different lengths and need to classify in actions.
For this task I'm using LSTM, but fitting is not working, I prepared 2 dummy examples of the issue I'm having, the 1st one is working properly if you run it in colab (sequence with fixed length) and the 2nd one is raising errors (sequence with variable length):
1.- Example 1: Fixed length - Status: OK
from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.utils import np_utils
import numpy as np
#FIXED LENGTH
def build_model_test():
model = Sequential()
model.add(LSTM(64, input_shape=(2, 3) , return_sequences=True))
model.add(Dense(1, activation='softmax'))
return model
dataset = np.array([np.array([[1, 4, 6 ], [9, 3, 1]]),
np.array([[1, 4, 6 ], [9, 3, 1]]),
np.array([[1, 4, 6 ], [9, 3, 1]])])
labels_test = np.array([1, 0, 1])
labels_test = to_categorical(labels_test)
model_test = build_model_test()
model_test.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model_test.fit(dataset, labels_test, batch_size=1, epochs=1)
2.- Example 2: Variable length - Status: ERROR
from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.utils import np_utils
import numpy as np
# SIZE TEST 2: VAERIABLE LENGHT
def build_model_test():
model = Sequential()
model.add(LSTM(64, input_shape=(None, 3) , return_sequences=True)) #CHANGE_1: None, 3
model.add(Dense(1, activation='softmax'))
return model
dataset = np.array([np.array([[1, 4, 6 ], [9, 3, 1], [9, 3, 1]]), #CHANGE_2: Shape of 1st item from 2 to 3
np.array([[1, 4, 6 ], [9, 3, 1]]),
np.array([[1, 4, 6 ], [9, 3, 1]])])
labels_test = np.array([1, 0, 1])
labels_test = to_categorical(labels_test)
model_test = build_model_test()
model_test.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model_test.fit(dataset, labels_test, batch_size=1, epochs=1)
Do you know how can I fix example 2?
Thanks in advance!

Related

Multiclass classification label error using TensoFlow

I am doing a multiclass classification using TensorFlow. Target has 4 values[0, 1, 13, 14]. That is why I took 4 in the last Dense Layer. I am using sparse_categorical_crossentropy in my loss function. My code is as follows:-
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPool1D, Dropout, Conv2D
import matplotlib.pyplot as plt
x_train, x_test, y_train, y_test = train_test_split(X, data['seg_type'], test_size=0.33, random_state=1)
#The known number of output classes.
labels = [0, 1, 13, 14]
num_classes = 4
# # label encoding
# encoder = LabelEncoder()
# y_train = encoder.fit_transform(y_train)
# y_test = encoder.fit_transform(y_test)
# # one hot encoding
# y_train = tensorflow.keras.utils.to_categorical(y_train, num_classes)
# y_test = tensorflow.keras.utils.to_categorical(y_test, num_classes)
y_train = np.array(y_train)
y_test = np.array(y_test)
# build CNN model
model = Sequential()
model.add(Conv2D(32, (1, 1) , input_shape = (1, 3, 1), activation='relu'))
model.add(Conv2D(64, (1, 1) , input_shape = (1, 3, 1), activation='relu'))
model.add(Conv2D(128, (1, 1) ,activation='relu'))
model.add(Flatten()) # flatten
model.add(Dense(32, activation='relu')) # fc
model.add(Dense(64, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(4, activation='softmax'))
# model compile
model.compile(loss='sparse_categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.summary()
batch_size = 32
epochs = 20
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=2)
But after fitting the model it shows the error: -
InvalidArgumentError: Received a label value of 14 which is outside the valid range of [0, 4). Label values: 14 14 13 13 13 14 13 13 14 1 13 13 14 14 14 1 14 13 1 14 13 14 14 13 1 14 13 14 1 14 14 14
[[node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits (defined at <ipython-input-81-33f0652484e5>:6) ]] [Op:__inference_train_function_574154]
Function call stack:
train_function
Full code - My notebook
Data - Access the data here
Thanks in advance!!!!!!!!!!
As you have used four labels in your code here,
#The known number of output classes.
labels = [0, 1, 13, 14]
num_classes = 4
The valid range of your labels is 0,1,2 & 3. So the values while passing for prediction should always come from this range itself, the model does not recognizes 13 and 14 values.
You need to use any encoder to convert your input labels to valid range and do reverse while predicting for them.
You can just change your labels to range with in [0,3] for workaround.
change the loss function from sparse_categorical_crossentropy to categorical crossentroy and convert data into the categorical data
from keras.utils import to_categorical
y_data = to_categorical(y_data, classes = 4)
Now it will work, the present situation is the classes should be like [0, 1, 2, 3] but you are using [0, 1, 13, 14]. the solution for this is to categorical function

neural network in Keras with two different input types - images and values

At the moment i have a working CNN that outputs a value from -1 to 1 from a given image. Now I also want to input given values to the network, because they could really add accuracy to the output. That job of course can't be done with a CNN, but it should be possible to add them to the fully connected layers, shouldn't it?
Would be great if somebody showed me how to approach that with Keras.
My current CNN:
model = Sequential()
model.add(Lambda(lambda x: x/127.5-1.0, input_shape=(66,200,3)))
model.add(Conv2D(24, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(36, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(48, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(64, 3, 3, activation='elu'))
model.add(Conv2D(64, 3, 3, activation='elu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(100, activation='elu'))
model.add(Dense(50, activation='elu'))
model.add(Dense(10, activation='elu'))
model.add(Dense(1))
model.summary()
How I think it should work:
~Modified graphic from
https://blog.insightdatascience.com/classifying-e-commerce-products-based-on-images-and-text-14b3f98f899e.
Diego gave the answer I'll just build a model as an example using the Functional API. Let's assume you have 3 features that you want to
add to each image. Each feature is a single real number so if we concatenate them we have a feature vector with three components.
from keras.layers import ( Conv2D, Flatten, Lambda, Dense, concatenate,
Dropout, Input )
from keras.models import Model
image = np.random.rand(10, 66, 200, 3)
feature = np.random.rand(10, 3) # feature vector
y = np.random.normal(0, 1, (10, 1))
image_input = Input(shape=(66, 200, 3))
aux_input = Input(shape=(3,))
lamb = Lambda(lambda x: x/127.5-1.0, input_shape=(66,200,3))(image_input)
cov1 = Conv2D(24, 5, 5, activation='elu', subsample=(2, 2))(lamb)
cov2 = Conv2D(36, 5, 5, activation='elu', subsample=(2, 2))(cov1)
cov3 = Conv2D(48, 5, 5, activation='elu', subsample=(2, 2))(cov2)
cov4 = Conv2D(64, 3, 3, activation='elu')(cov3)
cov5 = Conv2D(64, 3, 3, activation='elu')(cov4)
dropout = Dropout(0.5)(cov5)
flatten = Flatten()(dropout)
# Here we add in the feature vectors
merge = concatenate([flatten, aux_input])
d1 = Dense(100, activation='elu')(merge)
d2 = Dense(50, activation='elu')(d1)
d3 = Dense(10, activation='elu')(d2)
out = Dense(1)(d3)
model = Model(inputs=[image_input, aux_input], outputs=[out])
model.compile(loss='mse', optimizer='rmsprop')
model.fit([image, feature], y)
If you are trying to reproduce the model on your image, you can't use Sequential from Keras.
You'll need to use Model, it will be very similar but with some mods:
Add the text vector as an extra placeholder/input
Merge the output of the CNN with the output of the FC layers of the vectorized text
Finally, add some other FC layers and the output

How to convert the CIFAR10 tutorial to NCHW

I'm trying to convert the Tensorflow CIFAR10 tutorial from NHWC to NCHW, but can't figure out how to do so. I have only found answers such as this, which is a couple of lines of code without an explanation of how it works and where to use it. Here are a couple of unsuccessful attempts I have made using this approach:
def inference(images):
with tf.variable_scope('conv1') as scope:
kernel = _variable_with_weight_decay('weights',
shape=[5, 5, 3, 64],
stddev=5e-2,
wd=0.0)
# ****************************************************************** #
### Original
conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')
### Attempt 1
imgs = tf.transpose(images, [0, 3, 1, 2]) # NHWC -> NCHW
conv = tf.nn.conv2d(imgs, kernel, [1, 1, 1, 1], padding='SAME')
conv = tf.transpose(conv, [0, 2, 3, 1]) # NCHW -> NHWC
### Attempt 2
kern = tf.transpose(kernel, [0, 3, 1, 2]) # NHWC -> NCHW
conv = tf.nn.conv2d(images, kern, [1, 1, 1, 1], padding='SAME')
conv = tf.transpose(conv, [0, 2, 3, 1]) # NCHW -> NHWC
# ****************************************************************** #
biases = _variable_on_cpu('biases', [64], tf.constant_initializer(0.0))
pre_activation = tf.nn.bias_add(conv, biases)
conv1 = tf.nn.relu(pre_activation, name=scope.name)
_activation_summary(conv1)
...
Which get the errors (respectively):
ValueError: Dimensions must be equal, but are 24 and 3 for 'conv1/Conv2D' (op: 'Conv2D') with input shapes: [64,3,24,24], [5,5,3,64].
ValueError: Dimensions must be equal, but are 3 and 5 for 'conv1/Conv2D' (op: 'Conv2D') with input shapes: [64,24,24,3], [5,64,5,3].
Can someone please provide a set of steps I can follow to convert this example to NCHW successfully.
In your attempt #1 , try the following:
conv = tf.nn.conv2d(imgs, kernel, [1, 1, 1, 1], padding='SAME', data_format = 'NCHW')
(i.e. add data_format = 'NCHW' to the parameters)
e.g. as follows:
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
with tf.Session(config=config) as session:
kernel = tf.ones(shape=[5, 5, 3, 64])
images = tf.ones(shape=[64,24,24,3])
imgs = tf.transpose(images, [0, 3, 1, 2]) # NHWC -> NCHW
conv = tf.nn.conv2d(imgs, kernel, [1, 1, 1, 1], padding='SAME', data_format = 'NCHW')
conv = tf.transpose(conv, [0, 2, 3, 1]) # NCHW -> NHWC
print("conv=",conv.eval())

tensorflow size of convolution layers

I am attempting to recreate a cnn from a research paper, but I am still new to deep learning.
I am given a 3d patch of size 32x32x7. I first want to perform a convolution of size 3x3 with 32 features and a stride of 2. Then from that result, I need to perform a 3x3x4 convolution with 64 features and a stride of 1. I do not want to pool or have an activation function between the two convolutions. Why can't I just feed the results of my first convolution into the second one?
import tensorflow as tf
sess = tf.InteractiveSession()
def conv3d(tempX, tempW):
return tf.nn.conv3d(tempX, tempW, strides=[2, 2, 2, 2, 2],
padding='SAME')
def conv3d_s1(tempX, tempW):
return tf.nn.conv3d(tempX, tempW, strides=[1, 1, 1, 1, 1],
padding='SAME')
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
x = tf.placeholder(tf.float32, shape=[None, 7168])
y_ = tf.placeholder(tf.float32, shape=[None, 3])
W = tf.Variable(tf.zeros([7168,3]))
#first convolution
W_conv1 = weight_variable([3, 3, 1, 1, 32])
x_image = tf.reshape(x, [-1, 32, 32, 7, 1])
h_conv1 = conv3d(x_image, W_conv1)
#second convolution
W_conv2 = weight_variable([3, 3, 4, 1, 64])
h_conv2 = conv3d_s1(h_conv1, W_conv2)
Thank you!
After first conv3d you have tensor with shape [None, 16, 16, 4, 32], therefore you have to use kernel with shape [3, 3, 4, 32, 64] in the second conv3d_s1.

how to use TensorBoard callback AND TensorBoard server?

keras blog autoencoder code
I am trying to run the code for Convolutional Autoencode from
https://blog.keras.io/building-autoencoders-in-keras.html
from keras.layers import Input, Dense, Convolution2D, MaxPooling2D, UpSampling2D
from keras.models import Model
input_img = Input(shape=(1, 28, 28))
x = Convolution2D(16, 3, 3, activation='relu', border_mode='same')(input_img)
x = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(8, 3, 3, activation='relu', border_mode='same')(x)
x = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(8, 3, 3, activation='relu', border_mode='same')(x)
encoded = MaxPooling2D((2, 2), border_mode='same')(x)
# at this point the representation is (8, 4, 4) i.e. 128-dimensional
Convolution2D(8, 3, 3, activation='relu', border_mode='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(8, 3, 3, activation='relu', border_mode='same')(x)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(16, 3, 3, activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Convolution2D(1, 3, 3, activation='sigmoid', border_mode='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
after running it I run this code for training :
from keras.datasets import mnist
import numpy as np
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 1, 28, 28))
x_test = np.reshape(x_test, (len(x_test), 1, 28, 28))
now I want to plot the result I using callback ! I type this
tensorboard --logdir=/tmp/autoencoder
in my terminal and it successfully switch back to theano but when I run
from keras.callbacks import TensorBoard
autoencoder.fit(x_train, x_train,
nb_epoch=50,
batch_size=128,
shuffle=True,
validation_data=(x_test, x_test),
callbacks=[TensorBoard(log_dir='/tmp/autoencoder')])
it still imply that not switch back to tensorflow. Does anyone know how to fix it?
RuntimeError Traceback (most recent call last)
<ipython-input-4-fc8458b2c2ba> in <module>()
6 shuffle=True,
7 validation_data=(x_test, x_test),
----> 8 callbacks=[TensorBoard(log_dir='/tmp/autoencoder')])
/home/hoda/anaconda2/lib/python2.7/site-packages/keras/callbacks.pyc in __init__(self, log_dir, histogram_freq, write_graph, write_images)
487 super(TensorBoard, self).__init__()
488 if K._BACKEND != 'tensorflow':
--> 489 raise RuntimeError('TensorBoard callback only works '
490 'with the TensorFlow backend.')
491 self.log_dir = log_dir
RuntimeError: TensorBoard callback only works with the TensorFlow backend.
To switch to the Tensorflow backend you have to edit the keras.json file located in ~/.keras.
You should see a line "backend": "theano", change "theano" to "tensorflow" and if Tensorflow is properly installed it should work and the line "Using TensorFlow backend." should appear when you import Keras.