How to reshape a whole batch in Keras model? - python-3.x

I'm trying to reshape a whole batch in Keras so that it will transform from (?, 28, 28, 1) to (?/10, 10, 28, 28, 1). Is it possible to implement with Keras?
I have a dataset where labels are per group of images (let's call it 'bag') but not per images themselves. I'd like to load images from folder using Keras ImageDataGenerator and its flow_from_directory() method and then reshape images inside the model itself.
from keras.datasets import mnist
import keras.backend as K
from keras.layers import Lambda
(x_train, y_train), (x_test, y_test) = mnist.load_data()
def test_model(data):
from keras import Model
from keras.models import Input
input_layer = Input(shape=data.shape[1:])
layer = Lambda(lambda x: K.reshape(x,
(-1, 10, *data.shape[1:])),
output_shape=(-1, 10, *data.shape[1:]))(input_layer)
model = Model(inputs=[input_layer], outputs=[layer])
model.compile(optimizer='adadelta', loss='mean_squared_error')
return model.predict(data, batch_size=60)
if __name__ == '__main__':
test_model(x_train)
I expected the model to reshape each batch and return it somehow (to be honest, I don't know how Keras concatenates results of each batch when predicting).
Instead of results, I get error:
ValueError: could not broadcast input array from shape (6,10,28,28) into shape (60,10,28,28)

Related

First CNN and shapes error

I just started to build my first CNN. I'm practicing with the MNIST dataset, this is the code I just wrote:
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, Dropout, Flatten, Dense
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.optimizers import Adam
from sklearn.preprocessing import RobustScaler
import os
import numpy as np
import matplotlib.pyplot as plt
# CONSTANTS
EPOCHS = 300
TIME_STEPS = 30000
NUM_CLASSES = 10
# Loading data
print('Loading data:')
(train_X, train_y), (test_X, test_y) = mnist.load_data()
print('X_train: ' + str(train_X.shape))
print('Y_train: ' + str(train_y.shape))
print('X_test: ' + str(test_X.shape))
print('Y_test: ' + str(test_y.shape))
print('------------------------------')
# Splitting train/val
print('Splitting training/validation set:')
X_train = train_X[0:TIME_STEPS, :]
X_val = train_X[TIME_STEPS:TIME_STEPS*2, :]
print('X_train: ' + str(X_train.shape))
print('X_val: ' + str(X_val.shape))
# Normalizing data
print('------------------------------')
print('Normalizing data:')
X_train = X_train/255
X_val = X_val/255
print('X_train: ' + str(X_train.shape))
print('X_val: ' + str(X_val.shape))
# Building model
model = Sequential()
model.add(Conv1D(filters=32, kernel_size=5, input_shape=(28, 28)))
model.add(Conv1D(filters=16, kernel_size=4, activation="relu"))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(NUM_CLASSES, activation='softmax'))
model.compile(optimizer=Adam(), loss=categorical_crossentropy, metrics=['accuracy'])
model.summary()
model.fit(x=X_train, y=X_train, batch_size=10, epochs=EPOCHS, shuffle=False)
I'm going to explain what I did, any correction would be helpful so I can learn more:
The first thing I did is splitting the training set in two parts: a training part and a validation part, on which I would like to do the training before testing it on the test set.
Then, I normalized the data (is this a standard when we work with images?)
I then built my CNN with a simple structure: the first layer is the one which gets the inputs (with dimension 28x28) and I've chosen 32 filters that should be enough to perform well on this dataset. The kernel size is the one I did not understood since I thought that the kernel was the equivalent of the filter. I selected a low number to avoid problems. The second layer is similar to the previous one, but now it has an activation function (relu, but I'm not convinced, I was thinking to use a softmax to pass a set of probabilities to the full connected layer).
The last 3 layers are the full connected layer to get the output.
In the fit function I used a batch size of 10 and I think that this could be one of the reason I get the error:
ValueError: Shapes (10, 28, 28) and (10, 10) are incompatible
Even removing it I still getting the following error:
ValueError: Shapes (None, 28, 28) and (None, 10) are incompatible
Am I missing something important?
You are passing in the X_train variable twice, once as the x argument and once as the y argument. Instead of passing in X_train as the y argument in .fit() you should pass in an array of values you are trying to predict. Given that you are using MNIST is assume that you are trying to predict the written digit, so your y array should be of shape (n_samples, 10) with the digit being one-hot encoded.

