TypeError: Singleton array cannot be considered a valid collection - tensorflow

Tried using k-cross validation from this link but with my own dataset and I got this error:
TypeError: Singleton array array(<BatchDataset element_spec=(TensorSpec(shape=(None, 180, 180, 3), dtype=tf.float32, name=None), TensorSpec(shape=(None,), dtype=tf.int32, name=None))>,
dtype=object) cannot be considered a valid collection.
Here is my code:
import numpy as np
import PIL
import tensorflow as tf
import os
from sklearn.model_selection import KFold
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
import pathlib
num_folds = 10
acc_per_fold = []
loss_per_fold = []
tf.get_logger().setLevel('ERROR')
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
dataset_path = "data"
fullPath = os.path.abspath("./" + dataset_path)
#data_dir = tf.keras.utils.get_file('photos', origin='file://'+dataset_path, extract=True)
data_dir = pathlib.Path(fullPath)
image_count = len(list(data_dir.glob('*/*.jpg')))+len(list(data_dir.glob('*/*.png')))
print(image_count)
#man = list(data_dir.glob('man/*'))
#im = PIL.Image.open(str(man[28]))
#im.show()
batch_size = 32
img_height = 180
img_width = 180
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
labels='inferred',
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
labels='inferred',
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
class_names = train_ds.class_names
print(class_names)
normalization_layer = layers.Rescaling(1./255)
# Define the K-fold Cross Validator
kfold = KFold(n_splits=num_folds, shuffle=True, random_state=42)
fold_no = 1
for train, test in kfold.split(train_ds, val_ds):
# Define the model architecture
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dense(no_classes, activation='softmax'))
# Compile the model
model.compile(loss=loss_function,
optimizer=optimizer,
metrics=['accuracy'])
# Generate a print
print('------------------------------------------------------------------------')
print(f'Training for fold {fold_no} ...')
# Fit data to model
history = model.fit(inputs[train], targets[train],
batch_size=batch_size,
epochs=no_epochs,
verbose=verbosity)
# Generate generalization metrics
scores = model.evaluate(inputs[test], targets[test], verbose=0)
print(f'Score for fold {fold_no}: {model.metrics_names[0]} of {scores[0]}; {model.metrics_names[1]} of {scores[1]*100}%')
acc_per_fold.append(scores[1] * 100)
loss_per_fold.append(scores[0])
# Increase fold number
fold_no = fold_no + 1
# == Provide average scores ==
print('------------------------------------------------------------------------')
print('Score per fold')
for i in range(0, len(acc_per_fold)):
print('------------------------------------------------------------------------')
print(f'> Fold {i+1} - Loss: {loss_per_fold[i]} - Accuracy: {acc_per_fold[i]}%')
print('------------------------------------------------------------------------')
print('Average scores for all folds:')
print(f'> Accuracy: {np.mean(acc_per_fold)} (+- {np.std(acc_per_fold)})')
print(f'> Loss: {np.mean(loss_per_fold)}')
print('------------------------------------------------------------------------')

Related

How to get the filenames of all categories (TP, TN, FP, FN) of a Confusion Matrix in Keras/TensorFlow?

