您的位置:首页 > 编程语言 > Python开发

kNN分类器和Python算法实现

2018-01-04 23:19 471 查看
    很早就买了机器学习这本书,由于工作上太忙一直没来得及看,最近时间比较充裕,终于拿出时间来好好研究一下这本书。从第一个算法kNN分类器开始,记录自己的学习经历。

kNN分类器和Python算法实现

    假设生活中你突然遇到一个陌生人,你对他很不了解,但是你知道他喜欢看什么样的电影,喜欢穿什么样的衣服。根据以前你的认知,你把你身边的朋友根据喜欢的电影类型,和穿什么样的衣服,简单的分为了两类,有钱的和没钱的。那你该怎么将这个陌生人分类呢?物以类聚,人以群分,你看他喜欢看的电影和穿衣服的衣服和那群人比较接近,然后你就把他归为那类人,这就是kNN算法的思想。

    那么怎么评判他和那类人比较接近呢?这就用到了“距离”的概念。首先你要把电影类型、和穿的衣服量化,转化为可以进行计算的数字量。然后计算他的[电影类型、衣服品牌]和你原来分类中其余个体的[电影类型、衣服品牌]之间的距离,从距离[d1,d2,d3....]中选取出K个最近的值,然后看这些距离中最多的分类是哪个。

    这,就是kNN分类的思想。

    首先,我们先创建一个训练样本,也就是已有的数据大类“A”和“B”,对应的点分别为A - [1.0 0.9] [1.0 1.0] 和B - [0.1 0.2 ] [0.0 0.1]

from numpy import *
def createDataSet():
group = array([[1.0, 0.9], [1.0, 1.0], [0.1, 0.2], [0.0, 0.1]])
labels = ['A','A','B','B']
return group,labels


   在这里我们用欧式距离: d = sqrt((x1-x2)^2+(y1-y2)^2)来计算要分类的数据和样本数据之间的“相近”程度。当然,选择用什么距离也是kNN算法的一大难点,这里不做赘述。

    首先我们按照欧氏距离的计算公式,用Python表示出来

def Euclidean(vec1, vec2):
# 将两个向量转化为array,以便计算坐标的差
npvec1, npvec2 = array(vec1), array(vec2)
# 计算每个维度上差值平方根之和
return math.sqrt(((npvec1-npvec2)**2).sum()))
    计算输入数据和训练数据中每个数据的欧式距离
def DisVector(InX,DataSet):
Dis = []    #记录距离
Count = 0
#计算待分类数据和训练集和中所有数据的距离
for i in DataSet:
#print(i)
Dis.insert(Count,Euclidean(InX,i))
Count = Count +1
return Dis

    下面,就按距离来进行分类

def Classify(InX,DataSet,Labels,k):
Distance = DisVector(InX,DataSet)
classified =[]
Count = 0
# 初始化classified
for i in range(len(Distance)):
classified.append(0)
for i in range(k):#Distance和Labels列表长度一样
# 找到距离的最小值
count = Distance.index(min(Distance))
# 把最小值索引位置对应的+1
classified[count] =  classified[count] +1
#把Distance中的最小值移除,最小值变为次小值
Distance = Distance.remove(min(Distance))
#把字典classified的键值
return Labels[classified.index(max(classified))]


我们测试程序

dataset,labels = createdata()
a= [0.1,0.3]
Class = Classify(a,dataset,labels,1)
print(Class)
结果为B 

    当然,还有数据归一化的问题,等等。以后再更新吧。

下面是源码:

from numpy import *
import os
import math
def createDataSet():
group = array([[1.0, 0.9], [1.0, 1.0], [0.1, 0.2], [0.0, 0.1]])
labels = ['A','A','B','B']
return group,labels
def Euclidean(vec1, vec2):
# 将两个向量转化为array
npvec1, npvec2 = array(vec1),array(vec2)
# 计算每个维度上差值平方根之和
return math.sqrt(((npvec1-npvec2)**2).sum())
def DisVector(InX,DataSet): Dis = [] #记录距离 Count = 0 #计算待分类数据和训练集和中所有数据的距离 for i in DataSet: #print(i) Dis.insert(Count,Euclidean(InX,i)) Count = Count +1 return Dis

def Classify(InX,DataSet,Labels,k): Distance = DisVector(InX,DataSet) classified =[] Count = 0 # 初始化classified for i in range(len(Distance)): classified.append(0) for i in range(k):#Distance和Labels列表长度一样 # 找到距离的最小值 count = Distance.index(min(Distance)) # 把最小值索引位置对应的+1 classified[count] = classified[count] +1 #把Distance中的最小值移除,最小值变为次小值 Distance = Distance.remove(min(Distance)) #把字典classified的键值 return Labels[classified.index(max(classified))]
DataSet,Labels = createDataSet()
inX = [0.2,0.3]

print('训练样本为:',DataSet)
print('标签为:',DataSet)
print('待分类样本为:',inX)
print('分类结果为:',Classify(inX,DataSet,Labels,1))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: