热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

KNN图像分类及Python实现

NN,NearestNeighbor,最近邻KNN,K-NearestNeighbor,K最近邻KNN分类的思路:分类的过程其实是直接将测试集的每一个图片和训练集中的所有图片进行比

NN,Nearest Neighbor,最近邻

KNN,K-Nearest Neighbor,K最近邻

KNN分类的思路:



  • 分类的过程其实是直接将测试集的每一个图片和训练集中的所有图片进行比较,计算距离(这里使用L2距离)。

  • 距离越远,代表图片之间的相似度越低;距离越近,代表图片之间越相似。

  • 找到和测试图片距离最近的K个图,统计它们的分类,数量最多的分类就作为测试图片的分类。

 

Python实现:

1、加载CIFAR-10数据,参考前一篇 CIFAR-10和python读取



  • X_train,训练集 (50000,32,32,3)

  • y_train, 训练分类集 (50000,)

  • X_test, 测试集 (5000,32,32,3)

  • y_test,测试分类集 (5000,)

# Load the raw CIFAR-10 data.
cifar10_dir = 'cs231n/datasets/cifar-10-batches-py'
# Cleaning up variables to prevent loading data multiple times (which may cause memory issue)
try:
del X_train, y_train #del 只删除变量,不删变量引用的数据
del X_test, y_test
print('Clear previously loaded data.')
except:
pass
X_train, y_train, X_test, y_test
= load_CIFAR10(cifar10_dir)

为了提高执行效率,只从中取出5000和500个训练和测试数据,并变形为(5000,3072)和(500,3072)。

其中,3072=32*32*3,代表一个图片。

 

2、创建KNN分类器

from cs231n.classifiers import KNearestNeighbor
classifier
= KNearestNeighbor()
classifier.train(X_train, y_train)

 

 KNN分类并不对训练集做处理,只是单纯的保存下来。

class KNearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
self.X_train
= X
self.y_train
= y

 

3、计算距离

下面给出了三种计算距离的方式,最后可以看出向量计算的效率是最高的,



  • 双层循环

  • 单层循环

  • 无循环

双层循环:效率低

def compute_distances_two_loops(self, X):
num_test
= X.shape[0]
num_train
= self.X_train.shape[0]
dists
= np.zeros((num_test, num_train))
for i in range(num_test):
for j in range(num_train):
# numpy中的array可以直接逐元素相减
# square可以对整个array中的某一行中的每个元素做平方
dists[i, j] = np.sqrt( np.sum( np.square( self.X_train[ j, : ] - X[ i, : ]) ) )
   return dists

 

单层循环: 

和双层循环的区别在于,直接用整个数组减去另一个数组的一行,实现的就是每行相减的效果。

def compute_distances_one_loop(self, X):
num_test
= X.shape[0]
num_train
= self.X_train.shape[0]
dists
= np.zeros((num_test, num_train))
for i in range(num_test):

# self.X_train - X[ i, : ], 前者的每行减去后者
# np.sum中的axis =1, 表示每行中的所有列相加
dists[i, :] = np.sqrt( np.sum( np.square( self.X_train - X[ i, : ]), axis=1 ) )
return dists

 

无循环:

利用



  • L2距离平方和的展开

  • numpy的广播机制(broadcast)https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html

def compute_distances_no_loops(self, X):
num_test
= X.shape[0]
num_train
= self.X_train.shape[0]
dists
= np.zeros((num_test, num_train))
# 思路:L2距离展开,x-y的平方等于 x的平方 + y的平方 - 2xy, 2xy中的y需要从行转为列,再和x做点积。
# 最后生成的矩阵的每个元素,就是x-y的平方

# 2xy
d1 = np.dot(X, self.X_train.T)
#x的平方,keepdims=True,是保持矩阵的维度;500*1
# False,结果是一维的, 1*500
d2 = np.sum( np.square(X), axis=1, keepdims=True)

#y的平方
d3 = np.sum( np.square(self.X_train), axis=1, keepdims=True)
# 广播
# 500*1 和5000* 1是不能相加的
# 500*1 和5000*1的转置(1*5000)相加,会得到500 * 5000矩阵
dists = np.sqrt(d2 + d3.T - 2*d1)
return dists

 

可以计算三个方式获取的dists之间的差别,没有问题的话,difference应该是0

# np.linalg.norm, 计算范数
#
fro,F-范数,矩阵范数,矩阵中各项元素的绝对值平方的总和
difference = np.linalg.norm(dists - dists_one, ord='fro')

 

4、分类

def predict_labels(self, dists, k=1):
num_test
= dists.shape[0]
y_pred
= np.zeros(num_test)

for i in range(num_test):
closest_y
= []
# np.argsort,排序后的索引list,对应原array_like
labels = self.y_train[np.argsort(dists[i, :])].flatten()
# [0:k] 取0到k-1
closest_y = labels[0:k]

# Counter, 统计每个元素出现的次数
c = Counter(closest_y)
# most_common(n) 取数量最多的前n种
# most_common(1) = [(2, 3)], list, 2是种类,3是次数
# c.most_common(1)[0] = (2, 3), tuple
# c.most_common(1)[0][0] = 2
y_pred[i] = c.most_common(1)[0][0]

return y_pred

 

5、交叉验证



  • 交叉验证就是将训练集分为N等分,

  • 取其中一份作为验证集,其他作为训练集。

  • 每个等分分别做一次验证集,实现交叉验证。

  • 交叉验证可以减少过拟合。

