首先,回顾k-Nearest Neighbor(k-NN)分类器,可以说是最简单易懂的机器学习算法。 实际上,k-NN非常简单,根本不会执行任何“学习”,以及介绍k-NN分类器的工作原理。 然后,我们将k-NN应用于Kaggle Dogs vs. Cats数据集,这是Microsoft的Asirra数据集的一个子集。顾名思义,Dogs vs. Cats数据集的目标是对给定图像是否包含狗或猫进行分类。
Kaggle Dogs vs. Cats dataset
Dogs vs. Cats数据集实际上是几年前Kaggle挑战的一部分。 挑战本身很简单:给出一个图像,预测它是否包含一只狗或一只猫:
建立的工程文件的结构
k-NN classifier for image classificationShell
$ tree --filelimit 10
.
├── kaggle_dogs_vs_cats
│ └── train [25000 entries exceeds filelimit, not opening dir]
└── knn_classifier.py
2 directories, 1 file
k-Nearest Neighbor分类器是迄今为止最简单的机器学习/图像分类算法。 事实上,它很简单,实际上并没有“学习”任何东西。
在内部,该算法仅依赖于特征向量之间的距离,就像构建图像搜索引擎一样 - 只是这次,我们有与每个图像相关联的标签,因此我们可以预测并返回图像的实际类别。
简而言之,k-NN算法通过找到k个最接近的例子中最常见的类来对未知数据点进行分类。 k个最近的例子中的每个数据点都投了一票,而得票最多的类别获胜!
或者,用简单的英语:“告诉我你的邻居是谁,我会告诉你你是谁”。
在这里我们可以看到有两类图像,并且每个相应类别中的每个数据点在n维空间中相对靠近地分组。 我们的狗往往有深色的外套,不是很蓬松,而我们的猫有非常轻的外套非常蓬松。
这意味着红色圆圈中两个数据点之间的距离远小于红色圆圈中的数据点与蓝色圆圈中的数据点之间的距离。
为了应用k-最近邻分类,我们需要定义距离度量或相似度函数。 常见的选择包括欧几里德距离(差值平方和)、曼哈顿距离(绝对值距离)。可以根据数据类型使用其他距离度量/相似度函数(卡方距离通常用于分布即直方图)。 在今天的博客文章中,为了简单起见,我们将使用欧几里德距离来比较图像的相似性。
建立knn.py
# import the necessary packages
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
import os
def image_to_feature_vector(image, size=(32, 32)):
# resize the image to a fixed size, then flatten the image into
# a list of raw pixel intensities
return cv2.resize(image, size).flatten()
def extract_color_histogram(image, bins=(8, 8, 8)):
# extract a 3D color histogram from the HSV color space using
# the supplied number of `bins` per channel
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0, 1, 2], None, bins,
[0, 180, 0, 256, 0, 256])
# handle normalizing the histogram if we are using OpenCV 2.4.X
if imutils.is_cv2():
hist = cv2.normalize(hist)
# otherwise, perform "in place" normalization in OpenCV 3 (I
# personally hate the way this is done
else:
cv2.normalize(hist, hist)
# return the flattened histogram as the feature vector
return hist.flatten()
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
hel