K近邻法(KNN)相关知识总结以及如何用python实现

1、基本概念

K近邻法(K-nearest neighbors,KNN)既可以分类,也可以回归。

  KNN做回归和分类的区别在于最后预测时的决策方式。

KNN做分类时,一般用多数表决法

KNN做回归时,一般用平均法。

   基本概念如下:对待测实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中

2. KNN算法三要素

  KNN算法主要考虑:k值的选取,距离度量方式,分类决策规则。

1) k值的选取。在应用中,k值一般选择一个比较小的值,一般选用交叉验证来取最优的k值

当K值较小,训练误差减小,泛化误差增大,模型复杂容易过拟合;

当K值较大,泛化误差减小,训练误差增大,模型简单使预测发生错误(一个极端,K等于样本数m,则完全没有分类,此时无论测试集是什么,结果都属于训练集中最多的类)

  2)距离度量。Lp距离:误差绝对值p次方求和再求p次根。欧式距离:p=2的Lp距离。曼哈顿距离:p=1的Lp距离。p为无穷大时,Lp距离为各个维度上距离的最大值
  3)分类决策规则。也就是如何根据k个最近邻决定待测对象的分类。k最近邻的分类决策规则一般选用多数表决

3. KNN基本执行步骤

  1)计算待测对象和训练集中每个样本点的欧式距离
  2)对上面的所有距离值排序
  3)选出k个最小距离的样本作为“选民”
  4)根据“选民”预测待测样本的分类或值

4. KNN特点

  1)原理简单
  2)保存模型需要保存所有样本集
  3)训练过程很快,预测速度很慢

· 优点:
  精度高、对异常值不敏感
  可用于数值型数据和离散型数据(既可以用来估值,又可以用来分类)

· 缺点:
  时间复杂性高;空间复杂性高;需要大量的内存
  样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
  一般数值很大的时候不用这个,计算量太大。但是单个样本又不能太少,否则容易发生误分。
  最大的缺点是无法给出数据的内在含义。

需要思考的问题:
样本属性如何选择?如何计算两个对象间距离?当样本各属性的类型和尺度不同时如何处理?各属性不同重要程度如何处理?模型的好坏如何评估?

5.代码实现

K近邻算法的一般流程:准备数据- 分析数据- 测试算法- 使用算法

5.1 sklearn包实现

关于sklearn的详细介绍,请见之前的博客 //www.jb51.net/article/204984.htm

5.1.1 sklearn实现k-近邻算法简介 官方文档

5.1.2 KNeighborsClassifier函数8个参数

  •   - n_neighbors:k值,选取最近的k个点,默认为5;k值不同分类结果也会不同
  •   - weights:默认是uniform,参数可以是uniform(均等权重)、distance(按距离分配权重),也可以是用户自己定义的函数。uniform是均等的权重,就说所有的邻近点的权重都是相等的。
  •   - algorithm:快速k近邻搜索算法,默认参数为auto。除此之外,用户也可以自己指定搜索算法ball_tree、kd_tree、brute方法进行搜索。
  •   - leaf_size:默认是30,这个是构造的kd树和ball树的大小。这个值的设置会影响树构建的速度和搜索速度,同样也影响着存储树所需的内存大小。需要根据问题的性质选择最优的大小。
  •   - metric:用于距离度量,默认度量是minkowski,也就是p=2的欧氏距离(欧几里德度量)。
  •   - p:距离度量公式。欧氏距离和曼哈顿距离。这个参数默认为2,也可以设置为1。
  •   - metric_params:距离公式的其他关键参数,这个可以不管,使用默认的None即可。
  •   - n_jobs:并行处理设置。默认为1,临近点搜索并行工作数。如果为-1,那么CPU的所有cores都用于并行工作。

注意:样本数据 - 特征数据 feature 必须是数字类型,要进行运算的!

5.1.3 实例

(1)对电影进行分类

import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
# 读取数据
df = pd.read_excel(../../myfile.excel)

#1、实例模型对象
knn = KNeighborsClassifier(n_neighbors=3)

#2、拿到样本数据和分类结果数据: 截取目标列,样本数据要二维
feature = df[['Action Lean','Love Lean']]
target = feature['target']

#3、训练模型
knn.fit(feature,target)

#4、测试结果
movie = np.array([13,21])
res = knn.predict(movie) #5、评分:分数越高悦准确knn.score(feature,target)

(2)预测年收入是否大于50K美元

