概述
这篇博客以CIFAR-10数据集为基础,从对图像识别基础的预处理部分分析其背后理论,到讲述对KNN SVM Softmax的具体实现,并通过验证集进行参数调优,最后展开结果性分析,介绍基本的图像识别应用,材料部分来自于Stanford CS231n 的notes和assignments(project)。
CIFAR-10介绍
该数据集共有60000张彩色图像,每张图像是32*32*3的像素,相对较小且不需要分割提取的过程,可以直接进行处理,分为10个类,每类6000张图。这里面有50000张用于训练,构成了5个训练批,每一批10000张图;另外10000用于测试,单独构成一批。测试批的数据里,取自10类中的每一类,每一类随机取1000张。抽剩下的就随机排列组成了训练批。
如果是从CS231n提供的框架中下载的数据集,在Linux环境下只需要运行get_datasets.sh,为方便处理文件是以16进制存储的
这里对图像的提取不做赘述
上面就是从数据集中抽取的部分图片,可以看出就算一个类别内但彼此的差异性还是比较大的。抽取部分图片并展示的代码:
classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
num_classes = len(classes)
samples_per_class = 7
for y, cls in enumerate(classes):
idxs = np.flatnonzero(y_train == y)
idxs = np.random.choice(idxs, samples_per_class, replace=False)
for i, idx in enumerate(idxs):
plt_idx = i * num_classes + y + 1
plt.subplot(samples_per_class, num_classes, plt_idx)
plt.imshow(X_train[idx].astype('uint8'))
plt.axis('off')
if i == 0:
plt.title(cls);plt.show()
KNN进行图像识别
应该说,KNN是最为直观的识别算法,也易于实现,值得一提的是,我记得上次有同学在课程上尝试用《机器学习实战》书上的代码进行手写字识别,但是运行时间实在太长,其实虽然KNN是一种很耗费计算资源且如果数据维数变高后会变得十分恐怖的算法,但在面对大量数据时依旧可以通过矩阵化的计算极大地优化计算。
首先,对图像进行预处理,将我们32*32*3的每个图像化成一行,并且由于KNN并不是我们今天的主角且耗时较大,我们没有用全部的数据集进行训练,抽取了5000张数据集和500张测试集进行实验,目的是为了与SVM Softmax进行比较。
下面提供KNN代码,用类封装:
import numpy as np
class KNearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
self.X_train = X
self.y_train = y
def predict(self, X, k=1, num_loops=0):
if num_loops == 0:
dists = self.compute_distances_no_loops(X)
elif num_loops == 1:
dists = self.compute_distances_one_loop(X)
elif num_loops == 2:
dists = self.compute_distances_two_loops(X)
else:
raise ValueError('Invalid value %d for num_loops' % num_loops)
return self.predict_labels(dists, k=k)
def compute_distances_two_loops(self, X):
num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num