算法理解

K-近邻算法测量待分类样本的特征值与已经分好类的样本对应的特征值之间的距离,最邻近的一个或者几个训练样本的类别决定了待分类样本所属的类别。

工作原理

存在一个样本数据集合(训练样本集),并且每个训练样本都有已知对应的所属分类(标签)。输入待分类的新样本后,将新样本的每个特征与训练样本集中数据对应的特征进行比较。然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般选前k个最相似的数据(一般k不大于20)。最后,选择k个最相似数据中出现次数最多的分类,作为新样本的分类。

距离计算

在KNN中,通过计算待测样本和训练样本的特征值之间的差异(距离)作为对象之间的相似性指标,一般使用欧氏距离或曼哈顿距离:

k-近邻算法优点是精度高、对异常值不敏感、无数据输入假定。缺点是计算复杂度高、空间复杂度高。适用数据范围为数值型和标称型。

算法描述

1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

# -*- coding: utf-8 -*-
""" k-Nearest Neighbors
Created on Mon Jan 23 12:56:00 2017@author: xieyuxi
"""
from numpy import *
import operator
import numpy as npdef createDataSet():group = array([[1.0, 1.1],[1.0,1.0],[0,0],[0,0.1]])lables = ['A','A','B','B']return group, lablesprint group, lablescreateDataSet()""" Classify the unknown vector input into defined classes
1、calculate the distance between inX and the current point
2、sort the distances in increasing order
3、take k items with lowest distances to inX
4、find the majority class among these items
5、return the majority class as our prediction for the class of inX Args:inX : the input vector to classify dataSet : the full matrix of training exampleslabels : a vector of labels from the training examplesk : the number of nearest neighbors to use in the votingAttention:The labels vector should have as many elements in it as there are rows in the dataSet matrix.Returns:the majority class as our prediction for the class of inXRaises:None
"""
def classify0(inX, dataSet, labels, k):# shape是numpy的数组的一个属性,表示数组的维度# 比如一个 n x m的数组 Y(n 行 m列),Y.shape表示(n,m)# 所以 Y.shape[0]等于 n, Y.shape[1]等于 m# dataSet是4X2的数组,所以此处dataSetSize等于4dataSetSize = dataSet.shape[0]      # 4# 1、先将一维矩阵扩展和测试矩阵的维度一样# 2、将新生成的待测矩阵同测试矩阵进行矩阵减法,再将矩阵的差的平方和开根得到距离# 3、将距离排序并返回
#==============================================================================
#     1、 tile(A, reps):reps的数字从后往前分别对应A的第N个维度的重复次数。
#        如(A,2)表示A的列变量重复2遍,
#           tile(A,(2,3))表示A的行变量重复2遍,列变量重复3遍
#           tile(A,(2,2,3))表示A的第一个维度重复2遍,第二个维度重复2遍,
#           第三个维度重复3遍。
#           Examples:
#     ----------------------------------------
#     # a = np.array([0, 1, 2])
#     # np.tile(a, 2)
#     array([0, 1, 2, 0, 1, 2])
#     # np.tile(a, (2, 3))
#     array([[0, 1, 2, 0, 1, 2, 0, 1, 2],
#            [0, 1, 2, 0, 1, 2, 0, 1, 2]])
#     ----------------------------------------
#     # b = np.array([[1, 2], [3, 4]])
#     # np.tile(b, 2)
#     array([[1, 2, 1, 2],
#            [3, 4, 3, 4]])
#     # np.tile(b, (2, 1))
#     array([[1, 2],
#            [3, 4],
#            [1, 2],
#            [3, 4]])
#
#     2、diffMat矩阵:先将输入的值复制到和训练样本同行,再做减法
# 以[0,0]为例:
# [0,0] to array([[0, 0]       [[0, 0]   [[1.0,1.1]           [[-1.  -1.1]
#                 [0, 0]  to   [0, 0] -  [1.0,1.0]    to       [-1.  -1. ]
#                 [0, 0]       [0, 0]    [0,0]                 [ 0.   0. ]
#                 [0, 0]])     [0, 0]]   [0,0.1]]              [ 0.  -0.1]]
#==============================================================================diffMat = tile(inX, (dataSetSize,1)) - dataSet# 其中矩阵的每一个元素都做平方操作#    [[ 1.    1.21]#     [ 1.    1.  ]#     [ 0.    0.  ]#     [ 0.    0.01]]sqDiffMat = diffMat**2# axis=0, 表示列。 axis=1, 表示行。# example:# c = np.array([[0, 2, 1], [3, 5, 6], [0, 1, 1]])# c.sum() = 19# c.sum(axis=0) =[3 8 8],即将矩阵的行向量想加后得到一个新的一维向量# c.sum(axis=1) =[3,14,2], 即每个向量将自己内部元素加和作新一维向量里的一个元素 # 此处已经将每一个行向量中的每一个元素都做了平方操作,并求和得到每一个向量之和# 得到一个一维数组,其中有四个元素分别对应了输入元素与 4个测试样本的平方距离sqDistances = sqDiffMat.sum(axis=1)     # [ 2.21  2.    0.    0.01]# 将平方距离开方distances = sqDistances**0.5 # [ 1.48660687  1.41421356  0.          0.1 ]# argsort函数返回的是数组值从小到大的索引值# examples:#     # x = np.array([3, 1, 2])#     # np.argsort(x)#         array([1, 2, 0]) 数值1对应下表1,数值2对应下表2,数值3,对应下标0# [1.48660687  1.41421356  0.0  0.1 ] to [2 3 1 0]sortedDistIndex = distances.argsort()   # [2 3 1 0]# 建造一个名为classCount的字典,Key是label,value是这个label出现的次数classCount={}for i in range(k):# 这里很巧妙的地方在于,一开始测试数组和Label的位置是一一对应的# 所以这里可以通过上面获得的测试数组的下标index获得对应的分类labels[index]voteLabel = labels[sortedDistIndex[i]]# 这里将每一个[label : Value]赋值,Value为计算VoteLabel出现的次数# 如果Label不在字典classCount中时,get()返回 0,存在则value加 1classCount[voteLabel] = classCount.get(voteLabel,0) + 1# 根据字典classCount中的Value值对字典进行排序,选出出现次数最多的Label#       sorted(iterable, cmp=None, key=None, reverse=False) #       return new sorted list#       1、iterable:是可迭代类型的对象(这里的字典通过iteritems()进行迭代)#       2、cmp:用于比较的函数,比较什么由key决定,一般用Lamda函数#       3、key:用列表元素的某个属性或函数进行作为关键字,迭代集合中的一项; #               operator.itemgetter(1)表示获得对象的第一个域的值(这里指value)#       4、reverse:排序规则。reverse = True 降序 或者 reverse = False 升序。#       #       return: 一个经过排序的可迭代类型对象,与iterable一样。#               这里返回排好序的[Label:value], 即 [('B', 2), ('A', 1)]sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1), reverse=True)# 返回可迭代对象的第一个域的第一值,也就是出现次数最多的Label# sortedClassCount[0][1] 表示第一个域的第二个值,就是出现最多次数Label出现次数return sortedClassCount[0][0]