# 读取adult.txt文件,最后一列是年收入,并使用KNN算法训练模型,然后使用模型预测一个人的年收入是否大于50
# 1. 读取数据
data = pd.read_csv('../data/adults.txt')
data.head()

# 2. 获取年龄、教育程度、职位、每周工作时间作为机器学习数据 获取薪水作为对应结果
feature = data[['age','education_num','occupation'
     ,'hours_per_week']]
target = data['salary']

# 3. knn中特征数据是需要参与运算的,所以要保证特征数据必须为数值型的数据
  # 数据转换,将String类型数据转换为int
  #### map方法,进行数据转换

dic = {}# unique()方法保证数据唯一
occ_arr = feature['occupation'].unique()
# 生成 字符对应数字的 关系表
for i in range(occ_arr.size):
 dic[occ_arr[i]] = i 

# 数值替换字符串
feature['occupation'] = feature['occupation'].map(dic) 

# 4. 切片:训练数据和预测数据
# 查看数据的形状 (训练的数据必须是二维数据)
feature.shape

#训练数据
x_train = feature[:32500]
y_train = target[:32500]

#测试数据
x_test = feature[32500:]
y_test = target[32500:]  

# 5. 生成算法
from sklearn.neighbors import KNeighborsClassifier
# 实例化一个 knn对象,
# 参数:n_neighbors可调,调到最终预测的是最好的结果.
knn = KNeighborsClassifier(n_neighbors=10)
# fit() 训练函数, (训练数据,训练数据的结果)
knn.fit(x_train,y_train)

# 对训练的模型进行评分 (测试数据,测试数据的结果)
knn.score(x_test,y_test) 

# 6.预测数据
print('真实的分类结果:',np.array(y_test))
print('模型的分类结果:',knn.predict(x_test))

(3)实例:基于sklearn实现手写数字识别系统
        pylot 读取图片:img_arr.shape 查看形状

import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
# 1、样本数据提取:每张图片对应的numpy数组:0,1,2,3,4,5,6,7,8,9
feature =[]
target =[]
for i in range(10):#0-9 文件夹名称
 for j in range(1,501): #1-500图片名称
  imgpath = './data/'+str(i)+'/'+str(i)+'_'+str(j)+'.bmp' #图片路径
  img_arr = pld.imread(imgpath)
  feature.append(img_arr)
  target.append(i)
# 2、把列表转成numpy数组;feature 必须为二维数组;
feature = np.array(feature) #这个feature 里有多个二维数组,
target = np.array(target)

feature.shape
(5000,28,28) #里面有5000个28*28的二维数组

# 扩展:feature是三维数组;多个二维数组组成的数组是三维数组,多个一维数组组成的数组是二维数组!
# 3、feature变形为二维数组
feature.shape(5000,784)
#4、对样本数据和目标数据进行同步打乱
np.random.seed(10)
np.random.shuffle(feature)
np.random.seed(10)
np.random.shuffle(target)

# 5、对样本数据进行拆分:训练数据和测试数据
x_train = feature[:4950]
y_train = target[:4950]
x_test = feature[4950:]
y_test = target[4950:]

# 6、对模型进行训练:参数:n_neighbors可调,调到最终预测的评分最好的结果.
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=8)
knn.fit(x_train,y_train) # (训练数据,训练数据的结果)

# 7、对训练的模型进行评分 (测试数据,测试数据的结果)
knn.score(x_test,y_test)
# 8、对模型进行测试
print('真实的结果',y_test)
print('模型分类的结果',knn.predict(x_test))

#9、保存训练号的模型
from sklearn.externals import joblib
joblib.dump(knn,'./knn.m')

#10、读取训练好的模型
knn = joblib.load('./knn.m')
#-------------------------------------------------------------------------------------------------
# 11、将外部图片带入模型进行测试
# 注意:外部图片的样本数据要转成和训练模型时候使用的样本图片一样的维度数组
#  !!!模型只可以测试类似于测试数据中的特征数据 !!!
img_arr = plt.imgread('./数字.jpg')
eight_arr = img_arr[170:260,80:70] # 截取图片的部分
plt.imshow(eight_arr) #查看截取的数字图片

# 变形为测试数据中的特征数据:feature.shape(5000,784) 每一行是一个一维的784个元素的数组;像素要变为一样
# 12、将eight_arr 对应的图片降维(三维变为二维):将(65,50,3)变为(28,28)
 eight_arr.mean(axis=2 ) # axis=2 表示去除第三个维度,保留(65,50)保证图片不能变!