I am working with image data where I am trying to find the list of the files are in TP, TN (true positives, true negatives) and so on. The purpose is to check (visually) whether the files are being identified properly by the model. currntly I am using a sequential image classification model in google colab. Following is my code.
## Model
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(8, activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory('./train', target_size=(128, 128), batch_size=batch_size, color_mode = 'grayscale', class_mode='binary')
validation_generator = test_datagen.flow_from_directory('./validation', target_size=(128, 128), batch_size=batch_size, color_mode = 'grayscale', class_mode='binary')
test_generator = test_datagen.flow_from_directory('./test', target_size=(128, 128), batch_size=1,
color_mode = 'grayscale', class_mode='binary', shuffle=False)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
h = model.fit(train_generator, epochs = 50, validation_data=validation_generator)
from sklearn.metrics import confusion_matrix
y_true = test_generator.classes
true_classes = test_generator.classes
class_labels = list(test_generator.class_indices.keys())
confusion_matrix(y_true, yy_pred)
Output of confusion Matrix-
array([[22, 10],
[9, 50]])
Where I am trying to get image file names those are in True Positives (22 images), True Negatives (50 images) and so on. I am not sure whether I can get a list directly or do I have to re-generate the predicted images!
The function below will processes the test_generator and produce a classification report and a confusion matrix as well as a list of filenams the were misclassified.
You can process the classification report to get the metrics you desire
def predictor(test_gen):
y_pred= []
error_list=[]
error_pred_list = []
y_true=test_gen.labels
classes=list(test_gen.class_indices.keys())
class_count=len(classes)
errors=0
preds=model.predict(test_gen, verbose=1)
tests=len(preds)
for i, p in enumerate(preds):
pred_index=np.argmax(p)
true_index=test_gen.labels[i] # labels are integer values
if pred_index != true_index: # a misclassification has occurred
errors=errors + 1
file=test_gen.filenames[i]
error_list.append(file)
error_class=classes[pred_index]
error_pred_list.append(error_class)
y_pred.append(pred_index)
acc=( 1-errors/tests) * 100
msg=f'there were {errors} errors in {tests} tests for an accuracy of {acc:6.2f}'
print_in_color(msg, (0,255,255), (100,100,100)) # cyan foreground
ypred=np.array(y_pred)
ytrue=np.array(y_true)
f1score=f1_score(ytrue, ypred, average='weighted')* 100
if class_count <=30:
cm = confusion_matrix(ytrue, ypred )
# plot the confusion matrix
plt.figure(figsize=(12, 8))
sns.heatmap(cm, annot=True, vmin=0, fmt='g', cmap='Blues', cbar=False)
plt.xticks(np.arange(class_count)+.5, classes, rotation=90)
plt.yticks(np.arange(class_count)+.5, classes, rotation=0)
plt.xlabel("Predicted")
plt.ylabel("Actual")
plt.title("Confusion Matrix")
plt.show()
clr = classification_report(y_true, y_pred, target_names=classes, digits= 4) # create classification report
print("Classification Report:\n----------------------\n", clr)
return errors, tests, error_list, error_pred_list, f1score
errors, tests, error_list, error_pred_list, f1score =predictor(test_gen)

how to increase the accuracy of an image classifier?

I made an image classifier using Tensorflow, Keras with the implementation of a CNN architecture, the model works pretty fine (at least for the images that I have tested on it ) and it has reached an accuracy of 78.87%, the only thing that I m facing is that I want to make the accuracy no less than 85%.
Please Note:
Dataset: 2 folders: [Train Folder===> 80 folders each has 110 images, Validation folder===> 80 folders each has 22 images] size of the images [240-260]x[40-60]
Below is the code I used to create, save and test my model:
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
# dimensions of our images.
img_width, img_height = 251, 54
#img_width, img_height = 150, 33
train_data_dir = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/test/numbers/data/train'
validation_data_dir = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/test/numbers/data/valid'
nb_train_samples = 8800 #10435
nb_validation_samples = 1763 #2051
epochs = 30 #20 # how much time you want to train your model on the data
batch_size = 32 #16
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(80)) #1
model.add(Activation('softmax')) #sigmoid
model.compile(loss='sparse_categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy'])#categorical_crossentropy #binary_crossentropy
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.1,
zoom_range=0.05,
horizontal_flip=False)
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
model.save('testX_2.h5') #first_try
last epoche resulat
Epoch 30/30
275/275 [==============================] - 38s 137ms/step - loss: 0.9406 - acc: 0.7562 - val_loss: 0.1268 - val_acc: 0.9688
how I tested my model:
from keras.models import load_model
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
import os
result = {"0":"0", "1":"0.25", "2":"0.5", "3":"0.75", "4":"1", "5":"1.25", "6":"1.5", "7":"1.75",
"47":"2", "48":"2.25", "49":"2.5", "50":"2.75", "52":"3","53":"3.25", "54":"3.5", "55":"3.75", "56":"4", "57":"4.25", "58":"4.5",
"59":"4.75","60":"5", "61":"5.25", "62":"5.5", "63":"5.75", "64":"6", "65":"6.25","66":"6.5", "67":"6.75", "68":"7", "69":"7.25",
"70":"7.5", "71":"7.75", "72":"8", "73":"8.25", "74":"8.5", "75":"8.75", "76":"9", "77":"9.25", "78":"9.5", "79":"9.75", "8":"10",
"9":"10.25", "10":"10.5", "11":"10.75", "12":"11", "13":"11.25", "14":"11.5", "15":"11.75", "16":"12","17":"12.25", "18":"12.5",
"19":"12.75", "20":"13", "21":"13.25", "22":"13.5", "23":"13.75","24":"14", "25":"14.25", "26":"14.5", "27":"14.75", "28":"15",
"29":"15.25", "30":"15.5", "31":"15.75", "32":"16", "33":"16.25", "34":"16.5", "35":"16.75", "36":"17", "37":"17.25", "38":"17.5",
"39":"17.75", "40":"18", "41":"18.25", "42":"18.5", "43":"18.75", "44":"19", "45":"19.25", "46":"19.5", "51":"20"}
def load_image(img_path, show=False):
img = image.load_img(img_path, target_size=(251, 54))
img_tensor = image.img_to_array(img) # (height, width, channels)
img_tensor = np.expand_dims(img_tensor, axis=0) # (1, height, width, channels), add a dimension because the model expects this shape: (batch_size, height, width, channels)
img_tensor /= 255. # imshow expects values in the range [0, 1]
if show:
plt.imshow(img_tensor[0])
plt.axis('off')
plt.show()
return img_tensor
if __name__ == "__main__":
# load model
model = load_model('C:/Users/ADEM/Desktop/msi_youssef/PFE/other_shit/testX_2.h5')
# image path
img_path = 'C:/Users/ADEM/Desktop/msi_youssef/PFE/dataset/5.75/a.png'
# load a single image
new_image = load_image(img_path)
# check prediction
#pred = model.predict(new_image)
pred = model.predict_classes(new_image)
#print(pred[0])
print(result[str(pred[0])])
Taking all the information about dataset and considering your CNN model already has around 80% accuracy you can start with training the model for a higher number of epochs (typically > 100 epochs). That should give the required boost to your model.
If that alone does not work you can implement:
Transformation/augmentation:
perform transformation/augmentation on the images before feeding into the model.
Tweak Model:
make changes to model layers and do hyperparameter tuning.
You can follow this article to learn more.