num_folds = 5
k_choices
= [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]
X_train_folds
= []
y_train_folds
= []
# array_split,将数组等分
#
和split的区别是,在不能等分的情况下,也能做到尽量等分。
X_train_folds = np.array_split(X_train, num_folds)
y_train_folds
= np.array_split(y_train, num_folds)
k_to_accuracies
= {}
for k in k_choices:
k_to_accuracies[k]
= []
for i in range(num_folds):
y_pred
= classifier.predict_labels(X_train_folds[i], k=k)
# ==比较两个数组,可以得到相等元素的个数
num_correct = np.sum(y_pred == y_train_folds[i])
accuracy
= float(num_correct) / len(X_train_folds[i])
k_to_accuracies[k].append(accuracy)

 

准确率统计图

# plot the raw observations
for k in k_choices:
accuracies
= k_to_accuracies[k]
plt.scatter([k]
* len(accuracies), accuracies)
# plot the trend line with error bars that correspond to standard deviation
#
平均值
accuracies_mean = np.array([np.mean(v) for k,v in sorted(k_to_accuracies.items())])
# 标准差
accuracies_std = np.array([np.std(v) for k,v in sorted(k_to_accuracies.items())])
plt.errorbar(k_choices, accuracies_mean, yerr
=accuracies_std) # 误差图
plt.title('Cross-validation on k')
plt.xlabel(
'k')
plt.ylabel(
'Cross-validation accuracy')
plt.show()

 每个k对应5个交叉验证数据集,得到5个准确率,再取均值。最后的连线就是均值的连线。


 

python相关:

1、ndarray之间可以直接算术运算,相同维度的可以,不同维度的,通过广播也可以做到。

2、一些函数也可以直接对整个ndarray操作,实际上是对其中的每个元素操作。np.square

用到的一些方法:



  • np.sqrt, np.sum

  • np.argsort,排序后得到的对应原数组的索引数组。

  • flattern,转为1维数组

  • Counter,from collections import Counter, 统计list中每个元素出现的次数

  • most_common(n),取数量最多的前n种

  • np.array_split,等分ndarray

  • ==,可以取得数组中对应的元素个数

  • np.linalg.norm, 计算范数

  • np.random.choice, 随机选择

  • np.flatnonzero, 返回不等于0 的索引集合

  • np.mean, 计算平均值

  • np.std, 计算标准差

  • %load_ext autoreload,# 引用的其他模块更改了,可以自动重新加载

 

Reference:

http://cs231n.github.io/classification/



推荐阅读
  • 反向投影技术主要用于在大型输入图像中定位特定的小型模板图像。通过直方图对比,它能够识别出最匹配的区域或点,从而确定模板图像在输入图像中的位置。 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
  • 本文详细介绍了在 Windows 2000 系统中启用 TELNET 服务时需要注意的 NTLM 配置问题,帮助用户解决常见的身份验证失败错误。 ... [详细]
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
  • C语言标准及其GCC编译器版本
    编程语言的发展离不开持续的维护和更新。本文将探讨C语言的标准演变以及GCC编译器如何支持这些标准,确保其与时俱进,满足现代开发需求。 ... [详细]
  • 尽管深度学习带来了广泛的应用前景,其训练通常需要强大的计算资源。然而,并非所有开发者都能负担得起高性能服务器或专用硬件。本文探讨了如何在有限的硬件条件下(如ARM CPU)高效运行深度神经网络,特别是通过选择合适的工具和框架来加速模型推理。 ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • 在网站制作中随时可用的10个 HTML5 代码片段
    HTML很容易写,但创建网页时,您经常需要重复做同样的任务,如创建表单。在这篇文章中,我收集了10个超有用的HTML代码片段,有HTML5启动模板、空白图片、打电话和发短信、自动完 ... [详细]
  • 配置多VLAN环境下的透明SQUID代理
    本文介绍如何在包含多个VLAN的网络环境中配置SQUID作为透明网关。网络拓扑包括Cisco 3750交换机、PANABIT防火墙和SQUID服务器,所有设备均部署在ESXi虚拟化平台上。 ... [详细]
  • 深入解析Redis内存对象模型
    本文详细介绍了Redis内存对象模型的关键知识点,包括内存统计、内存分配、数据存储细节及优化策略。通过实际案例和专业分析,帮助读者全面理解Redis内存管理机制。 ... [详细]
  • 基于结构相似性的HOPC算法:多模态遥感影像配准方法及Matlab实现
    本文介绍了一种基于结构相似性的多模态遥感影像配准方法——HOPC算法,该算法通过相位一致性模型构建几何结构特征描述符,能够有效应对多模态影像间的非线性辐射差异。文章详细阐述了HOPC算法的原理、实验结果及其在多种遥感影像中的应用,并提供了相应的Matlab代码。 ... [详细]
  • Kubernetes 持久化存储与数据卷详解
    本文深入探讨 Kubernetes 中持久化存储的使用场景、PV/PVC/StorageClass 的基本操作及其实现原理,旨在帮助读者理解如何高效管理容器化应用的数据持久化需求。 ... [详细]
  • 深入理解路由器控制平面与转发平面及路由表
    本文详细介绍了路由器的控制平面和转发平面,并解释了路由表及其核心表项的重要性,帮助读者全面掌握路由器的工作原理。 ... [详细]
author-avatar
手机用户2602937435
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有