数据集和源代码有需要的童鞋可以私信我~
K-近邻算法
K-近邻算法有称为KNN算法(k-Nearest Neighbour algorithm)。
1.原理
1.1基本原理
K-近邻算法原理:给定已知标签类别的训练数据集,输入没有标签的新数据后,在训练集种找到与新数据最邻近的k个实列,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。
图1中,蓝色方块和红色三角为两种类别,现在需要判断绿色原点属于那种类别:
当k=3时,绿色圆点属于红色三角这类;
当k=5时,绿色圆点属于蓝色方块这类。
举个例子,k-近邻算法可以用来分类电影的所属类型。
可以计算出未知电影到已知电影的距离,按照距离递增排序,就可以找到k个距离最近电影。这k个距离最近的电影类别出现最多就是未知电影的类别。
假设,k=3,前三部电影都是“爱情片”,则可以认为未知电影也是“爱情片”。
1.2距离计算
知道了K-近邻算法的基本原理后,下一步要做的就是来求解距离。
K-邻近算法中计算距离采用的时欧氏距离,二维、三维的欧氏距离高中便已经学过:
三维欧式公式:
∣
A
B
∣
=
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
+
(
z
1
−
z
2
)
2
3
\lvert AB \rvert = \sqrt[3]{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2}
∣AB∣=3(x1−x2)2+(y1−y2)2+(z1−z2)2
扩展到N维:
∣
A
B
∣
=
(
x
1
−
y
1
)
2
+
(
x
1
−
y
2
)
2
+
.
.
.
.
.
.
.
+
(
x
n
−
y
n
)
2
n
=
∑
(
x
i
−
y
i
)
2
n
\lvert AB \rvert = \sqrt[n]{(x_1-y_1)^2+(x_1-y_2)^2+.......+(x_n-y_n)^2}=\sqrt[n]{\sum{(x_i-y_i)^2}}
∣AB∣=n(x1−y1)2+(x1−y2)2+.......+(xn−yn)2=n∑(xi−yi)2
我们可以通过以上公式计算出未知电影到已知电影的距离。
2.算法实现
在了解K-邻近算法后,可以利用python来实现这些过程:
from numpy import*
import operator
import matplotlib
import matplotlib.pyplot as plt
#打开文件,读取数据
def openfile(filename):
fr = open(filename)
arrayOlines = fr.readlines()
numberOfLines = len(arrayOlines)
returnMat = zeros((numberOfLines,3))
index = 0
classLabelVector = []
for lines in arrayOlines:
lines = lines.strip()
listFromLine = lines.split('\t')
returnMat[index,:] = listFromLine[0:3]
classLabelVector.append(listFromLine[-1])
index += 1
return returnMat,classLabelVector
#数据归一化处理
def autoNorm(dataSet):
minVector = dataSet.min(0)
maxVector = dataSet.max(0)
ranges = maxVector - minVector
normdataSet = zeros(shape(dataSet))
normdataSet = dataSet - tile(minVector,(dataSet.shape[0],1))
normdataSet = normdataSet/tile(ranges,(dataSet.shape[0],1))
return normdataSet,ranges,minVector
def classfy0(inX,dataSet,labels,k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX,(dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sumDance = sqDiffMat.sum(axis = 1)
distances = sqrt(sumDance)
SortDance = distances.argsort()
classCount = {}
for i in range(k):
LabelVector = labels[SortDance[i]]
classCount[LabelVector] = classCount.get(LabelVector,0) + 1
sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
def datingClasstest(path):
hoRadio = 0.1
datingDataMat,datingLabel = openfile(path)
normDataMat,ranges,minVector = autoNorm(datingDataMat)
m = normDataMat.shape[0]
numTestVector = int(hoRadio*m)
errorCount = 0.0
for i in range(numTestVector):
classifileResult = classfy0(datingDataMat[i,:],datingDataMat[numTestVector:m,:],datingLabel[numTestVector:m],3)
print('the classifileReult is :{} ,the real label is :{}'.format(classifileResult,datingLabel[i]))
if (classifileResult != datingLabel[i]):
errorCount += 1
print('the total error is :',(errorCount/(numTestVector)))
path = 'datingTestSet.txt'
m,n =openfile(path)
datingClasstest(path)
fig = plt.figure()
ax = fig.add_subplot(111)
#ax.scatter(m[:,1],m[:,2],15.0*array(n),15.0*array(n))
ax.scatter(m[:,0],m[:,1],15.0*array(n),15.0*array(n))
plt.show()