本案例的数据被置于txt文件中,所以需要我们将数据从txt文件中抽出并做处理。所以我们准备函数file2matrix()将txt的数据转换为矩阵方便我们后面做运算。

""" Parsing data from a text file
Change the text file data to the format so that the classifier can accept and use it Args:filename string Returns:A matrix of training examples,A vector of class labelsRaises:None
"""
def file2matrix(filename):# 根据文件名打开文件fr = open(filename)# 读取每一行的数据# txt文件中的数据类似:"40920      8.326976    0.953952    largeDoses"WarrayOlines = fr.readlines()# 得到文件行数numberOfLines = len(arrayOlines)# 创建返回的Numpy矩阵# zeros(a) 仅有一个参数时,创建一个一维矩阵,一行 a 列# zeros(a, b) 创建一个 a X b 矩阵, a 行 b 列# 这里取了数据的行数和前三个特征值(前三个是特征,第四个个是类别)创建一个矩阵returnMat = zeros((numberOfLines,3)) # 建造一个名为 classLabelVector 的 List 用来存放最后列的LabelclassLabelVector = []# 这里的 index 指的是矩阵的第几行,从 0 开始index = 0#( 以下三行) 解析文件数据到列表for line in arrayOlines:# 去掉文本中句子中的换行符"/n",但依然保持一行四个元素line = line.strip()# 以 ‘\t’(tab符号)分个字符串,文本中的数据是以tab分开的# 另外需要注意 split() 函数返回一个 List对象#       如:['30254', '11.592723', '0.286188', '3']listFromLine = line.split('\t')# 选取前listFromLine的三个元素,存储在特征矩阵中# returnMat[index,:]这里需要注意,因为returnMat是一个矩阵#       其中的 index指的是矩阵中的第几个list#       例如 listMat = [[list1] #                       [list2] #                       [list3]#                       ......#                       [listn]]#       listMat[0]表示的是矩阵listMat中的第1行,即 [list1]#       listMat[2,:] 表示的是矩阵listMat中的第3行的所有元素#       listMat[2,0:2] 表示矩阵listMat中的第3行下标为 0和1两个元素## listFromLine[0:3]切片开始于0、停止于3,也就是取了下标为0,1,2的元素# 将listFromLine[0:3]的第0号到2号元素赋值给特征矩阵returnMat对应特征中returnMat[index,:] = listFromLine[0:3]# listFromLine[-1] 取listFromLine的最后一列标签类(将其强行转换为int类型)# 同时将该类别标签按顺序加入到标签向量classLabelVector中classLabelVector.append(int(listFromLine[-1]))# index加 1,矩阵存取下一个listindex += 1return returnMat,classLabelVector