image preprocessing is not working in vgg16

I am learning image classification using transfer learning(vgg16) and I am using inbuilt fashion mnist dataset of keras.
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
to preprocess the data for vgg16, I used the below commands by importing preprocess_input from keras.applications.vgg16
X_train = preprocess_input(x_train)
X_test = preprocess_input(x_test)
train_features = vgg16.predict(np.array(X_train), batch_size=256, verbose=1)
test_features = vgg16.predict(np.array(X_test), batch_size=256, verbose=1)
but I am getting the below error
ValueError: Error when checking input: expected input_1 to have 4 dimensions, but got array with shape (60000, 28, 28)
I am using keras2.2.4, pip 19.0.3
Fashion mnist dataset has grayscale images it means it has only single channel in depth and VGG16 is trained with RGB images with 3 channels in depth. According to your error you can not use VGG16 with single channel input. To use VGG16 for fashion mnist dataset you have to read images as three channel. You can further process your X_train and X_test as follows using np.stack:
import numpy as np
X_train = np.stack((X_train,)*3, axis=-1)
X_test = np.stack((X_test,)*3, axis=-1)
VGG accepts a minimum of 32 and max of 224, which can be seen here, to reshape this, we can do
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1) # converting it to (,28x28x1)
x_train = np.pad(x_train, ((0,0),(2,2),(2,2),(0,0)), 'constant',constant_values=(0, 0)) # converting it to min (,32x32x1)
x_train = np.stack((x_train,)*3, axis=-1) # (,32,32,1,3)
x_train = x_train[:,:,:,0,:] # (,32,32,1)
y_train = keras.utils.to_categorical(y_train, num_classes)
This can be used easily for .fit(), .evaluate() and .predict() in keras without the need to convert it into tensor data and write generators.

Wrapper for Keras Model in Spark

