热门标签 | 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/



推荐阅读
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 本文介绍了如何在方法参数中指定一个对象的协议,以及如何调用符合该协议的方法。以一个具体的示例说明了如何在方法参数中指定一个UIView子类对象,并且该对象需要符合PixelUI协议,同时方法需要能够访问该对象的属性。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • 本文介绍了如何在Mac上使用Pillow库加载不同于默认字体和大小的字体,并提供了一个简单的示例代码。通过该示例,读者可以了解如何在Python中使用Pillow库来写入不同字体的文本。同时,本文也解决了在Mac上使用Pillow库加载字体时可能遇到的问题。读者可以根据本文提供的示例代码,轻松实现在Mac上使用Pillow库加载不同字体的功能。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • Python使用Pillow包生成验证码图片的方法
    本文介绍了使用Python中的Pillow包生成验证码图片的方法。通过随机生成数字和符号,并添加干扰象素,生成一幅验证码图片。需要配置好Python环境,并安装Pillow库。代码实现包括导入Pillow包和随机模块,定义随机生成字母、数字和字体颜色的函数。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 引号快捷键_首选项和设置——自定义快捷键
    3.3自定义快捷键(CustomizingHotkeys)ChemDraw快捷键由一个XML文件定义,我们可以根据自己的需要, ... [详细]
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社区 版权所有