在这先根据特征值,利用Matplotlib绘制类别的散点图。

import matplotlib
# matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表。
import matplotlib.pyplot as plt
# 我们先利用写好的KNN.py文件中的file2matrix()函数将数据转为矩阵
datingDataMat, datingLabels = KNN.file2matrix(filename)
# 这里创建了一个新的 figure,我们要在上面作图
fig = plt.figure()
# add_subplot(111)相当于在figure上添加子图
# 其中 111 的意思是,将子图切割成 1行 1列的图,并在第 1 块上作画
# 所以这里只有一副画
# 再举个例子 add_subplot(22x),将子图切割成 2行 2列的图,并在第 X 块上作画
ax = fig.add_subplot(111)
# 利用scatter()函数分别取已经处理好的矩阵datingDataMat的第一列和第二列数据
# 并用不同颜色将类别标识出来
ax.scatter(datingDataMat[:,0], datingDataMat[:,1],
15.0*array(datingLabels), 15.0*array(datingLabels))
# 展示我们做好的 figure
plt.show()

下图是很好地解释add_subplot(22x):

根据矩阵第一列和第二列数据可以获得以下带有颜色类别区分的散点图:

(红色的点表示非常喜欢,绿色的点表示一般喜欢,蓝色的点表示并不喜欢)

观察上图我们不难发现一个问题,如果当某一个特征值与其他的特征值的差异过大的话,如果不加权重或各特征权重均衡的话,很可能会影响到最后的分类,比如例子中的飞行距离,远远大于其他两个特征值,在这种情况下,特征的距离就会受飞行距离特征值得影响。所以我们需要将数据进行归一化,即将所有数据都变为 0~1 之间的数,目的是让数据的影响都能比较均衡。

""" Normalizing numeric values
Normalize the data to values between 0 and 1.Formula:newValue = (oldValue-min)/(max-min)
In the normalization procedure, the variables min and max are the
smallest and largest values in the dataset. Args:dataSet: the data set to be normalized Returns:A normalized data setRaises:None
"""
def autoNorm(dataSet):# min(0)取矩阵每一列的最小值# min(1)取矩阵每一行的最小值# Examples:#     array([[1,2]#            [3,4]#            [5,6]])#       min(array,0) = [1,2]#       min(array,1) = [1,3,5]# 这里同: minVals = np.min(dataSet,0)# 返回的是一个一维矩阵minVals = dataSet.min(0)    # max(0)取矩阵每一列的最大值# max(1)取矩阵每一列的最大值# 返回的是一个一维矩阵    maxVals = dataSet.max(0)# ranges也是一个一维矩阵ranges = maxVals - minVals# shape(dataSet) 返回一个记录有矩阵维度的tuple# 例如:np.shape([[1, 2]]) = (1, 2)# zeros(shape)返回一个具有 shape 维度的矩阵,并且所有元素用 0 填充normDataSet = zeros(shape(dataSet))# m 表示 dataSet 矩阵的行数# dataSet.shape[1] 表示矩阵的列数m = dataSet.shape[0]# tile(minVals, (m,1)) 首先将 minVals 复制为 m 行的矩阵# examples:#    if   minVals = [[1,2,3]]#         tile(minVals, (3,1))(行数复制 3 遍,列保持不变)#    return [[1,2,3]#            [1,2,3]#            [1,2,3]]normDataSet = dataSet - tile(minVals, (m,1))# 同上,将 一维矩阵 ranges 复制 m行,再让矩阵中的元素做商normDataSet = normDataSet/tile(ranges, (m,1))# 返回归一化的矩阵,最大与最小值的差值矩阵,和最小值矩阵return normDataSet, ranges, minVals


(上图为归一化后的特征值)

我自己的博客地址为:谢雨熹的学习博客
欢迎大家来交流!

Talk is cheap, show me your code!

