1、原理
给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最近的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类。
2、步骤
(1).计算新实例和训练样本中每个样本点的距离(常见的距离度量有欧式距离,马氏距离,曼哈顿距离等);
(2)对上面所有的距离值进行排序;
(3)选前k个最小距离的样本;
(4)根据这k个样本的标签进行投票,得到最后的分类类别;
如何选择一个最佳的K值,这取决于数据。一般情况下,在分类时较大的K值能够减小噪声的影响。但会使类别之间的界限变得模糊。一个较好的K值可通过各种启发式技术来获取,比如,交叉验证。另外噪声和非相关性特征向量的存在会使K近邻算法的准确性减小。
3、公式描述
输入:训练数据集
T={(x1,y1),(x2,y2),...,(xn,yn)}
其中, xi⊂Rn 为实例的特征向量, yi⊂{c1,c2,c3,...,ck} 为实例的类别,i=1,2,3..,n
输出:实例x所属的类y
(1)根据给定的距离度量,在训练集T中找出与x最临近的k个点,涵盖这k个点的x的邻域记做 Nk(x)
(2)在 Nk(x) 中根据分类决策规则(如多数表决)决定x的类别y:
y=argmax∑xi⊂Nk(x)I(yi=cj),i=1,2,3...,n,j=1,2,3...,n
其中 I 为指示函数,即当
KNN算法的优点:
1. 思想简单,理论成熟,既可以用来做分类也可以用来做回归;
2. 可用于非线性分类;
3. 训练时间复杂度为O(n);
4. 准确度高,对数据没有假设,对outlier不敏感;
缺点:
1. 计算量大;
2. 样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
3. 需要大量的内存;
4、代码实现
(1)手动编写knn分类器
import numpy as np
# 创建数据集,包含四个实例和两个分类
def createDataSet():
group = np.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
# 用KNN进行分类
def kNNClassify(newInput, dataSet, labels, k):
numSamples = dataSet.shape[0] # shape[0]代表行数,这里为样本点个数
## step 1: 计算欧式距离
# >行数=原来*numSamples,列数=原来*1
# >然后每个特征点和样本的点进行相减,返回一个矩阵
diff = np.tile(newInput, (numSamples, 1)) - dataSet
squaredDiff = diff ** 2
# axis=0 按列求和,1为按行求和,行向量分别相加,从而得到新的一个行向量
squaredDist = np.sum(squaredDiff, axis = 1) # 每一列分别求和,得到行向量
distance = squaredDist ** 0.5
## step 2: 对距离按大小逆序排序
sortedDistIndices =np.argsort(distance) #返回的是数组元素值从小到大的索引值
classCount = {} # 定义一个元组,用于存距离最近的K个点中,点所属的每个类出现的次数
for i in xrange(k):
## step 3: 在距离中选择最小K个距离
voteLabel = labels[sortedDistIndices[i]]
# step 4: 计算标签发生的概率
# get()函数返回指定键的值,如果值不在字典中返回默认值0。
classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
## step 5: 最大的类将会被返回
maxCount = 0
for key, value in classCount.items():
if value > maxCount:
maxCount = value
maxIndex = key
return maxIndex
if __name__ == '__main__':
dataSet, labels = createDataSet()
testX = np.array([1.2, 1.0])
k = 3
outputLabel = kNNClassify(testX, dataSet, labels, 3)
print "Your input is:", testX, "and classified to class: ", outputLabel
testX = np.array([0.1, 0.3])
outputLabel = kNNClassify(testX, dataSet, labels, 3)
print "Your input is:", testX, "and classified to class: ", outputLabel
(2)调用框架中的工具实现Knn分类器
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
group = np.array([[1.0, 0.9], [1.0, 1.0], [0.1, 0.2], [0.0, 0.1]])
labels = ['A', 'A', 'B', 'B']
knn = KNeighborsClassifier(n_neighbors=3) # k值设置为3
knn.fit(group, labels)
print(knn.predict([[0.1, 0.3]])) # 预测值