# 13、将图片像素进行等比例压缩
import scipy.ndimage as ndimage
data_pre_test = ndimage.zoom(eight_arr,zoom=(28/65,28/50))
eight_arr.shape #(28,28)

# 14、将压缩好的图片由二维(28,28)变为一维(1,784)
eight_arr = eight_arr(1,784)

# 15、识别外部进行压缩和降维的图片
knn.predict(eight_arr)
array([8])
# -*- coding: UTF-8 -*-
import numpy as np
import operator
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN

"""
函数说明:将32x32的二进制图像转换为1x1024向量。

Parameters:
 filename - 文件名
Returns:
 returnVect - 返回的二进制图像的1x1024向量

"""
def img2vector(filename):
 #创建1x1024零向量
 returnVect = np.zeros((1, 1024))
 #打开文件
 fr = open(filename)
 #按行读取
 for i in range(32):
  #读一行数据
  lineStr = fr.readline()
  #每一行的前32个元素依次添加到returnVect中
  for j in range(32):
   returnVect[0, 32*i+j] = int(lineStr[j])
 #返回转换后的1x1024向量
 return returnVect

"""
函数说明:手写数字分类测试

Parameters:
 无
Returns:
 无

"""
def handwritingClassTest():
 #测试集的Labels
 hwLabels = []
 #返回trainingDigits目录下的文件名
 trainingFileList = listdir('trainingDigits')
 #返回文件夹下文件的个数
 m = len(trainingFileList)
 #初始化训练的Mat矩阵,测试集
 trainingMat = np.zeros((m, 1024))
 #从文件名中解析出训练集的类别
 for i in range(m):
  #获得文件的名字
  fileNameStr = trainingFileList[i]
  #获得分类的数字
  classNumber = int(fileNameStr.split('_')[0])
  #将获得的类别添加到hwLabels中
  hwLabels.append(classNumber)
  #将每一个文件的1x1024数据存储到trainingMat矩阵中
  trainingMat[i,:] = img2vector('trainingDigits/%s' % (fileNameStr))
 #构建kNN分类器
 neigh = kNN(n_neighbors = 3, algorithm = 'auto')
 #拟合模型, trainingMat为训练矩阵,hwLabels为对应的标签
 neigh.fit(trainingMat, hwLabels)
 #返回testDigits目录下的文件列表
 testFileList = listdir('testDigits')
 #错误检测计数
 errorCount = 0.0
 #测试数据的数量
 mTest = len(testFileList)
 #从文件中解析出测试集的类别并进行分类测试
 for i in range(mTest):
  #获得文件的名字
  fileNameStr = testFileList[i]
  #获得分类的数字
  classNumber = int(fileNameStr.split('_')[0])
  #获得测试集的1x1024向量,用于训练
  vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
  #获得预测结果
  # classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
  classifierResult = neigh.predict(vectorUnderTest)
  print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))
  if(classifierResult != classNumber):
   errorCount += 1.0
 print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount/mTest * 100))

"""
函数说明:main函数

Parameters:
 无
Returns:
 无

"""
if __name__ == '__main__':
 handwritingClassTest()

可以尝试更改这些参数的设置,加深对其函数的理解。

以上就是K近邻法(KNN)相关知识总结以及如何用python实现的详细内容,更多关于python实现K近邻法(KNN)的资料请关注我们其它相关文章!

(0)

