This paper will introduce how to use Keras to train a CNN model in the image data set established in the previous section and use this model
1. Introduction of Keras
Keras: Deep learning library based on Python
Keras is a high-level neural network API written in Python that can be run as a back end with TensorFlow, CNTK, or Theano. The focus of Keras development is to support rapid experimentation. * Being able to translate your ideas into experimental results with minimal delay is the key to good research.
- Keras prioritizes developer experience
- Keras is widely adopted by industry and academia
- Keras can easily turn a model into a product
- Keras supports multiple back-end engines and doesn’t lock you into an ecosystem
- Keras’s growth is supported by key companies in the deep learning ecosystem. The development of Keras is primarily supported by Google, and the Keras API is packaged in TensorFlow as tF.keras. In addition, Microsoft maintains the CNTK backend of Keras. Amazon AWS is developing MXNet support. Other companies offering support include NVIDIA, uber, apple (via CoreML), and others
2. Our existing data set is shown below
We will train a CNN model based on this data set to recognize these several classified images and achieve recognition accuracy of more than 97%
3. Our CNN and Keras project directory structure is as follows:
├── heavy metal ├── heavy metal ├── heavy metal ├── heavy metal ├── heavy metal ├── heavy metal ├── heavy metal ├── ─ heavy metal ├── ─ heavy metal ├── ─ heavy metal ├── ── ── ── ── ── ── ── ── ── ── ── ── ─ Bulbasaur_001. Jpeg │ ├ ─ ─ bulbasaur_002. Jpeg │ ├ ─ ─ charmander_001. Jpeg │ ├ ─ ─ charmander_002. JPG │ ├ ─ ─ mewtwo_001. JPG │ ├ ─ ─ mewtwo_002. JPG │ ├ ─ ─ pikachu_001. JPG │ ├ ─ ─ pikachu_002. JPG │ ├ ─ ─ squirtle_001. JPG │ └ ─ ─ squirtle_002. JPG ├ ─ ─ pokedex │ ├ ─ ─ pokedex │ ├ ─ ─ pokedex. Xcodeproj │ ├ ─ ─ pokedexTests │ └ ─ ─ pokedexUITests ├ ─ ─ pyimagesearch │ ├ ─ ─ __pycache__ │ ├ ─ ─ Set py │ └ ─ ─ smallervggnet. Py ├ ─ ─ the classify. Py ├ ─ ─ coremlconverter. Py ├ ─ ─ lb. Pickled ├ ─ ─ the plot. The PNG ├ ─ ─ ├─ Download.txt ├─ download.txt ├─ download.txt ├─ download.txtCopy the code
We have four categories:
- Dataset directory, which stores five classified images downloaded by us. The name of each subdirectory represents the classification of the images under the subdirectory, which will be used as the label of the images during model training.
- Examples directory, which holds the images we used to test the model
- The PyImagesearch directory, which houses our SmallerVGGNet model classes, will be completed in this article
- The Pokedex directory, which houses iOS App projects, will be completed in the next article
There are eight more files in the root directory
- Plot.png: Our training/verification accuracy and loss chart will be generated after run.
- Lb. Pickle: Our LabelBinarizer serialized file that contains the corresponding look-up mechanism for tag indexes and tag names
- Pokedex.model: This is the Keras Convolutional Neural Network model file that we have saved after serialization
- Train.py: We use this script to train the Keras CNN model, draw the training accuracy/loss diagram, serialize the Keras CNN model and tags, and save to disk
- Classify. Py: Our test script
- Pokedex. model: Keras CNN model generated by running the training script
- Coremlconverter. py: Model transformation script to run to convert the Keras CNN model to the Core ML model
- Pokedex. mlModel: Run the Core ML model generated by CoremlConverter. py. We will use this in a later article
4. Create a SmallerVGGNet model with the following structure
Click to see the complete model structure
Create the Smallervggnet. py script, save it in the PyImagesearch directory, and insert the following code
# import the necessary packages
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dropout
from keras.layers.core import Dense
from keras import backend as K
class SmallerVGGNet:
@staticmethod
def build(width, height, depth, classes):
# initialize the model along with the input shape to be
# "channels last" and the channels dimension itself
model = Sequential()
inputShape = (height, width, depth)
chanDim = - 1
# if we are using "channels first", update the input shape
# and channels dimension
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
# CONV => RELU => POOL
model.add(Conv2D(32, (3.3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3.3)))
model.add(Dropout(0.25))
# (CONV => RELU) * 2 => POOL
model.add(Conv2D(128, (3.3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3.3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2.2)))
model.add(Dropout(0.25))
# first (and only) set of FC => RELU layers
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# softmax classifier
model.add(Dense(classes))
model.add(Activation("softmax"))
# return the constructed network architecture
return model
Copy the code
Create a new __init__.py script and save it to the PyImagesearch directory so Python can recognize this directory as a module. We will use our SmallerVGGNet class as a module in our training script.
5. Implement our Keras CNN training script
Create a new train. Py script and insert the following code
# set the matplotlib backend so figures can be saved in the background
import matplotlib
matplotlib.use("Agg")
# import the necessary packages
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing.image import img_to_array
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from pyimagesearch.smallervggnet import SmallerVGGNet
import matplotlib.pyplot as plt
from imutils import paths
import numpy as np
import argparse
import random
import pickle
import cv2
import os
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d"."--dataset", required=True,
help="path to input dataset (i.e., directory of images)")
ap.add_argument("-m"."--model", required=True,
help="path to output model")
ap.add_argument("-l"."--labelbin", required=True,
help="path to output label binarizer")
ap.add_argument("-p"."--plot", type=str, default="plot.png",
help="path to output accuracy/loss plot")
args = vars(ap.parse_args())
# initialize the number of epochs to train for, initial learning rate,
# batch size, and image dimensions
EPOCHS = 100
INIT_LR = 1e-3
BS = 32
IMAGE_DIMS = (96.96.3)
# initialize the data and labels
data = []
labels = []
# grab the image paths and randomly shuffle them
print("[INFO] loading images...")
imagePaths = sorted(list(paths.list_images(args["dataset"])))
random.seed(42)
random.shuffle(imagePaths)
# loop over the input images
for imagePath in imagePaths:
# load the image, pre-process it, and store it in the data list
image = cv2.imread(imagePath)
image = cv2.resize(image, (IMAGE_DIMS[1], IMAGE_DIMS[0]))
image = img_to_array(image)
data.append(image)
# extract the class label from the image path and update the
# labels list
label = imagePath.split(os.path.sep)[2 -]
labels.append(label)
# scale the raw pixel intensities to the range [0, 1]
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)
print("[INFO] data matrix: {:.2f}MB".format(
data.nbytes / (1024 * 1000.0)))
# binarize the labels
lb = LabelBinarizer()
labels = lb.fit_transform(labels)
# partition the data into training and testing splits using 80% of
# the data for training and the remaining 20% for testing
(trainX, testX, trainY, testY) = train_test_split(data,
labels, test_size=0.2, random_state=42)
# construct the image generator for data augmentation
aug = ImageDataGenerator(rotation_range=25, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,
horizontal_flip=True, fill_mode="nearest")
# initialize the model
print("[INFO] compiling model...")
model = SmallerVGGNet.build(width=IMAGE_DIMS[1], height=IMAGE_DIMS[0],
depth=IMAGE_DIMS[2], classes=len(lb.classes_))
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="categorical_crossentropy", optimizer=opt,
metrics=["accuracy"])
# train the network
print("[INFO] training network...")
H = model.fit_generator(
aug.flow(trainX, trainY, batch_size=BS),
validation_data=(testX, testY),
steps_per_epoch=len(trainX) // BS,
epochs=EPOCHS, verbose=1)
# save the model to disk
print("[INFO] serializing network...")
model.save(args["model"])
# save the label binarizer to disk
print("[INFO] serializing label binarizer...")
f = open(args["labelbin"]."wb")
f.write(pickle.dumps(lb))
f.close()
# plot the training loss and accuracy
plt.style.use("ggplot")
plt.figure()
N = EPOCHS
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="upper left")
plt.savefig(args["plot"])
Copy the code
6. Train Keras CNN model
Run the following command on the terminal
$python train.py --dataset dataset --model pokedex.model --labelbin lb.pickle
Copy the code
Using TensorFlow backend. [INFO] loading images... libpng warning: iCCP: known incorrect sRGB profile libpng warning: iCCP: known incorrect sRGB profile libpng warning: iCCP: known incorrect sRGB profile .... [INFO] Data matrix: 165.67MB [INFO] Compiling Model... Epoch 1/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 26 s 1 s/step - loss: 2.0648 acc: 0.5099 - val_loss: 1.5347 - val_acc: 0.6818 Epoch 2/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 22 1 s/s step - loss: 1.2485 acc: 0.6371 - val_loss: 0.9233 - val_acc: 0.7662 Epoch 3/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 24 s 1 s/step - loss: 1.1295 - ACC: 0.6336 - val_loss: 1.3024 - val_ACC: 0.7013 Epoch 4/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 23 1 s/s step - loss: 1.0230 acc: 0.6530 - val_loss: 1.1989 - val_acc: 0.6688 Epoch 5/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 23 1 s/s step - loss: 0.9785 acc: 0.6683 - val_loss: 1.0938 - val_acc: 0.6818 Epoch 6/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 22 1 s/s step - loss: 0.9792-ACC: 0.6979 - val_loss: 1.1388 - val_ACC: 0.7143 Epoch 7/100 19/19 [= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =] - 22 1 s/s step - loss: 0.9480 acc: 0.6963 - val_loss: 0.9233 - val_acc: 0.7468 Epoch 8/100 4/19 [] = = = = = >... -ETA: 17s-loss: 0.6971 - ACC: 0.7500... [INFO] serializing network... [INFO] serializing label binarizer...Copy the code
On the MacBook Pro, the training takes about half an hour to complete, and three files — Pokedex. model, lb.pickle, and plot.png — are generated in the home directory. Plot.png is shown below
We can see that the training accuracy and verification accuracy are about 97%
7. Write test scripts
Now we have a trained model that we will use to classify images that are not included in the training data set and test data to test the accuracy of the model. Create a new Pyhon script file named classify. Py and insert the following code
# import the necessary packages
from keras.preprocessing.image import img_to_array
from keras.models import load_model
import numpy as np
import argparse
import imutils
import pickle
import cv2
import os
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-m"."--model", required=True,
help="path to trained model model")
ap.add_argument("-l"."--labelbin", required=True,
help="path to label binarizer")
ap.add_argument("-i"."--image", required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image
image = cv2.imread(args["image"])
output = image.copy()
# pre-process the image for classification
image = cv2.resize(image, (96.96))
image = image.astype("float") / 255.0
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
# load the trained convolutional neural network and the label
# binarizer
print("[INFO] loading network...")
model = load_model(args["model"])
lb = pickle.loads(open(args["labelbin"]."rb").read())
# classify the input image
print("[INFO] classifying image...")
proba = model.predict(image)[0]
idx = np.argmax(proba)
label = lb.classes_[idx]
# we'll mark our prediction as "correct" of the input image filename
# contains the predicted label text (obviously this makes the
# assumption that you have named your testing image files this way)
filename = args["image"][args["image"].rfind(os.path.sep) + 1:]
correct = "correct" iffilename.rfind(label) ! =- 1 else "incorrect"
# build the label and draw the label on the image
label = "{}: {:.2f}% ({})".format(label, proba[idx] * 100, correct)
output = imutils.resize(output, width=400)
cv2.putText(output, label, (10.25), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0.255.0), 2)
# show the output image
print("[INFO] {}".format(label))
cv2.imshow("Output", output)
cv2.waitKey(0)
Copy the code
8. Use our Keras CNN model to classify images
Test pikachu images
$ python classify.py --model pokedex.model --labelbin lb.pickle --image examples/pikachu_001.jpg Using TensorFlow backend. [INFO] loading network... [INFO] classifying image... [the INFO] pikachu: 100.00% (correct)Copy the code
Test charmander images
$ python classify.py --model pokedex.model --labelbin lb.pickle --image examples/pikachu_001.jpg Using TensorFlow backend. [INFO] loading network... [INFO] classifying image... [the INFO] charmander: 99.66% (correct)Copy the code
9. Summary
We used Keras to train a CNN model, using only about 1000 pictures, and the test accuracy reached about 97%! To better identify pokemon, you need to increase the number of image categories and the number of images under each category.
Scan the public account and reply “training code” to obtain the training code of Keras CNN model