Keras target shape is incorrect - neural-network

I am relatively new to keras so i played around with a simple seq2seq architecture.
model = Sequential()
model.add(Embedding(22, 10, input_length=32, mask_zero=True))
model.add(LSTM(4, return_sequences = True))
model.add(TimeDistributed(Dense(output_dim=3)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(x,y,nb_epoch =1, batch_size = 1, verbose = 2)
Exception: Error when checking model target: expected activation_6 to have shape (None, 32, 3) but got array with shape (2, 4, 3)
x has shape of (2,32) and y has shape of (2,4,3).
According to my understanding, it means that y has 2 examples with each sequence have a length of 4 and one hot-encoded into 3 dimension. However, when i ran model.fit it seems its not the shape that i am expecting. Why is this so?

Related

How to get accurate encoder output for kmeans clustering of similar images

I expected that if I trained similar images in an autoencoder the output from the encoder would be similar, hence if passed through a clustering algorithm they would form clusters around the same point. So what I did was to train the model with identical images (basically 60 duplicates of the same image). What I noticed, on the contrary, is that the values from the encoder appear different and when passed through kmeans clustering the points are scattered, which tells me nothing about how related my images are to each other.
kmeans clustering of 60 duplicate images
def autoencoderConv2D(input_shape=(228, 228, 1), filters=[32, 64, 128, 10]):
input_img = Input(shape=input_shape)
if input_shape[0] % 8 == 0:
pad3 = 'same'
else:
pad3 = 'valid'
x = Conv2D(filters[0], 5, strides=2, padding='same', activation='relu', name='conv1', input_shape=input_shape)(input_img)
x = Conv2D(filters[1], 5, strides=2, padding='same', activation='relu', name='conv2')(x)
x = Conv2D(filters[2], 3, strides=2, padding=pad3, activation='relu', name='conv3')(x)
x = Flatten()(x)
encoded = Dense(units=filters[3], name='embedding')(x)
x = Dense(units=filters[2]*int(input_shape[0]/8)*int(input_shape[0]/8), activation='relu')(encoded)
print (x.shape)
x = Reshape((int(input_shape[0]/8), int(input_shape[0]/8), filters[2]))(x)
print (x.shape)
x = Conv2DTranspose(filters[1], 3, strides=2, padding=pad3, activation='relu', name='deconv3')(x)
x = Conv2DTranspose(filters[0], 5, strides=2, padding='same', activation='relu', name='deconv2')(x)
print (x.shape)
decoded = Conv2DTranspose(input_shape[2], 5, strides=2, padding='same', name='deconv1')(x)
return Model(inputs=input_img, outputs=decoded, name='AE'), Model(inputs=input_img, outputs=encoded, name='encoder')
autoencoder, encoder = autoencoderConv2D()
pretrain_epochs = 50
batch_size = 2
autoencoder.compile(optimizer='adadelta', loss='mse')
autoencoder.fit(x, x, batch_size=batch_size, epochs=pretrain_epochs)
encoded = encoder.predict(x)
encoded.shape
(60, 10)
n_clusters = 1
kmeans = KMeans(n_clusters=n_clusters, n_init=20, n_jobs=4)
y_pred_kmeans = kmeans.fit_predict(encoded)
I also tried this with MNIST dataset with digit-2 being 5958 samples and digit-4 being 50 samples. Using k=2, the clustering gives the result as the figure below which shows no distinction between the two digits. Is there something I'm not doing right as I am looking to apply this technique for image filtering where dissimilar images are distinguished and filtered from the similar ones.

How to have parallel convolutional layers in keras?

I am a little new to neural networks and keras. I have some images with size 6*7 and the size of the filter is 15. I want to have several filters and train a convolutional layer separately on each and then combine them. I have looked at one example here:
model = Sequential()
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
border_mode='valid',
input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten(input_shape=input_shape))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('tanh'))
This model works with one filter. Can anybody give me some hints on how to modify the model to work with parallel convolutional layers.
Thanks
Here is an example of designing a network of parallel convolution and sub sampling layers in keras version 2. I hope this resolves your problem.
rows, cols = 100, 15
def create_convnet(img_path='network_image.png'):
input_shape = Input(shape=(rows, cols, 1))
tower_1 = Conv2D(20, (100, 5), padding='same', activation='relu')(input_shape)
tower_1 = MaxPooling2D((1, 11), strides=(1, 1), padding='same')(tower_1)
tower_2 = Conv2D(20, (100, 7), padding='same', activation='relu')(input_shape)
tower_2 = MaxPooling2D((1, 9), strides=(1, 1), padding='same')(tower_2)
tower_3 = Conv2D(20, (100, 10), padding='same', activation='relu')(input_shape)
tower_3 = MaxPooling2D((1, 6), strides=(1, 1), padding='same')(tower_3)
merged = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)
merged = Flatten()(merged)
out = Dense(200, activation='relu')(merged)
out = Dense(num_classes, activation='softmax')(out)
model = Model(input_shape, out)
plot_model(model, to_file=img_path)
return model
The image of this network will look like
My approach is to create other model that defines all parallel convolution and pulling operations and concat all parallel result tensors to single output tensor. Now you can add this parallel model graph in your sequential model just like layer. Here is my solution, hope it solves your problem.
# variable initialization
from keras import Input, Model, Sequential
from keras.layers import Conv2D, MaxPooling2D, Concatenate, Activation, Dropout, Flatten, Dense
nb_filters =100
kernel_size= {}
kernel_size[0]= [3,3]
kernel_size[1]= [4,4]
kernel_size[2]= [5,5]
input_shape=(32, 32, 3)
pool_size = (2,2)
nb_classes =2
no_parallel_filters = 3
# create seperate model graph for parallel processing with different filter sizes
# apply 'same' padding so that ll produce o/p tensor of same size for concatination
# cancat all paralle output
inp = Input(shape=input_shape)
convs = []
for k_no in range(len(kernel_size)):
conv = Conv2D(nb_filters, kernel_size[k_no][0], kernel_size[k_no][1],
border_mode='same',
activation='relu',
input_shape=input_shape)(inp)
pool = MaxPooling2D(pool_size=pool_size)(conv)
convs.append(pool)
if len(kernel_size) > 1:
out = Concatenate()(convs)
else:
out = convs[0]
conv_model = Model(input=inp, output=out)
# add created model grapg in sequential model
model = Sequential()
model.add(conv_model) # add model just like layer
model.add(Conv2D(nb_filters, kernel_size[1][0], kernel_size[1][0]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten(input_shape=input_shape))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('tanh'))
For more information refer similar question: Combining the outputs of multiple models into one model

