KNN算法
概述
KNN算法:即最邻近分类算法(K-NearestNeighbor
算法思路:如果一个样本在特征空间中的k个最相似(即特征空间中最临近)的样本中的大多数属于某一个类别 则该样本也属于这个类别 k通常是不大于20的整数 KNN算法中 所选择的邻居都是已经正确分类的对象 该方法在定义决策上只依据最邻近的一个或几个样本的类别来决定待分样本所属的类别
如上所示
绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。由此也说明了KNN算法的结果很大程度取决于K的选择。
在kNN中,计算对象之间的距离通常使用欧氏距离。比如若是求二维平面的欧氏距离,则公式为d = sqrt[(x1 - x2)^2 + (y1 - y2)^2]
KNN算法思路总结:就是在训练集中数据和标签已知的情况下,输入测试数据 将测试数据的特征与训练集中对应的特征进行相互比较 找到训练集中与之最为相似的前K个数据 则该测试数据对应的类别就是K个数据中出现次数最多的那个分类 其算法的描述为:
1. 计算测试数据与各个训练数据之间的距离
2. 按照距离的递增关系进行排序
3. 选取距离最小的K个点
4. 确定前K个点所在类别的出现频率
5. 返回前K个点中出现频率最高的类别作为测试数据的预测分类
import numpy as np
import math
import operator
"""knn算法优化
:param dataSet 无量纲化
:func knn weight
:return 系统体系
other
:knn logistic regression
"""
def createDataSet():
group = np.array([[10, 9.2], [8.8, 7.9], [0.1, 1.4], [0.3, 3.5]])
labels = ['A', 'A', 'B', 'B']
return group, labels
def normDatafunc(dataSet):
print(dataSet)
print(np.max(dataSet))
print(np.min(dataSet))
dataMax = np.max(dataSet)
dataMin = np.min(dataSet)
dataRange = dataMax - dataMin
normData = (dataSet-dataMin)/dataRange
return dataRange, dataMin, dataMax, normData
def normTest(dataMin, dataRange, testSet):
test = (testSet-dataMin)/dataRange
return test
def gaussian(dist, a=1, b=0, c=0.3):
return a * np.math.e ** (-(dist - b) ** 2 / (2 * c ** 2))
def knnClassify(dataSet, Labels, testSet, k):
nrow = np.shape(dataSet)[0]
cdiff = np.tile(testSet, (nrow, 1)) - dataSet
sqdiff = cdiff ** 2
sumdiff = np.sum(sqdiff, axis=1)
dist = np.sqrt(sumdiff)
print('dist', dist)
weightDis = []
for i in dist:
weightDis.append(gaussian(i, a=1, b=0, c=0.3))
print('weightDis', weightDis)
weightDis = np.array(weightDis)
indexSorted = np.argsort(-weightDis)
print(indexSorted)
classCount = {}
for i in range(k):
vote = Labels[indexSorted[i]]
classCount[vote] = classCount.get(vote, 0) + 1
sortedLabel = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedLabel[0][0]
def main():
dataSet, Labels = createDataSet()
dataRange, dataMin, dataMax, normData = normDatafunc(dataSet)
testSet = [0.0, 0.0]
test = normTest(dataMin, dataRange, testSet)
k = 3
lis = {
'A': 'big',
'B': 'smaller'
}
print(lis)
result = knnClassify(normData, Labels, test, k)
print('result is:'+lis[result])
if __name__ == '__main__':
main()
KNN学习及补充
import math
"""KNN
一句话总计:近朱者赤 近墨者黑
input:
经过预处理的特征向量
对应于特征空间的点 --- 多个类
监督分析算法
分类时通过多数表决进行预测
k近邻算法--没有训练过程
--不具有显式的学程
基本要素:
k值的选择
距离度量
分类决策规则
案列:
爱情片和动作片分类
数学原理:
欧式距离
计算未知与已知之间的距离
相似度越高距离越小
相似度越低距离越大
k: 是自己设置的数
训练时间为0 计算时间很多
k值:
交叉验证优化
优缺点:
缺点:
k值小了 容易过拟合 分得过于细了
k值大了
可以避免过拟合
对最终结果可能有影响
缺点:
分类决策规则:
knn中求取分类最优近邻 是合理的
距离加权
距离近权重加大
距离远权重减小
# 学习误差:
# 估计误差: 模型估计值与实际之间的差距 训练
# 近似误差: 模型估值与实际差距 测试集
消除数据的量纲大小影响---做无量纲化优化
归一化:AutoNorm
将你需要处理的数据经过处理限制在一定条件范围内
方法:
1.线性函数转化[0, 1]
2.对数函数转化
3.反余切函数转化
4.输入值转为[-1, 1]
样本数据分解:
0.1 训练数据
0.9 测试数据
总体样本数据
用于回归:
k个近邻的平均值
"""
"""knn 距离加权的几种方式
1. 反函数
该方法最简单的形式是返回距离的倒数 完全一样或非常接近的商品权重为会很大
因此: 在距离求倒数时 在距离上加一个常量
比如距离D 权重为:1/D
weigh = 1/(distance + const)
缺点: 为近邻分配很大的权重 使得算法对噪声数据变得敏感
2.高斯函数(正态分布)
高斯函数在距离为0的时候权重为1,随着距离增大,权重减少,但不会变为0
计算加权knn
1.在处理离散型数据时,将这k个数据用权重区别对待,预测结果与第n个数据的label相同的概率
2.在处理数值型数据时,并不是对这k个数据简单的求平均,而是加权平均:通过将每一项的距离值乘以对应权重,让后将结果累加。求出总和后,在对其除以所有权重之和。
"""
def gaussian(dist, a=1, b=0, c=0.3):
return a * math.e ** (-(dist - b) ** 2 / (2 * c ** 2))
KNN预测算法
import numpy as np
import operator
def creatDataSet():
groups = np.array([[1, 1.1], [1, 0.99], [0.1, 0.02], [0.2, 0.1]])
labels = ['A', 'A', 'B', 'B']
return groups, labels
def classify(test, dataSet, labels, k):
dataSize = dataSet.shape[0]
diff = np.tile(test, (dataSize, 1)) - dataSet
stdDiff = diff ** 2
stdDis = np.sum(stdDiff, axis=1)
sortedIndex = np.argsort(stdDis)
classCount = {}
for n in range(k):
voteLabel = labels[sortedIndex[n]]
classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def test():
dataSet, labels = creatDataSet()
test = [0.9, 1]
result = knnLR(test, dataSet, labels, 2)
print(result)
def weight(dist, a=1, b=0, c=0.3):
return a * np.math.e ** (-(dist - b) ** 2 / (2 * c ** 2))
def knnLR(inX,dataset,labels,k):
dataset_size = dataset.shape[0]
diff_mat = np.tile(inX,(dataset_size,1))-dataset
sqdiff_mat = diff_mat**2
sq_distances = sqdiff_mat.sum(axis=1)
distances = sq_distances**0.5
print(distances, 'distances')
lis = []
for i in distances:
lis.append(weight(i, a=1, b=0, c=0.3))
print(lis, 'lis')
sorted_distances_index = distances.argsort()
knnpredict = int()
for i in range(k):
knnpredict += dataset[sorted_distances_index[i]] * lis[sorted_distances_index[i]]
knnpredict = knnpredict/k
return knnpredict
if __name__ == '__main__':
test()