knn

KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别。
knn三要素
训练集少且种类少的时候算法有效,训练集大的时候要使用KD树和球树的方法建立模型。
距离度量
距离衡量的方法有多种,目的都是搜索最近邻,最常用的是欧氏距离。
k值的选择
k值决定了最后确定类别时所参考的样本数量,k值过大则训练误差增大,选取的临近点中包含错误种类的可能性增大,导致结果不准确;k值过小则泛化误差增大,模型容易受到噪声干扰,容易过度拟合。因此k值的选取非常重要,一般先选取一个很小的值,再使用交叉检验确定最优的k值,一般都低于训练样本的平方根。
分类决策规则
1.多数表决法
多数表决法类似于投票的过程,也就是在 K 个邻居中选择类别最多的种类作为测试样本的类别。
2.加权表决法
根据距离的远近,对近邻的投票进行加权,距离越近则权重越大,通过权重计算结果最大值的类为测试样本的类别。
看的资料里面都是关于下面这道题在这里插入图片描述如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。
如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。
然后就是关于距离运算公式,如在这里插入图片描述
然后就是步骤:
就是找个随便分为几部分给定k值,根据求出的距离选定距离最近的k个样本`"""
“”"

import numpy as np
from matplotlib import pyplot as plt

#计算距离公式
def d_man(x, y):
d = np.sum(np.abs(x - y))#曼哈顿距离公式
return d
def d_euc(x, y):
d = np.sqrt(np.sum(np.square(x - y)))#欧式距离公式
return d

#sorted函数按照key值进行排序,key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较
#reverse参数接受False 或者True 表示是否逆序;class_count.items()返回可遍历的(键, 值) 元组数组。
import operator
def majority_voting(class_count):
sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)#itemgetter(a)获得第_a_个值,默认从小到大
return sorted_class_count

#生成示例数据
def create_data():
features = np.array(
[[2.88, 3.05], [3.1, 2.45], [3.05, 2.8], [2.9, 2.7], [2.75, 3.4],
[3.23, 2.9], [3.2, 3.75], [3.5, 2.9], [3.65, 3.6], [3.35, 3.3]]) #np.array构建二维数组且无需指针
labels = [‘A’, ‘A’, ‘A’, ‘A’, ‘A’, ‘B’, ‘B’, ‘B’, ‘B’, ‘B’]
return features, labels #返回features,labels

def knn_classify(test_data, train_data, labels, k):
distances = np.array([]) # 创建一个空的数组存放距离

for each_data in train_data:  # 使用欧式距离计算数据相似度
    d = d_euc(test_data, each_data)
    distances = np.append(distances, d)      #append() 用于在列表末尾添加新的对象。
print(f"距离相似度distances={distances}")
sorted_distance_index = distances.argsort()  # 获取按距离大小排序后的索引(argsort提取索引)
sorted_distance = np.sort(distances)    
print(f"查看sorted_distance_index{sorted_distance_index}")
print(f"查看sorted_distance{sorted_distance}")
r = (sorted_distance[k]+sorted_distance[k-1])/2  # 计算圆的半径

#选择距离最近的k个值
class_count = {}   
for i in range(k):  
    vote_label = labels[sorted_distance_index[i]]  #根据索引找到距离对应的类别
    class_count[vote_label] = class_count.get(vote_label, 0) + 1   
#排序
final_label = majority_voting(class_count)
return final_label, r            #返回值

#生成训练样本
features, labels =create_data()
test_data = np.array([3.18, 3.15])
final_label, r = knn_classify(test_data, features, labels, 5)
print(final_label)
print®

#可视化

#极坐标方式表示圆
def circle(r, a, b): # 为了画出圆,这里采用极坐标的方式对圆进行表示 :x=rcosθ,y=rsinθ。
theta = np.arange(0, 2*np.pi, 0.01)
x = a+r * np.cos(theta)
y = b+r * np.sin(theta)
return x, y

k_circle_x, k_circle_y = circle(r, 3.18, 3.15)

plt.figure(figsize=(5, 5))
plt.xlim((2.4, 3.8)) #x轴范围
plt.ylim((2.4, 3.8)) #y轴范围
x_feature = list(map(lambda x: x[0], features)) # 返回每个数据的x特征值
y_feature = list(map(lambda y: y[1], features))
plt.scatter(x_feature[:5], y_feature[:5], c=“b”) # 在画布上绘画出"A"类标签的数据点
plt.scatter(x_feature[5:], y_feature[5:], c=“g”)
plt.scatter([3.18], [3.15], c=“r”, marker=“x”) # 待测试点的坐标为 [3.18,3.15]
plt.plot(k_circle_x, k_circle_y)
`

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值