Why my Keras Image classification prediction always return one value...?

I am using CNN to classify multiple people. People's number is 114 and each has about 120 image dataset.
I use keras and model that is used in dog vs cat classification.
It works well in Dogs and Cat classification.
But this is only return same value in different person image.
It says accuracy 99.12 but not work.
this is my train code
# coding: utf-8
# In[1]:
import os
import cv2
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.cross_validation import train_test_split
from keras import backend as K
from keras import layers, models, optimizers
from keras.preprocessing.image import ImageDataGenerator, img_to_array, array_to_img
from keras.applications.resnet50 import preprocess_input
from keras.utils import np_utils
from numpy import array
# In[2]:
TRAIN_DIR = './Dataset'
train_folder_list = array(os.listdir(TRAIN_DIR))
# In[13]:
X = []
Y = []
# In[14]:
label_encoder = LabelEncoder()
integer_encoded = label_encoder.fit_transform(train_folder_list)
onehot_encoder = OneHotEncoder(sparse=False)
integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
for idx, index in enumerate(range(len(train_folder_list))):
path = os.path.join(TRAIN_DIR, train_folder_list[index])
path = path + '/'
img_list = os.listdir(path)
for img in img_list:
img_path = os.path.join(path, img)
img = cv2.imread(img_path)
if img is not None:
img = cv2.resize(img, (100, 100))
img = img_to_array(img)
X.append(img)
Y.append(idx)
X = np.array(X, dtype="float") / 255.0
# In[15]:
(X_train, X_test, Y_train, Y_test) = train_test_split(X,Y,test_size=0.2, random_state = 42)
Y_train = np_utils.to_categorical(Y_train, len(train_folder_list))
Y_test = np_utils.to_categorical(Y_test, len(train_folder_list))
print(X_train[0])
# In[17]:
nb_train_samples = len(X_train)
nb_valivation_samples = len(X_test)
batch_size = 32
# In[18]:
print(K.image_data_format())
# In[19]:
model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), input_shape=(100, 100, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(32, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(64, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(500))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(114))
model.add(layers.Activation('softmax'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.summary()
# In[20]:
train_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# In[21]:
train_generator = train_datagen.flow(X_train, Y_train, batch_size=batch_size)
test_generator = test_datagen.flow(X_test , Y_test, batch_size=batch_size)
print(train_generator)
# In[ ]:
history = model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=3,
validation_data=test_generator,
validation_steps=nb_valivation_samples // batch_size
)
model.save_weights('model_weights.h5')
model.save('model_keras.h5')
and my test code
from keras.models import load_model
import cv2
from keras.applications.resnet50 import preprocess_input
import numpy as np
model = load_model('model_keras.h5')
img = cv2.imread('input_test.jpg')
if img is not None:
img = cv2.resize(img, (100,100), interpolation=cv2.INTER_CUBIC)
img = np.reshape(img,[1,100,100,3])
img = preprocess_input(img)
classes = model.predict_classes(img)
print(classes)
Replace binary_crossentropy with categorical_crossentropy like this:
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])