Keras model classifying well but predicted probabilities are always 1.0 or 0.0

I am using Keras to build a multi-class (3 classes) image classifier.
I trained the following model with a dataset of approximately 2000 images (1500 training/ 500 validation).
batch_size = 128
nb_classes = 3
nb_epoch = 25
img_rows, img_cols = 128, 128
input_shape = (1, img_rows, img_cols)
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(32, 5, 5, border_mode='same', input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(64, 5, 5, border_mode='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(nb_classes, activation='softmax'))
lrate = 0.001
decay = lrate/nb_epoch
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
history = model.fit(X_train, Y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, Y_test),
shuffle=True,
callbacks=early_stopping)
These are the figures for the training/validation accuracy and loss.
I achieve a 95% training accuracy, 92% validation accuracy and 94% on another separate chunk of images (aside from the 2000 of the dataset) that I have.
Therefore, the model seems to classify reasonably well. However, my problem is that the predicted probabilities for an input image (obtained with the function predict_proba()) are always either 1.0 or 0.0.
Likewise, if I give as an input an image that doesn't belong to any of the 3 classes I would expect some low probabilities (perhaps higher in the most similar class) but I still get 1.0 in one of the classes and 0.0 in the others.
What could be causing that? It seems to me that there is no over fitting. Is there any issue with the model?
Could it be that the images of each class are quite similar between them so somehow the model is quickly too confident on its decision?

Keras Dense Layer Error: TypeError: 'int' object is not callable

I'm trying to visualize the output of each convolutional layer in keras, following this link: MNIST Visualisation. I have modified some layers to remove errors, but now I'm stuck with the Dense Layer Error.
np.set_printoptions(precision=5, suppress=True)
np.random.seed(1337) # for reproducibility
nb_classes = 10
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data("mnist.pkl")
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28)
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28)
X_train = X_train.astype("float32")
X_test = X_test.astype("float32")
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
i = 4600
pl.imshow(X_train[i, 0], interpolation='nearest', cmap=cm.binary)
print("label : ", Y_train[i,:])
model = Sequential()
model.add(Convolution2D(32, 3, 3, border_mode='same',input_shape = (1,28,28))) #changed border_mode from full -> valid
convout1 = Activation('relu')
model.add(convout1)
model.add(Convolution2D(32, 32, 3))
convout2 = Activation('relu')
model.add(convout2)
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(32*196, 128)) #ERROR HERE
Any comment or suggestion highly appreciated. Thank you.
If you check the documentation of a Dense layer then you'll notice that the first argument it accepts is the shape of output and second is init which describes the way how weights of the layer are initiated. In your case you provided the int as second positional argument and this caused error. You should change the code to (assuming that you want an output in a form of 128-dimensional vector):
model.add(Dense(128))