《机器学习实战》第二章 - k-近邻算法相关推荐

  1. 机器学习实战第二章K近邻算法照葫芦画瓢实践。

    分别实现了最基本的3个DEMO 1.给你若干个带有标签的二维点作为训练集,给定一系列的二维随机点,看其通过训练集,可以被分为哪一类 2.给你N个人的飞行里程数,玩游戏消耗时间百分比和每周消耗冰激凌的公 ...

  2. 【机器学习入门】(1) K近邻算法:原理、实例应用(红酒分类预测)附python完整代码及数据集

    各位同学好,今天我向大家介绍一下python机器学习中的K近邻算法.内容有:K近邻算法的原理解析:实战案例--红酒分类预测.红酒数据集.完整代码在文章最下面. 案例简介:有178个红酒样本,每一款红酒 ...

  3. 机器学习7更多关于k近邻算法的思考

    文章目录 一.一些总结 1.缺点1: 2.优化: 3.缺点2: 4.缺点3: 5.缺点4: 二.机器学习流程回顾 一.一些总结 k近邻算法是一个解决分类问题的算法,天然可以解决多分类问题: 不仅如此, ...

  4. 机器学习7/100天-K近邻算法

    Day7 K近邻算法 github: 100DaysOfMLCode What is K-NN k近邻算法是常用的简单分类算法也可用于回归问题. KNN是一个无参的(不需要对数据分布做任何假设).基于 ...

  5. 机器学习实战第二章——KNN算法(源码解析)

    机器学习实战中的内容讲的都比较清楚,一般都能看懂,这里就不再讲述了,这里主要是对代码进行解析,如果你很熟悉python,这个可以不用看. #coding=utf-8 ''' Created on 20 ...

  6. 机器学习实战读书笔记--k邻近算法KNN

    k邻近算法的伪代码: 对未知类别属性的数据集中的每个点一次执行以下操作: (1)计算已知类别数据集中的点与当前点之间的距离: (2)按照距离递增次序排列 (3)选取与当前点距离最小的k个点 (4)确定 ...

  7. 【机器学习】sklearn机器学习入门案例——使用k近邻算法进行鸢尾花分类

    1 背景 这个案例恐怕已经被说的很烂了,机器学习方面不同程度的人对该案例还是有着不同的感觉.有的人追求先理解机器学习背后的理论甚至自己推导一遍相关数学公式,再用代码实现:有的人则满足于能够实现相关功能 ...

  8. 机器学习实战-第二章代码+注释-KNN

    #-*- coding:utf-8 -*- #https://blog.csdn.net/fenfenmiao/article/details/52165472 from numpy import * ...

  9. 机器学习第七章之K近邻算法

    K近邻算法(了解) 7.1 K近邻算法 7.1.1 K近邻算法的原理介绍 7.1.2 K近邻算法的计算步骤及代码实现 7.2 数据预处理之数据归一化 7.2.1 min-max标准化 7.2.2 Z- ...

  10. 【机器学习】原理与实现k近邻算法

    文章目录 系列文章目录 前言 一.k近邻算法是什么? 二.使用步骤 1.引入库 2.读入数据 总结 前言 随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了 ...

最新文章

  1. PHP框架性能不权威对比
  2. 全国成人计算机考试题,成人计算机考试试题.docx
  3. UI自动化之特殊处理三(日期控件\表格\富文本)
  4. linux 进程管理 ppt,linux操作系统-进程管理和打印管理.ppt
  5. java 酒店系统_基于JAVA的酒店管理系统
  6. php 比较数组中的元素,php – 比较多维数组中的元素
  7. 在Jersey测试中模拟SecurityContext
  8. CentOS安装图文教程
  9. @程序员,盘一盘炼成高效能开发者的 14 个习惯!
  10. python写机器人程序_从Python写入机器人框架控制台
  11. python机器学习案例系列教程——算法总结
  12. 北京内推 | 微软亚洲研究院机器学习组招聘AI药物发现研究实习生
  13. 漏洞扫描工具Nessus的下载与安装教程
  14. GO GOPROXY代理设置
  15. Android常用工具类...
  16. 互联网大数据面试题集锦
  17. 让苹果CEO库克折服的程序员仅10岁!?
  18. 无人机技术将从硬件创新转向自动化智能飞行
  19. 点计算机管理 显示文件缺失,电脑开机显示文件丢失怎么回事
  20. 吴恩达深度学习作业(week2)-(1)

热门文章

  1. 基于CPLD的主板上电时序控制--状态机方式
  2. 现代永磁同步电机控制原理及matlab仿真_永磁同步电机是什么?
  3. 如何在微信公众号分享PPT?
  4. mkdir: Permission denied: user=root, access=WRITE, inode=/lcy/test5.txt:hdfs:hdfs:drwxr-xr-x
  5. 【解决问题】ducky one2 mini mecha机械键盘在macOS下不识别
  6. vue项目之H5 app页面通过swiper实现中间变大,两边缩小的滑动轮播功能
  7. CGB2105-Day-09笔记
  8. 【前端必备项目】品优购商城前端
  9. 苹果手机双卡双待是哪一款_手机双卡双待信号有区别吗手机主卡、副卡这些区别,早知道为好!...
  10. 技术人员必会英语单词