DAY 96-100 DAYS MLCODE: Classification using HOG
In the previous blog, we discussed HOG, in this blog we’ll try to see HOG in action. Let’s develop a classifier using HOG.
Let’s download the faces from the Labeled Faces in the Wild dataset, which we can downloaded by Scikit-Learn:
from sklearn.datasets import fetch_lfw_people
face_images = fetch_lfw_people()
good_patches = face_images.images
good_patches.shape
Now download some none face images. We can take input images, and extract thumbnails from images at a variety of scales. We can use some of the images from Scikit-Image and Scikit-Learn’s PatchExtractor
from skimage import data, transform
non_face_img = ['camera', 'text', 'coins', 'moon',
'page', 'clock', 'immunohistochemistry',
'chelsea', 'coffee', 'hubble_deep_field']
negative_images = [color.rgb2gray(getattr(data, name)())
for name in non_face_img]
Let’s review the data which we prepared above.
fig, ax = plt.subplots(6, 10)
for i, axi in enumerate(ax.flat):
axi.imshow(negative_patches[500 * i], cmap='gray')
axi.axis('off')
Let’s combine them and compute HOG features. This step takes a little while, because the HOG features involve a nontrivial computation for each image.
from itertools import chain
X_train = np.array([feature.hog(im)
for im in chain(good_patches,
bad_patches)])
y_train = np.zeros(X_train.shape[0])
y_train[:good_patches.shape[0]] = 1
Train Model
For a high-dimensional binary classification task, a Linear support vector machine is a good choice. Let’s use Scikit-Learn’s,LinearSVC
because in comparison to itSVC
often has better scaling for a large number of samples.
First, though, let’s use a simple Gaussian naive Bayes to get a quick baseline
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import cross_val_score
cross_val_score(GaussianNB(), X_train, y_train)
Output:
array([0.94677677, 0.91423218, 0.94073971])
We can see that even our simple Gaussian is able to provide the 91% accuracy.
Let’s try the support vector machine, with a grid search over a few choices of the C parameter.
from sklearn.svm import LinearSVC
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(LinearSVC(), {'C': [1.0, 2.0, 4.0, 8.0]})
grid.fit(X_train, y_train)
grid.best_score_
Output : 0.9863530173709898
We can see the score reached at 98% with C = 2.
Let’s create and re-train the model with best estimator parameters
model = grid.best_estimator_
model.fit(X_train, y_train)
Output: LinearSVC(C=2.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss=’squared_hinge’, max_iter=1000, multi_class=’ovr’, penalty=’l2′, random_state=None, tol=0.0001, verbose=0)
Test the new Model
We are going to use the below image to see whether model can predict or not
Now read the image from internet and convert into gray scale.
!wget -O image_n1.jpg https://img.etimg.com/thumb/msid-57927105,width-300,imgsize-43611,resizemode-4/virat-kohli-hikes-endorsement-fee-to-rs-5-crore/day-highest-among-indian-celebrities.jpg
from skimage import io
image_1 = io.imread(‘image_n1.jpg’)
test_image = image_1 #skimage.data.astronaut()
test_image = skimage.color.rgb2gray(test_image)
test_image = skimage.transform.rescale(test_image, 0.5)
test_image = test_image[:160, 40:180]
plt.imshow(test_image, cmap=’gray’)
plt.axis(‘off’);
We can take these HOG-featured patches and use our model to evaluate whether each patch contains a face
labels = model.predict(patches_hog)
labels.sum()
Output 11
Let’s now draw the rectangle
fig, ax = plt.subplots()
ax.imshow(test_image, cmap=’gray’)
ax.axis(‘off’)
Ni, Nj = positive_patches[0].shape
indices = np.array(indices)
for i, j in indices[labels == 1]:
ax.add_patch(plt.Rectangle((j, i), Nj, Ni, edgecolor=’red’,
alpha=0.3, lw=2, facecolor=’none’))
Output:
In summary, we can see that we are able to detect the faces using very few lines of code. Not a bad idea and it is working as expected. You can find the entire code here.