随笔 - 70  文章 - 0  评论 - 0  阅读 - 1948 

KNN——最近邻算法(即选择最近的占比最高的类别作为预测类别)

KNN算法的计算逻辑

1)给定测试对象,计算它与训练集中每个对象的距离。

2)圈定距离最近的k个训练对象,作为测试对象的邻居。

3)根据这k个近邻对象所属的类别,找到占比最高的那个类别作为测试对象的预测类别。

在 KNN算法中,有两个方面的因素会影响KNN算法的准确度:一个是计算测试对象与训练集中各个对象的距离,另一个因素就是k的选择。

距离度量:曼哈顿距离和欧式距离。

(1)曼哈顿距离 假设先只考虑两个点,第一个点的坐标为(x1,y1),第二个点的坐标为(x2,y2),那么,它们之间的曼哈顿距离就是|x1-x2|+|y1-y2|

(2)欧式距离 以空间为基准的两点之间的最短距离。第一个点的坐标为(x1,y1),第二个点的坐标为(x2,y2),那么它们之间的欧式距离就是√(x1-x2)2  +(y1-y2)2

复制代码
import numpy as np
import matplotlib.pyplot as pl
##给出训练数据以及对应的类别 
def createDataSet(): 
      group = np.array([[1.0,2.0],[1.2,0.11,[0.1,1.4),[0.3,3.5],[1.1,1.0],[0.5,1.5]]) 
      labels = np,array(['A','A''B','B','A','B']) 
return group,labels 
if_ name___=='__main___': 
group,labels = createDataSet() plt,scatter(group!labels=='A',0],group[labels=='A',1),color='',marker='*')
#对于类别为A的数据集我们使用红色六角形表示 
plt,scatter(group[labels=='B',0],group[labels=='B',1],color = 'g', markere'+') scatter方法是用来绘制散点图
# 对于类别为B的数据集我们使用绿色十字形表示 plt,show ( )
复制代码
复制代码
def kN_classify(k,dis,x_train,x_train,Y_test):
assert dis =='E'or dis =≡ 'M', 'dis must E or  kM,E代表欧式距离,M代表曼哈顿距离。
num_test = Y_test.shape[0]    #测试样本的数量    
labellist=[]
"'
使用欧式距离公式作为距离度量
"'
if (dis =='E'):k
for i in range(num_test):
#实现欧式距离公式
distances = np.sqrt(np.sum(((x_train - np.tile(Y_test[i],(X_train.
shape[0],1))) ** 2),axis=1))
nearest_k = np.argsort(distances))#距离由小到大进行排序,并返回index 值
topK = nearest_k[:k]    #选取前k个距离    
classCount ={}
for i in topk:    # 统计每个类别的个数    
classCount [x_train[i]] =classCount.get (x_train[i],0) +1 
sortedclassCount = sorted(classCount .items() ,key=operator.
itemgetter(1),reverse=True)
labellist.append(sortedclassCount[0][0]) 
return np.array(labellist)
#使用曼哈顿公式作为距离度量
复制代码

 

测试下KNN算法的效果

if ___name__=='__main__':
group, labels = createDataset()
y_test_pred = kNN_classify(1,'E',group, labels, np.array([[1.0,2.1],[0.4,2.0]]))
print(y_test_pred)    #打印输出['A' 'B']需要注意的是,在输入测试集的时候,需要将其转换为Numpy的矩阵,否则系统会提示传人的参数是list类型,没有shape的方法。


 图像分类
图像分类问题就是将已有的固定的分类标签集合中最合适的标签分配给输入的图像。图像分类的任务就是预测一个给定的图像包含了哪个分类标签(或者给出属于一同标签的可能性)。图像是三维数组,数组元素是取值范围从0~255的整数。数组尺寸是宽度x高度x3,其中3代表的是红、绿、蓝3个颜色通道。

图像预处理

图像预处理不仅可以使得原始图像符合某种既定规则以便于进行后续的处理,帮助去除图像中的噪声。

数据预处理还可以减少后续的运算量以及加速收敛。常用的图像预处理操作包括归一化、灰度变换、变换以及各种形态学变换

归一化

归一化可用于保证所有维度上的数据都在一个变化幅度上 ,

可以使用两种方法来实现归一化:一种是最值归 一化,比如将最大值归一化成1,最小值归一化成-1;最大值归一化成1,最小值归一化成0
另一种是均值方差归一 化,一般是将均值归一化成0,方差归一化成1。

复制代码
import torch
from torch.utile.data import DataLoader import torchvision.datasets as dsets
import torchvision.transforms as transforma batch_aize - 100*MNIST dataset
train_dataset = dsetm,MNIST(root ='/ml/pymnist',    #选择数据的根目录    
train = True,    #选择训练集    
transform = None,    #不考虑使用任何数据预处理    
download =True)    #从网络上下载图片    
test_dataset = dsets,MNIST(root ='/ml/pymnist',    选择数据的根目录    
train =False,    #选择测试集    
transform = None,    #不考虑使用任何数据预处理    
download =True)    #从网络上下载图片    
#加载数据
train_loader = torch.utils.data.DataLoader (dataset - train_dataset,
batch_size = batch_size, shuffle - True)#将数据打乱
test_loader = torch.utils.data.DataLoader (dataset = test_dataset,
batch_size = batch_mize, shuffle = True)

