一、KNN算法的核心思想:寻找最近的k个数据,推测新数据的分类
二、KNN算法的原理:
- 计算测量数据与各个训练数据之间的距离;
- 按照距离的递增关系进行排序;
- 选取前k个距离最小的点;
- 对这前k个点距离取加权平均数;
三、计算距离量度方式包括:
样本空间内的两个点之间的距离量度表示两个样本点之间的相似程度:距离越短,表示相似程度越高;反之,相似程度越低。量度空间中点的距离,有好几种量度方式,比如常见的曼哈顿距离计算,欧式距离计算等等。不过通常KNN算法中使用的是欧式距离,不用曼哈顿距离。
曼哈顿距离只计算水平或垂直距离,有维度的限制。
欧式距离可用于任何空间的距离计算问题。
样本空间内的数据点可以存在于任何空间,欧氏距离是更可行的选择。
四、k的选取:
- k太大:导致分类模糊
- k太小:受个例影响,波动较大
- 在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的方差,最终找到一个比较合适的K值。
- 一般也要选择K的值应该尽量选择为奇数,并且不要是分类结果的偶数倍,否则会出现同票的情况。
五、应用——癌症数据模拟:
import random
import csv
#读取
with open('F:\python_jqxx\knn\Prostate_Cancer.csv','r') as file:
# 以字典的形式读取文件
reader = csv.DictReader(file)
#放入list中
datas = [row for row in reader]
#分组
#打乱顺序
random.shuffle(datas)
#训练集
n = len(datas)//3
train_set = datas[n:]
#测试集
test_set = datas[0:n]
#knn
#距离(欧氏距离)
def distance(d1,d2):
res = 0;
for key in ("radius", "texture", "perimeter",
"area", "smoothness", "compactness", "symmetry", "fractal_dimension"):
#平方
res += (float(d1[key]) - float(d2[key]))**2
#开方
return res**0.5
k = 3
def knn(data):
#距离
res=[
{"result":train['diagnosis_result'],"distance":distance(data,train)}
for train in train_set
]
#res = [{'result': 'M', 'distance': 138.97843884214558}, {'result': 'M', 'distance': 264.20447461767185}...]
#升序排序
res = sorted(res,key = lambda item:item['distance'])
#取前k个
res2 = res[0:k]
#加权平均
result = {'B':0,'M':0}
#总距离
sum = 0
for r in res2:
sum += r['distance']
for r in res2:
#加权
result[r['result']] += 1 - r['distance']/sum
if result['B'] > result['M']:
return 'B'
else:
return 'M'
#测试阶段
correct = 0
for test in test_set:
result = test['diagnosis_result']
result2 = knn(test)
if result == result2:
correct = correct + 1;
print("准确率:{:.2f}%".format(correct*100/len(test_set)))
结果:
六、KNN算法的优缺点:
优点
1、KNN可以处理分类问题,同时天然可以处理多分类问题,比如鸢尾花的分类
2、简单,易懂,同时也很强大,对于手写数字的识别,鸢尾花这一类问题来说,准确率很高
3、KNN还可以处理回归问题,也就是预测
缺点
1、效率低,因为每一次分类或者回归,都要把训练数据和测试数据都算一遍,如果数据量很大的话,需要的算力会很惊人
2、对训练数据依赖度特别大,虽然所有机器学习的算法对数据的依赖度很高,但是KNN尤其严重,因为如果我们的训练数据集中,有一两个数据是错误的,刚刚好又在我们需要分类的数值的旁边,这样就会直接导致预测的数据的不准确,对训练数据的容错性太差
3、维数灾难,KNN算法对于多维度的数据处理也不是很好
七、KNN算法的时间复杂度:
KNN算法的时间复杂度为O(D*N*N)。其中D为维度数,N为样本总数。从时间复杂度上我们可以很清楚的就知道KNN非常不适合高维度的数据集,容易发生维度爆炸的情况。