机器学习之k近邻算法(k-nearest neighbor, k-NN)

**前言: ** 学习笔记,记录下对于一些问题的记录和理解,复习和加深记忆用,挖坑补坑用。

参考:李航 《统计学习方法》

0. 基本内容

k近邻算法(kNN)是一种基本分类和回归方法。其不具有显式的学习过程,而是通过给定的训练集合数据,通过k个最近邻的训练实例通过多数表决的方式,进行预测。所以k-NN由三个基本要素决定,即距离度量、k值选择和 分类决策规则。通常对应选择为:欧氏距离,k值根据具体情况选择,多数表决方式。

1. 问题与理解

  • 几种距离
    特征空间中两“点” x i = ( x i ( 1 ) , x i ( 2 ) , . . . , x i ( n ) ) T , x j = ( x j ( 1 ) , x j ( 2 ) , . . . , x j ( n ) ) T x_i = (x_i^{(1)}, x_i^{(2)},..., x_i^{(n)})^T , x_j = (x_j^{(1)}, x_j^{(2)},..., x_j^{(n)})^T xi=(xi(1),xi(2),...,xi(n))T,xj=(xj(1),xj(2),...,xj(n))T,则两点间的 L p L_p Lp距离定义为:
    L p ( x i , x j ) = ( ∑ k = 1 n ∣ x i ( k ) − x j ( k ) ∣ p ) 1 p L_p(x_i, x_j) = (\sum_{k=1}^{n} |x_i^{(k)} - x_j^{(k)}|^p)^{\frac{1}{p}} Lp(xi,xj)=(k=1nxi(k)xj(k)p)p1

    • 当p = 1时,称为曼哈顿距离(Manhattan distance)
    • 当p = 2时,称为欧氏距离(Euclidean distance),另欧式空间,欧式范数。
    • 当p = ∞时,取值为各个坐标的最大值
  • kd树

    • kNN是个简单易理解的算法,可预想到的难点在于,当进行分类时,如何找到最近的k个近邻。一种方法是逐点扫描,计算距离,然后通过比较找到最近的k个点,但显而易见的是,如果训练数据很多,这种方法的计算量会是巨大的。事实上,有很多数据点是不需要考虑和进行计算的。第二种方法kd树便为解决这些问题而生的。

2. 具体实例与算法实现

from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as plt
import numpy as np

def loadData():
	
	# 读取mnist手写数字集数据
	mnist_dir = '/home/zhangwei/data/database/MNIST'
	mnist = input_data.read_data_sets(mnist_dir, one_hot = True)
	# 图片数据
	train_images = mnist.train.images	# (55000, 784)
	val_images = mnist.validation.images	# (5000, 784)
	test_images = mnist.test.images		# (10000, 784)
	# 标签信息
	train_labels = mnist.train.labels	# (55000, 10)
	val_labels = mnist.validation.labels
	test_labels = mnist.test.labels
	
	return train_images,train_labels,test_images,test_labels

def kNN(train_images,train_labels,test_images,test_labels, k = 10, sample_size = 55000):
	# k:近邻系数

	# 截取部分数据进行kNN测试
	train_img = train_images[0:sample_size, :]
	train_label = train_labels[0:sample_size, :]
	test_img = test_images
	test_label = test_labels
	
	# 使用逐行扫描的方法,使用欧氏距离度量和多数表决策略
	rNum = 0 # 预测正确数
	wNum = 0 # 预测错误数
	batch = 100 # 测试100个test_img,查看准确率
	for i in range(batch):
		Diff = np.tile(test_img[i], (train_img.shape[0], 1)) - train_img
		sqDiff = Diff ** 2
		sqDistance = sqDiff.sum(axis = 1)
		d = sqDistance ** 0.5
		index = d.argsort()	# 返回排序后的索引

		classList = np.zeros((1, 10))
		for j in index[0:k]:
			classList = train_label[j] + classList

		predict = classList.argsort()[0,-1]
		fact = test_label[i].argsort()[-1]
		if(predict == fact):
			rNum = rNum + 1
		else:
			wNum = wNum + 1
	
	accuracy = rNum / float(wNum + rNum) # 准确率
	return accuracy

if __name__ == '__main__':

	train_images,train_labels,test_images,test_labels = loadData()
	# k取不同值时,计算精度acc
	k = np.arange(1, 21)
	acc = []
	for n,i in enumerate(k):
		acc.append(kNN(train_images,train_labels,test_images,test_labels, i,10000))
		print(n+1, '/', len(k))
	plt.plot(k, acc, 'o')
	plt.show()

结果展示:
选取样本数固定时,不同k(横坐标)值时,acc(纵坐标)的变化图
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值