Keras convolution along single feature row

I have a multiclass classification problem. Say I have a feature matrix:
A B C D
1 -1 1 -6
2 0.5 0 11
7 3.7 1 1
4 -50 1 0
And labels:
LABEL
0
1
2
0
2
I want try to apply convolution kernels along each single feature row with Keras. Say nb_filter=2 and batch_size=3. So I expect input shape for convolution layer to be (3, 4) and output shape to be (3, 3) (as it is applied for AB, BC, CD).
Here what I tried with Keras (v1.2.1, Theano backend):
def CreateModel(input_dim, num_hidden_layers):
from keras.models import Sequential
from keras.layers import Dense, Dropout, Convolution1D, Flatten
model = Sequential()
model.add(Convolution1D(nb_filter=10, filter_length=1, input_shape=(1, input_dim), activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
return model
def OneHotTransformation(y):
from keras.utils import np_utils
return np_utils.to_categorical(y)
X_train = X_train.values.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test = X_test.values.reshape(X_test.shape[0], 1, X_test.shape[1]),
y_train = OneHotTransformation(y_train)
clf = KerasClassifier(build_fn=CreateModel, input_dim=X_train.shape[1], num_hidden_layers=1, nb_epoch=10, batch_size=500)
clf.fit(X_train, y_train)
Shapes:
print X_train.shape
print X_test.shape
print y_train.shape
Output:
(45561, 44)
(11391, 44)
(45561L,)
When I try to run this code I get and exception:
ValueError: Error when checking model target: expected dense_1 to have 3 dimensions, but got array with shape (45561L, 3L)
I tried to reshape y_train:
y_train = y_train.reshape(y_train.shape[0], 1, y_train.shape[1])
This gives me exception:
ValueError: Error when checking model target: expected dense_1 to have 3 dimensions, but got array with shape (136683L, 2L)
Is this approach with Convolution1D correct to achieve my goal?
If #1 is yes, how can I fix my code?
I've already read numerous github issues and some questions (1, 2) here, but it didn't really help.
Thanks.
UPDATE1:
According to Matias Valdenegro comment.
Here are shapes after reshaping 'X' and after onehot encoding for 'y':
print X_train.shape
print X_test.shape
print y_train.shape
Output:
(45561L, 1L, 44L)
(11391L, 1L, 44L)
(45561L, 3L)
UPDATE2: Thanks again to Matias Valdenegro. X reshaping is done after creating model for sure it was a copy paste issue. The code should look like:
def CreateModel(input_dim, num_hidden_layers):
from keras.models import Sequential
from keras.layers import Dense, Dropout, Convolution1D, Flatten
model = Sequential()
model.add(Convolution1D(nb_filter=10, filter_length=1, input_shape=(1, input_dim), activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
return model
def OneHotTransformation(y):
from keras.utils import np_utils
return np_utils.to_categorical(y)
clf = KerasClassifier(build_fn=CreateModel, input_dim=X_train.shape[1], num_hidden_layers=1, nb_epoch=10, batch_size=500)
X_train = X_train.values.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test = X_test.values.reshape(X_test.shape[0], 1, X_test.shape[1]),
y_train = OneHotTransformation(y_train)
clf.fit(X_train, y_train)
The input to a 1D convolution should have dimensions (num_samples, channels, width). So that means you need to reshape X_train and X_test, not y_train:
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])