print("train_data:", train_dataset.train_data.size())
print("train_labels:", train_dataset.train_labels.size()) print("test_data:", test_dataset.test_data,size())
print("test_labels:", test_dataset.test_labels.size())

 

train_data: torch.size([60000,28,281)
train_labels: torch.Size([600001) #训练集标签的长度
test_data; torch,Size([10000,28,281)
test_labels: torch,Size((10000)) #测试集标签的长度

复制代码

train_dataset 与test_dataset可以返回训练集数据、训练集标签、测试集数据以及测试集标签,训练集数据以及测试集数据都是n*m维的矩阵,这里的n是样本数(行数),m是特征数(列数)。

训练数据集包含60000个样本,测试数据集包含10000个样本。在 MNIST 数据集中,每张图片均由28X28个像素点构成,每个像素点使用一个灰度值表示。在这里,我们将28x28的像素展开为一个一维的行向量,这些行向量就是图片数组里的行(每行 784个值,或者说每行就代表了一张图片)。训练集标签以及测试标签包含了相应的目标变量,也就是手写数字的类标签(整数0~9)。

 一般不会直接使用train_dataset与test_dataset,在训练一个算法的时候(比如,神经网络),最好是对一个batch的数据进行操作,同时还需要对数据进行shuffle 和并行加速

import matplotlib.pyplot as plt    #取第一个图片的数据    
digit = train_loader.dataset,train_data(0) 
pit.imshow(digit,cmap=plt.cm.binary)#颜色映射
#输出对应的标签,结果为5
plt.show()
print (train_loader.dataset.train_labels[0])

KNN实现MNIST数字分类

验证KNN在MNIST上的分类效果

复制代码
x-train = train_loader.dataset.train_data.numpy()#需要转为numpy矩阵
x-train = x_train.reshape(x-train.shape[0],28*28)#需要reshape之后才能放进knn分类器

y_train = train_loader.dataset.train_1abels.numpy ()

x_test = test_loader.dataset .test_data[:1000].numpy ()

x_test =X_test.reshape(X_test.shape(0],28*28)#返回一个一维的数组,
y_test = test_loader.dataset.test_labela[:1000].numpy ()

num_test = y_test,shape(0)
y_test_pred = KNN_classify(5,'M', x_train,y_train, x_test)

num_correct = np.sum(y_test_pred == y_test)

accuracy = float(num_correct) / num_test
print('Got %d / %d correct => accuracy: %f'%(num_correct, num_test, accuracy))

 
复制代码
复制代码
x_train = train_loader.dataset.train_data.numpy ()
mean_image = getXmean(X_train)
x_train = centralized(X_train,mean_image)#归一化处理
y_train = train_loader.dataset.train_labels.numpy () 
x_test = test_loader.dataset.test_data[:1000].numpy () 
x_test = centralized(X_test,mean_image)
y_test = test_loader.dataset.test_labels[:1000].numpy () 
num_test = y_test.shape[0]#从 y_test #数组中获取其第一个维度的大小,计算测试集中样本(或实例)的总数
y_test_pred =KNN_classify(5,'M', x_train, y_train,x_teat) 
num_correct = np.sum(y_test_pred =-y_test) 
accuracy = float(num_correct) / num_test
print ('Got %d / %d correct => accuracy:%f '% (num_correct, num_test,accuracy) 
复制代码

基于面向对象的思想来实现KNN算法的封装(在Python中,封装主要通过私有属性和私有方法来实现。私有成员是以双下划线(__)开头的成员。这些成员在类的外部不能直接访问,但可以通过类的公共方法来间接访问和修改。)

复制代码
def predict(self, x_train,y_train):
return model
def predict(self,k, dis, x_test):#其中,k的选择范围为1-20,dis代表选择的是欧拉还是曼哈顿公式,x_test表示训练数据,函数返回的是预测的类别    
return test_labelss
def fit(self,x_train,y_train):
 self,xtr=x_train
 self.ytr =y_train
def predict (self,k, dis,x_test):
assert dis == 'E' or dis == 'M',dis must E or M' 
num_test = X_test.shape[0]#测试样本的数量
labellist = ()
*使用欧式距离公式作为距高度量

if (dis == 'E'): for i in range(num_test):
 distances = np.aqrt(np.sum(((nelf.xtr - np.tile(X_test[i],(self. 
Xtr.shape[0],1)) ** 2),axis=1))  
nearest_k
= np.argsort(distances)
topk = nearest_k[:k]
classCount=()

for i in topk:
classCount (self.ytr(il]
=classCount.get (self.ytr[i].0)+1
itemgetter(
i), reverse=True)
sortedclassCount = sorted(classCount .items(), key=operator.
labellist.append(sortedClassCount[0][
0])

return np.array(labellist)
复制代码

 

posted on   风起-  阅读(40)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示