Hello and welcome to part 6 of the deep learning basics with Python, TensorFlow and Keras. In this part, we're going to cover how to actually use your model. We will us our cats vs dogs neural network that we've been perfecting. To begin, here's the code that creates the model that we'll be using, assuming you already have downloaded the data from the previous parts.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.
from tensorflow.keras.callbacks import TensorBoard
import pickle
import time
pickle_in = open("X.pickle","rb")
X = pickle.load(pickle_in)
pickle_in = open("y.pickle","rb")
y = pickle.load(pickle_in)
X = X/255.0
dense_layers = [0]
layer_sizes = [64]
conv_layers = [3]
for dense_layer in dense_layers:
for layer_size in layer_sizes:
for conv_layer in conv_layers:
NAME = "{}-conv-{}-nodes-{}-dense-{}".format(conv_layer, layer_size, dense_layer, int(time.time()))
print(NAME)
model = Sequential()
model.add(Conv2D(layer_size, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
for l in range(conv_layer-1):
model.add(Conv2D(layer_size, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
for _ in range(dense_layer):
model.add(Dense(layer_size))
model.add(Activation('relu'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'],
)
model.fit(X, y,
batch_size=32,
epochs=10,
validation_split=0.3,
callbacks=[tensorboard])
model.save('64x3-CNN.model')
The above model gives me:
loss: 0.2705 - acc: 0.8860 - val_loss: 0.4556 - val_acc: 0.8012
I'll take it. So now we've got a model saved to 64x3-CNN.model
in our working directory. How might we use this model on new, real, data?
We've already covered how to load in a model, so really the only piece we need now is how to take data from the real world and feed it in. Doing this is the same process as we've needed to do to train the model, so we'll be recycling quite a bit of code.
First, we some images. I am going to use a couple of images that I know to be unique. One is of my own dog, and the other is of a cat where I used to live.
You can use my images, or you can go to google images and grab some there too. That said, there's a high chance the images from google images are contained in the dataset we used, so, if you have some unique ones, use those.
What were the things we did to our training images? We grayscaled, resized, and reshaped. Let's create a function that does all of that.
import cv2
import tensorflow as tf
CATEGORIES = ["Dog", "Cat"] # will use this to convert prediction num to string value
def prepare(filepath):
IMG_SIZE = 70 # 50 in txt-based
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE) # read in the image, convert to grayscale
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) # resize image to match model's expected sizing
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1) # return the image with shaping that TF wants.
Next, we want to load our model:
model = tf.keras.models.load_model("64x3-CNN.model")
Now, we can make a prediction:
prediction = model.predict([prepare('dog.jpg')]) # REMEMBER YOU'RE PASSING A LIST OF THINGS YOU WISH TO PREDICT
Let's look at what we've got now:
prediction
Here, we've got a 2D array. To grab the actual prediction:
prediction[0][0]
Now, if we convert this to int, we can use it as an index to get the category string:
print(CATEGORIES[int(prediction[0][0])])
We can also test our cat example:
prediction = model.predict([prepare('cat.jpg')])
print(prediction) # will be a list in a list.
print(CATEGORIES[int(prediction[0][0])])
Full code
import cv2
import tensorflow as tf
CATEGORIES = ["Dog", "Cat"]
def prepare(filepath):
IMG_SIZE = 70 # 50 in txt-based
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1)
model = tf.keras.models.load_model("64x3-CNN.model")
prediction = model.predict([prepare('doggo.jpg')])
print(prediction) # will be a list in a list.
print(CATEGORIES[int(prediction[0][0])])
There you have how to use your model to predict new samples.
Should you use to use this in production, you can easily run off a CPU rather than a GPU, unless you need to classify thousands of things a minute.
One thing to note is that you don't want to keep loading your model. For my production models, I tend to use a database where the sample data is input to a database.
Then I have the model script constantly running in a loop, checking that database for new entries. If there is one, generate the result, put the result into the database, and then we can use that result however we need to. You just don't want to be constantly re-initializing tensorflow or the model itself.
Alrighty, in the next tutorial, we're going to discuss recurrent nets!