K近邻算法


K-近邻算法(KNN)是分类数据最简单最有效的算法。

核心思想

采用不同特征值之间的距离方法进行分类
首先:

我们有一个样本集(也称训练样本集),样本中的每个数据都存在标签,即样本集中每一个数据对应与所属分类的对应关系。

之后:

输入没有标签的新数据时,将新数据的每个特征与样本集中数据的特征进行比较,(一般是计算欧氏距离)然后算法提取样本集中特征最相近数据(最近邻)的分类标签

附:一本只选择样本数据集中前K个最相近的数据,这就是k近邻中的k。k一般不超过20的整数

KNN算法的过程为:

  • 选择一种距离计算方式, 通过数据所有的特征计算新数据与已知类别数据集中的数据点的距离
  • 按照距离递增次序进行排序,选取与当前距离最小的k个点
  • 对于离散分类,返回k个点出现频率最多的类别作预测分类;对于回归则返回k个点的加权值作为预测值

kNN的优缺点

优点:简单有效
缺点:
一是必须有接近实际数据的训练样本数据,且要保存全部数据集,占用存储空间且计算耗时;
二是无法给出任何数据的急促结构信息,无法知晓平均实例样本和典型实例样本具有什么特征。使用概率测量方法可以解决这个问题

算法实例

创建kNN.py
(1)创建数据集

#创造数据集
def createDataSet():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels

有四个数据,其标签分别为(A,A,B,B)
(2) 构照kNN分类器

#第一个kNN分类器  
#inX-测试数据 dataSet-样本数据  labels-标签 k-邻近的k个样本
def classify0(inX,dataSet,labels,k):  
    dataSetSize = dataSet.shape[0]  #dataSet.shape[0]是第一维的数目    
    '''
    计算与所有点的距离,并进行排序
    '''
    diffMat = tile(inX,(dataSetSize,1)) - dataSet #要分类的新数据与原始数据做差 
    sqDiffMat = diffMat**2  #求差的平方  
    sqDistance = sqDiffMat.sum(axis=1)  #求差的平方的和    
    distances = sqDistance**0.5 #求标准差   
    sortDistIndicies = distances.argsort() #距离排序    
    classCount = {}  #定义元字典   
    '''
    遍历前k个元素,选择距离最小的k个点
    '''
    for i in range(k):  
        voteIlabel = labels[sortDistIndicies[i]]  #获得前k个元素的标签 
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#计算前k个数据标签出现的次数   
    '''
    排序
    '''
    sortedClassCount =sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse = True) #对得到的标签字典按降序排列   
    return sortedClassCount[0][0] #返回出现次数最多的标签  

结果测试

group, labels = kNN.createDataSet( )
kNN.classfy0([0,0],group,labels,3)

结果为B

(3)读取文本文件中的数据

def file2matrix(filename):

    fr = open(filename)# 打开文件
    numberOfLines = len(fr.readlines()) # 计算文本文件的行数
    returnMat = zeros((numberOfLines,3))# 创建返回的数据矩阵
    classLabelVector = []# 创建类标签
    fr = open(filename) # 打开文件
    index = 0 # 定义索引
    # 读取文件的每一行并处理
    for line in fr.readlines():
        line = line.strip()# 去除行的尾部的换行符
        listFromLine = line.split('\t') # 将一行数据按空进行分割
        returnMat[index,:] = listFromLine[0:3] # 0:3列为数据集的数据
        classLabelVector.append((listFromLine[-1])) # 最后一列为数据的分类标签
        index += 1# 索引加1
   
    return returnMat,classLabelVector # 返回数据集和对应的类标签

(4)显示散点图

import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet.txt')
#ax.scatter(datingDataMat[:,1], datingDataMat[:,2])

ax1.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0*array(datingLabels), 15.0*array(datingLabels))

ax.axis([-2, 25, -0.2, 2.0])
plt.xlabel(u"玩游戏视频所耗时间百分比")
plt.ylabel(u"每周消费的冰淇淋公升数")
plt.show()

(5)归一化数值
为了防止特征值数量的差异对预测结果的影响(比如计算距离,量值较大的特征值影响肯定很大),我们将所有的特征值都归一化到[0,1]

def autoNorm(dataSet):
    minVals = dataSet.min(0) # 求数据矩阵每一列的最小值
    maxVals = dataSet.max(0)# 求数据矩阵每一列的最大值
    ranges = maxVals - minVals# 求数据矩阵每一列的最大最小值差值
    #normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0] # 返回数据矩阵第一维的数目
    normDataSet = dataSet - tile(minVals, (m, 1)) # 求矩阵每一列减去该列最小值,得出差值
    normDataSet = normDataSet / tile(ranges, (m, 1)) # 用求的差值除以最大最小值差值,即数据的变化范围,即归一化
    return normDataSet, ranges, minVals # 返回归一化后的数据,最大最小值差值,最小值

附:numpy函数小结

#coding=utf-8
__author__ = 'Administrator'
from numpy import *

a = array([[0, 1, 0], [1, 1, 2]])
print a

aSize = a.shape[0] #可以认为是输出列数
print aSize

b = arange(7, dtype=uint16) #dtype为数据类型对象
print b

'''
tile
将数组a重复n次
'''
c = array([0, 1])
d = tile(c, (3, 1))
print d

c = zeros((3, 1), dtype=int)
print c

输出结果

[[0 1 0]
[1 1 2]]
2
[0 1 2 3 4 5 6]
[[0 1]
[0 1]
[0 1]]
[[0]
[0]
[0]]

参考文献:

http://www.aichengxu.com/yejie/512129.htm
http://blog.csdn.net/quincuntial/article/details/50471423
http://blog.csdn.net/suipingsp/article/details/41964713

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容