I have a Keras Nueral Network and I want to deploy this model using an wrapper in the spark environment. So I tried the following tutorial here
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Input, Dense, Conv1D, Conv2D, MaxPooling2D, Dropout,Flatten
from keras import backend as K
from keras.models import Model
import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# Expect to see a numpy n-dimentional array of (60000, 28, 28)
type(X_train), X_train.shape, type(X_train)
#This time however, we flatten each of our 28 X 28 images to a vector of 1, 784
X_train = X_train.reshape(-1, 784)
X_test = X_test.reshape(-1, 784)
# expect to see a numpy n-dimentional array of : (60000, 784) for Traning Data shape and (10000, 784) for Test Data shape
type(X_train), X_train.shape, X_test.shape
#We also use sklearn's MinMaxScaler for normalizing
from sklearn.preprocessing import MinMaxScaler
def scaleData(data):
# normalize features
scaler = MinMaxScaler(feature_range=(0, 1))
return scaler.fit_transform(data)
X_train = scaleData(X_train)
X_test = scaleData(X_test)
# We define the same Keras model as earlier
input_shape = (1,28,28) if K.image_data_format() == 'channels_first' else (28,28, 1)
keras_model = Sequential()
keras_model.add(Conv2D(32, kernel_size=(5, 5), activation='relu', input_shape=input_shape, padding='same'))
keras_model.add(MaxPooling2D(pool_size=(2, 2)))
keras_model.add(Conv2D(64, (5, 5), activation='relu', padding='same'))
keras_model.add(MaxPooling2D(pool_size=(2, 2)))
keras_model.add(Flatten())
keras_model.add(Dense(512, activation='relu'))
keras_model.add(Dropout(0.5))
keras_model.add(Dense(10, activation='softmax'))
keras_model.summary()
# Import the Keras to DML wrapper and define some basic variables
from systemml.mllearn import Keras2DML
epochs = 5
batch_size = 100
samples = 60000
max_iter = int(epochs*math.ceil(samples/batch_size))
# Now create a SystemML model by calling the Keras2DML method and feeding it your spark session, Keras model, its input shape, and the # predefined variables. We also ask to be displayed the traning results every 10 iterations.
sysml_model = Keras2DML(spark, keras_model, input_shape=(1,28,28), weights='weights_dir', batch_size=batch_size, max_iter=max_iter, test_interval=0, display=10)
# Initiate traning. More spark workers and better machine configuration means faster training!
sysml_model.fit(X_train, y_train)
# Test your model's performance on the secluded test set, and re-iterate if required
sysml_model.score(X_test, y_test)
At the line from systemml.mllearn import Keras2DML
The error I got is
Traceback (most recent call last): File
"d:/SparkJarDirectory/./NNSpark.py", line 58,
in
from systemml.mllearn import Keras2DML File "C:\Users\xyz\AppData\Local\Continuum\anaconda3\lib\site-packages\systemml\mllearn__init__.py",
line 45, in
from .estimators import * File "C:\Users\xyz\AppData\Local\Continuum\anaconda3\lib\site-packages\systemml\mllearn\estimators.py",
line 917
def init(self, sparkSession, keras_model, input_shape, transferUsingDF=False, load_keras_weights=True, weights=None,
labels=None, batch_size=64, max_iter=2000, test_iter=10,
test_interval=500, display=100, lr_policy="step", weight_decay=5e-4,
regularization_type="L2"):
^ SyntaxError: import * only allowed at module level 2019-03-12 20:25:48 INFO ShutdownHookManager:54 - Shutdown hook called
2019-03-12 20:25:48 INFO ShutdownHookManager:54 - Deleting directory
C:\Users\xyz\AppData\Local\Temp\spark-2e1736f8-1798-42da-a157-cdf0ade1bf36
From my understanding I get that that there is an issue at the library I am using where they use
from .estimators import *
__all__ = estimators.__all__
I am not sure why the wrapper is not working or what fix is required. Any help is appreciated.
I think the systemml release 1.2.0 misses some fixes for python 3.5 (https://github.com/apache/systemml/commit/9e7ee19a45102f7cbb37507da25b1ba0641868fd) so you will need to install systemml from source (for my setup, which is different than yours, it would git clone and then "cd src/main/python; sudo python3.4 setup.py install")

Conv2d input parameter mismatch

I am giving variable size images (all 278 images of different size 139 of each category) input to my cnn model. As a fact that cnn required fixed size images, so from here i got solution for this is to make input_shape=(None,Nonen,1) (for tensorflow backend and gray scale). but this solution doesnot work with flatten layer, so from their only i got solution of using GlobleMaxpooling or Globalaveragepooling. So from uses these facrts i am making a cnn model in keras to train my network with following code:
import os,cv2
import numpy as np
from sklearn.utils import shuffle
from keras import backend as K
from keras.utils import np_utils
from keras.models import Sequential
from keras.optimizers import SGD,RMSprop,adam
from keras.layers import Conv2D, MaxPooling2D,BatchNormalization,GlobalAveragePooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import regularizers
from keras import initializers
from skimage.io import imread_collection
from keras.preprocessing import image
from keras import Input
import keras
from keras import backend as K
#%%
PATH = os.getcwd()
# Define data path
data_path = PATH+'/current_exp'
data_dir_list = os.listdir(data_path)
img_rows=None
img_cols=None
num_channel=1
# Define the number of classes
num_classes = 2
img_data_list=[]
for dataset in data_dir_list:
img_list=os.listdir(data_path+'/'+ dataset)
print ('Loaded the images of dataset-'+'{}\n'.format(dataset))
for img in img_list:
input_img=cv2.imread(data_path + '/'+ dataset + '/'+ img,0)
img_data_list.append(input_img)
img_data = np.array(img_data_list)
if num_channel==1:
if K.image_dim_ordering()=='th':
img_data= np.expand_dims(img_data, axis=1)
print (img_data.shape)
else:
img_data= np.expand_dims(img_data, axis=4)
print (img_data.shape)
else:
if K.image_dim_ordering()=='th':
img_data=np.rollaxis(img_data,3,1)
print (img_data.shape)
#%%
num_classes = 2
#Total 278 sample, 139 for 0 category and 139 for category 1
num_of_samples = img_data.shape[0]
labels = np.ones((num_of_samples,),dtype='int64')
labels[0:138]=0
labels[138:]=1
x,y = shuffle(img_data,labels, random_state=2)
y = keras.utils.to_categorical(y, 2)
model = Sequential()
model.add(Conv2D(32,(2,2),input_shape=(None,None,1),activation='tanh',kernel_initializer=initializers.glorot_uniform(seed=100)))
model.add(Conv2D(32, (2,2),activation='tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (2,2),activation='tanh'))
model.add(Conv2D(64, (2,2),activation='tanh'))
model.add(MaxPooling2D())
model.add(Dropout(0.25))
#model.add(Flatten())
model.add(GlobalAveragePooling2D())
model.add(Dense(256,activation='tanh'))
model.add(Dropout(0.25))
model.add(Dense(2,activation='softmax'))
model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy'])
model.fit(x, y,batch_size=1,epochs=5,verbose=1)
but i am getting following error:
ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (278, 1)
how to solve it.
In the docs for Conv2D it says that the input tensor has to be in this format:
(samples, channels, rows, cols)
I believe you can't have a variable input size unless your network is fully convolutional.
Maybe what you want to do is to keep it to a fixed input size, and just resize the image to that size before feeding it into your network?
Your array with input data cannot have variable dimensions (this is a numpy limitation).
So the array, instead of being a regular array of numbers with 4 dimensions is being created as an array of arrays.
You should fit each image individually because of this limitation.
for epoch in range(epochs):
for img,class in zip(x,y):
#expand the first dimension of the image to have a batch size
img = img.reshape((1,) + img.shape)) #print and check there are 4 dimensions, like (1, width, height, 1).
class = class.reshape((1,) + class.shape)) #print and check there are two dimensions, like (1, classes).
model.train_on_batch(img,class,....)

Keras Convolution Neural Network

Right now I am trying to construct a basic convolutional neural network to do simple classification with mnist dataset using keras. Eventually I want to put my own images in I just want to build a simple network first to make sure I have the structure working. so I downloaded the mnist data as mnint.pkl.gz unpacked it and loaded it into tuples and eventually bumpy arrays. Here is my code:
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from PIL import Image as IM
import theano
from sklearn.cross_validation import train_test_split
import cPickle
import gzip
f=gzip.open('mnist.pkl.gz')
data1,data2,data3=cPickle.load(f)
f.close()
X=data1[0]
Y=data1[1]
x=X[0:15000,:]
y=Y[0:15000]
X_train,X_test,y_train,y_test=train_test_split(x,y,test_size
=0.33,random_state=99)
model=Sequential()
model.add(Convolution2D(10,5,5,border_mode='valid',
input_shape= (1,28,28)))
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(10))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
model.fit(X_train,y_train, batch_size=10, nb_epoch=10)
score=model.evaluate(X_test,y_test,batch_size=10)
print(score)
I get an error as such:
'Wrong number of dimensions: expected 4, got 2 with shape
(10, 784).')
I think this means I need to put it into a theano 4d tensor such that
is has (samples,channels,rows,columns) but I have no idea how to do that. Furthermore when I specifically want to solve the problem I am after I will we loading '.png' files in, I was then going to put them into numpy matrices to feed in but it looks like that is not going to work. Can anybody tell me how I can get Images into theano4d tensors to use in this code? Thanks
You are correct that the code is expecting a tensor4. The conventional structure is (batch, channel, width, height). In this case the images are monochrome so channel=1 It looks like you're using a batch size of 10 and the MNIST images are 28 pixels in width and 28 pixels in height.
You can simply reshape the data into the format required. If x is of shape (10, 784) then x.reshape(10, 1, 28, 28) will have the required format.
The code is expecting a 4-dimensional numpy array, not a Theano tensor (keras does all the Theano tensor manipulation under the hood).
Your inputs, X_train and X_test need to be reshaped as follows:
X_train = X_train.reshape(-1, 1, 28, 28)
X_test = X_test.reshape(-1, 1, 28, 28)

Resources