相关推荐

  • python K近邻算法的kd树实现

    k近邻算法的介绍 k近邻算法是一种基本的分类和回归方法,这里只实现分类的k近邻算法. k近邻算法的输入为实例的特征向量,对应特征空间的点:输出为实例的类别,可以取多类. k近邻算法不具有显式的学习过程,实际上k近邻算法是利用训练数据集对特征向量空间进行划分.将划分的空间模型作为其分类模型. k近邻算法的三要素 k值的选择:即分类决策时选择k个最近邻实例: 距离度量:即预测实例点和训练实例点间的距离,一般使用L2距离即欧氏距离: 分类决策规则. 下面对三要素进行一下说明: 1.欧氏距离即欧几里得距

  • python实现K近邻回归,采用等权重和不等权重的方法

    如下所示: from sklearn.datasets import load_boston boston = load_boston() from sklearn.cross_validation import train_test_split import numpy as np; X = boston.data y = boston.target X_train, X_test, y_train, y_test = train_test_split(X, y, random_state =

  • python实现KNN近邻算法

    示例:<电影类型分类> 获取数据来源 电影名称 打斗次数 接吻次数 电影类型 California Man 3 104 Romance He's Not Really into Dudes 8 95 Romance Beautiful Woman 1 81 Romance Kevin Longblade 111 15 Action Roob Slayer 3000 99 2 Action Amped II 88 10 Action Unknown 18 90 unknown 数据显示:肉眼判断

  • Python K最近邻从原理到实现的方法

    本来这篇文章是5月份写的,今天修改了一下内容,就成今天发表的了,CSDN这是出BUG了还是什么改规则了... 引文:决策树和基于规则的分类器都是积极学习方法(eager learner)的例子,因为一旦训练数据可用,他们就开始学习从输入属性到类标号的映射模型.一个相反的策略是推迟对训练数据的建模,直到需要分类测试样例时再进行.采用这种策略的技术被称为消极学习法(lazy learner).最近邻分类器就是这样的一种方法. 注:KNN既可以用于分类,也可以用于回归. 1.K最近邻分类器原理 首先给

  • python k-近邻算法实例分享

    简单说明 这个算法主要工作是测量不同特征值之间的距离,有个这个距离,就可以进行分类了. 简称kNN. 已知:训练集,以及每个训练集的标签. 接下来:和训练集中的数据对比,计算最相似的k个距离.选择相似数据中最多的那个分类.作为新数据的分类. python实例 复制代码 代码如下: # -*- coding: cp936 -*- #win系统中应用cp936编码,linux中最好还是utf-8比较好.from numpy import *#引入科学计算包import operator #经典pyt

  • 用python实现k近邻算法的示例代码

    K近邻算法(或简称kNN)是易于理解和实现的算法,而且是你解决问题的强大工具. 什么是kNN kNN算法的模型就是整个训练数据集.当需要对一个未知数据实例进行预测时,kNN算法会在训练数据集中搜寻k个最相似实例.对k个最相似实例的属性进行归纳,将其作为对未知实例的预测. 相似性度量依赖于数据类型.对于实数,可以使用欧式距离来计算.其他类型的数据,如分类数据或二进制数据,可以用汉明距离. 对于回归问题,会返回k个最相似实例属性的平均值.对于分类问题,会返回k个最相似实例属性出现最多的属性. kNN

  • K最近邻算法(KNN)---sklearn+python实现方式

    k-近邻算法概述 简单地说,k近邻算法采用测量不同特征值之间的距离方法进行分类. k-近邻算法 优点:精度高.对异常值不敏感.无数据输入假定. 缺点:计算复杂度高.空间复杂度高. 适用数据范围:数值型和标称型. k-近邻算法(kNN),它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标

  • python机器学习理论与实战(一)K近邻法

    机器学习分两大类,有监督学习(supervised learning)和无监督学习(unsupervised learning).有监督学习又可分两类:分类(classification.)和回归(regression),分类的任务就是把一个样本划为某个已知类别,每个样本的类别信息在训练时需要给定,比如人脸识别.行为识别.目标检测等都属于分类.回归的任务则是预测一个数值,比如给定房屋市场的数据(面积,位置等样本信息)来预测房价走势.而无监督学习也可以成两类:聚类(clustering)和密度估计

  • python机器学习案例教程——K最近邻算法的实现

    K最近邻属于一种分类算法,他的解释最容易,近朱者赤,近墨者黑,我们想看一个人是什么样的,看他的朋友是什么样的就可以了.当然其他还牵着到,看哪方面和朋友比较接近(对象特征),怎样才算是跟朋友亲近,一起吃饭还是一起逛街算是亲近(距离函数),根据朋友的优秀不优秀如何评判目标任务优秀不优秀(分类算法),是否不同优秀程度的朋友和不同的接近程度要考虑一下(距离权重),看几个朋友合适(k值),能否以分数的形式表示优秀度(概率分布). K最近邻概念: 它的工作原理是:存在一个样本数据集合,也称作为训练样本集,并

  • python实现K最近邻算法

    KNN核心算法函数,具体内容如下 #! /usr/bin/env python3 # -*- coding: utf-8 -*- # fileName : KNNdistance.py # author : zoujiameng@aliyun.com.cn import math def getMaxLocate(target): # 查找target中最大值的locate maxValue = float("-inFinIty") for i in range(len(target)

随机推荐