1.knn算法介绍:(copy自百度)
邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
2.knn算法的python实现:
(#运行环境python3.6.2)
import numpy as np
from PIL import Image
import operator
import os
#k为选择最相邻样本的个数
#testdata为需要进行测试的一条新数据:包含n条特征的numpy一维数组
#traindata为包含多条已知结果的训练数据:由m条与测试数据相同(特征长度为n)的numpy二维数组
#labels为训练数据的结果集,一个list对象
def knn(k,testdata,traindata,labels):
#先把测试数据转为一维数组,然后把所有训练数据减去该一维数组
rst = traindata-testdata
#求出差值的平方
reqrst = rst**2
# print(reqrst.size)
#把每一行数据相加再开方
distance = (np.sum(reqrst,axis=1))**0.5
#根据距离来排序索引值,由小到大
sorteddistance = distance.argsort()
count = {}
for i in range(k):
type = labels[sorteddistance[i]]
count[type] = count.get(type,0)+1
sort_count =sorted(count.items(),key=operator.itemgetter(1),reverse=True)
return sort_count[0][0] #返回统计结果中value值最大的那个key值,即识别的结果
3.knn算法的使用案例:
利用knn进行手写体数字的识别,数据包为在csdn下载的手写数字数据包.数据存放在nums文件夹,将其中一个图片剪切出来放入到test文件夹,重命名为test.bmp
,作为待识别的数据.
def study():#学习的方法
#遍历获取当前目录下的nums文件夹中的所有数字图片,并转为一维数组,同时按照顺序保存其类型labels
traindata = np.empty(2) #用于保存训练数据的具体值的数组
# print(f'size:{traindata.size}')
labels =[] #用于保存训练数组类型的数组
for i in range(10):
num_pic_names = os.listdir('./nums/'+str(i)+'/')
for name in num_pic_names:
img = Image.open('./nums/'+str(i)+'/'+name)#打开图片
array = np.array(img) #转为数组
simple_arr = np.where(array == 0, 0, 1) #把灰度值转为0,1数组
item = simple_arr.flatten()
labels.append(i)
# print(traindata.shape)
if traindata.size == 2:
traindata = item
else:
traindata = np.row_stack((traindata,item))
# print(traindata.shape)
# print(len(labels))
return traindata,labels #返回训练数据的具体值和类型
def test():
# ====================识别一个测试数据的代码===========
traindata,labels = study()
test_img = Image.open('./test/test.bmp')
test_array = np.array(test_img) # 转为数组
simple_arr = np.where(test_array == 0, 0, 1) # 把灰度值转为0,1数组
testdata = simple_arr.flatten()
rst = knn(3,testdata,traindata,labels)
print('===========================================')
print(f'本次的识别结果为:{rst}')
test() #调用test()方法来执行代码
4.knn算法识别率的测试:
knn算法在手写体数字测试中的识别率比较高,通过切分训练数据和测试数据来进行测试(约1000个数据,切分出5%作为测试数据),准确率可以达到95%以上.
import time
from sklearn.model_selection import train_test_split
def test2():
#====================以下为测试识别的准确率的代码
print('开始学习...')
begin = time.time()
traindata, labels = study()
study_end =time.time()
print(f'学习结束,总共耗时{study_end-begin}秒,接下来进行准确率的验证')
x_train,x_test,y_train,y_test = train_test_split(traindata, labels,test_size=0.05,random_state=20)
count=0
right=0
print(f'本次测试数据的个数为:{len(y_test)}')
for test,rst in zip(x_test,y_test):
knn_rst= knn(3,test,x_train,y_train)
count+=1
# print(f'原数据结果为:{rst},识别结果为:{knn_rst},',end='') #如果识别错误,则打印出错误信息
if knn_rst == rst:
print('识别成功')
right+=1
else:
print()
print(f'准确率为:{right/count}')
end = time.time()
print(f'本次总共耗时{end-begin}秒')
test2() #调用test2()方法来执行代码