Welcome back to our tutorial on building a deep face detection model using Python and TensorFlow. In this part, we'll cover steps 9 through 11, including defining losses, optimizers, training the model, and making predictions.
Check out Part 1
Check out Part 2
Check out Part 3
9. Define Losses and Optimizers
9.1 Define Optimizer and Learning Rate
batches_per_epoch = len(train)
lr_decay = (1. / 0.75 - 1) / batches_per_epoch
opt = tf.keras.optimizers.Adam(learning_rate=0.0001, decay=lr_decay)
9.2 Create Localization Loss and Classification Loss
def localization_loss(y_true, yhat):
delta_coord = tf.reduce_sum(tf.square(y_true[:, :2] - yhat[:, :2]))
h_true = y_true[:, 3] - y_true[:, 1]
w_true = y_true[:, 2] - y_true[:, 0]
h_pred = yhat[:, 3] - yhat[:, 1]
w_pred = yhat[:, 2] - yhat[:, 0]
delta_size = tf.reduce_sum(tf.square(w_true - w_pred) + tf.square(h_true - h_pred))
return delta_coord + delta_size
classloss = tf.keras.losses.BinaryCrossentropy()
regressloss = localization_loss
9.3 Test out Loss Metrics
localization_loss(y[1], coords)
classloss(y[0], classes)
regressloss(y[1], coords)
10. Train Neural Network
10.1 Create Custom Model Class
class FaceTracker(Model):
def __init__(self, eyetracker, **kwargs):
super().__init__(**kwargs)
self.model = eyetracker
def compile(self, opt, classloss, localizationloss, **kwargs):
super().compile(**kwargs)
self.closs = classloss
self.lloss = localizationloss
self.opt = opt
def train_step(self, batch, **kwargs):
X, y = batch
with tf.GradientTape() as tape:
classes, coords = self.model(X, training=True)
batch_classloss = self.closs(y[0], classes)
batch_localizationloss = self.lloss(tf.cast(y[1], tf.float32), coords)
total_loss = batch_localizationloss + 0.5 * batch_classloss
grad = tape.gradient(total_loss, self.model.trainable_variables)
opt.apply_gradients(zip(grad, self.model.trainable_variables))
return {"total_loss": total_loss, "class_loss": batch_classloss, "regress_loss": batch_localizationloss}
def test_step(self, batch, **kwargs):
X, y = batch
classes, coords = self.model(X, training=False)
batch_classloss = self.closs(y[0], classes)
batch_localizationloss = self.lloss(tf.cast(y[1], tf.float32), coords)
total_loss = batch_localizationloss + 0.5 * batch_classloss
return {"total_loss": total_loss, "class_loss": batch_classloss, "regress_loss": batch_localizationloss}
def call(self, X, **kwargs):
return self.model(X, **kwargs)
model = FaceTracker(facetracker)
model.compile(opt, classloss, regressloss)
10.2 Train
logdir = 'logs'
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir)
hist = model.fit(train, epochs=10, validation_data=val, callbacks=[tensorboard_callback])
10.3 Plot Performance
hist.history
fig, ax = plt.subplots(ncols=3, figsize=(20, 5))
ax[0].plot(hist.history['total_loss'], color='teal', label='loss')
ax[0].plot(hist.history['val_total_loss'], color='orange', label='val loss')
ax[0].title.set_text('Loss')
ax[0].legend()
ax[1].plot(hist.history['class_loss'], color='teal', label='class loss')
ax[1].plot(hist.history['val_class_loss'], color='orange', label='val class loss')
ax[1].title.set_text('Classification Loss')
ax[1].legend()
ax[2].plot(hist.history['regress_loss'], color='teal', label='regress loss')
ax[2].plot(hist.history['val_regress_loss'], color='orange', label='val regress loss')
ax[2].title.set_text('Regression Loss')
ax[2].legend()
plt.show()
11. Make Predictions
11.1 Make Predictions on Test Set
test_data = test.as_numpy_iterator()
test_sample = test_data.next()
yhat = facetracker.predict(test_sample[0])
fig, ax = plt.subplots(ncols=4, figsize=(20, 20))
for idx in range(4):
sample_image = test_sample[0][idx]
sample_coords = yhat[1][idx]
if yhat[0][idx] > 0.9:
cv2.rectangle(sample_image,
tuple(np.multiply(sample_coords[:2], [120, 120]).astype(int)),
tuple(np.multiply(sample_coords[2:], [120, 120]).astype(int)),
(255, 0, 0), 2)
ax[idx].imshow(sample_image)
11.2 Save the Model
from tensorflow.keras.models import load_model
facetracker.save('facetracker.h5')
facetracker = load_model('facetracker.h5')
11.3 Real-Time Detection
cap = cv2.VideoCapture(1)
while cap.isOpened():
_ , frame = cap.read()
frame = frame[50:500, 50:500, :]
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
resized = tf.image.resize(rgb, (120, 120))
yhat = facetracker.predict(np.expand_dims(resized/255, 0))
sample_coords = yhat[1][0]
if yhat[0] > 0.5:
# Controls the main rectangle
cv2.rectangle(frame,
tuple(np.multiply(sample_coords[:2], [450, 450]).astype(int)),
tuple(np.multiply(sample_coords[2:], [450, 450]).astype(int)),
(255, 0, 0), 2)
# Controls the label rectangle
cv2.rectangle(frame,
tuple(np.add(np.multiply(sample_coords[:2], [450, 450]).astype(int), [0, -30])),
tuple(np.add(np.multiply(sample_coords[:2], [450, 450]).astype(int), [80, 0])),
(255, 0, 0), -1)
# Controls the text rendered
cv2.putText(frame, 'face',
tuple(np.add(np.multiply(sample_coords[:2], [450, 450]).astype(int), [0, -5])),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
cv2.imshow('Face Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
This wraps up part 4 of our tutorial. In the next part, we'll discuss how to evaluate the model's performance and fine-tune it for better results.
Stay tuned for the upcoming installment!
Top comments (0)