ValueError: Error when checking input: expected conv2d_1_input to have shape (28, 28, 1) but got array with shape (28, 28, 3)

Using Tensorflow, I build a binary classification model:
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
import tensorflow
import glob
from PIL import Image
import numpy as np
img_width, img_height = 28, 28#all MNIST images are of size (28*28)
train_data_dir = '/Binary Classifier/data/train'#train directory generated by train_cla
validation_data_dir = '/Binary Classifier/data/val'#validation directory generated by val_cla
train_samples = 40000
validation_samples = 10000
epochs = 2
batch_size = 512
if K.image_data_format() == 'channels_first':
input_shape = (1, img_width, img_height)
else:
input_shape = (img_width, img_height, 1)
#build a sequential model to train data
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
train_datagen = ImageDataGenerator(#train data generator
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
val_datagen = ImageDataGenerator(rescale=1. / 255)#validation data generator
train_generator = train_datagen.flow_from_directory(#train generator
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = val_datagen.flow_from_directory(#validation generator
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
model.fit_generator(#fit the generator to train and validate the model
train_generator,
steps_per_epoch=train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=validation_samples // batch_size)
But I got an error saying "ValueError: Error when checking input: expected conv2d_1_input to have shape (28, 28, 1) but got array with shape (28, 28, 3)", and I don't understand where this error comes from. I specifically defines the input shape to be either (28,28,1) or (28,28,1), and all my input data are MNIST digits which should also be size of (28,28,1). How does the generator receive a (28,28,3) array? Any help is appreciated!
The default in ImageDataGenerator's flow_from_directory is to load color images in RGB format, which implies three channels. You want to load images as grayscale (one channel), and you can do this by setting the color_mode parameter in flow_from_directory to grayscale.
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary', color_mode = 'grayscale')
validation_generator = val_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary', color_mode = 'grayscale')

Tensorflow JS : Convert Saved Model from tensorflow

I am trying to convert a tensorflow saved model to tensorflowjs format using this converter.
But this gives me the error IOError: SavedModel file does not exist at:
Though my directory has the Saved Model. It has:
.data-****-of-****,
.meta and .index files.
Am I missing anything?
I had an issue when I tried tensorflowjs_converter, I'd like to use tfjs.converters.save_keras_model method in your python implementation as follow.
Add just one line and that's it then you can import this model from your tensorflowjs project, like I did.
Example code minist_cnn.py
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
import tensorflowjs as tfjs
batch_size = 128
num_classes = 10
epochs = 12
# input image dimensions
img_rows, img_cols = 28, 28
# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
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 = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
# add this line
tfjs.converters.save_keras_model(model, './SavedModel')
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])