KNN K近邻算法学习

KNN算法、k-nearest neighbor,或者K-近邻算法是一种经典的机器学习算法,可以完成分类和回归任务。
KNN算法主要思想
对于输入的特征X,选取与他记录最近的K个点,统计这K个点所属类别,X属于最多的一类。

KNN参数
通过上面的算法思想,可以知道,我们需要确定超参数K的数量和距离度量的表示

1、超参数K
k的取值非常重要,如果k的取值国小,一旦原数据分布有噪声的存在,那么会对最终预测结果产生影响,产生偏差。如果k的取值较大,就意味着用较多的样本进行预测,训练误差会增大,即使是较远的点也会对结果产生影响,也可以理解为模型变得简单了

2、度量方式
(1)欧式距离
欧氏距离是一种常用的距离测量方式,也就是我们初中时候学的求两点之间的距离公式,只是这里扩充到多维度。
在这里插入图片描述
(2)曼哈顿距离
曼哈顿距离是相应维度做差取绝对值,再对各个维度求和
在这里插入图片描述
(3)还有一些其他的距离度量方式比如:马氏距离、切比雪夫距离、明可夫斯基距离等

算法缺点

  1. 如果样本类别不均衡,数量差距较大,预测结果可能会偏向于样本量较大的一类;
  2. 计算耗时较长

代码实现
代码部分主要参考:这个博客https://blog.csdn.net/pengjunlee/article/details/82713047
主要有两种方式
1 利用sklearn库封装好的算法,导入使用
2 手动实现

sklearn实现

# 导入画图工具
import matplotlib.pyplot as plt
# 导入数组工具
import numpy as np
# 导入数据集生成器
from sklearn.datasets import make_blobs
# 导入KNN 分类器
from sklearn.neighbors import KNeighborsClassifier
# 导入数据集拆分工具
from sklearn.model_selection import train_test_split
 
# 生成样本数为200,分类数为2的数据集
data=make_blobs(n_samples=200, n_features=2,centers=2, cluster_std=1.0, random_state=8)
X,Y=data
 
# 将生成的数据集进行可视化
# plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
# plt.show()
 
clf = KNeighborsClassifier()
clf.fit(X,Y)
 
# 绘制图形
x_min,x_max=X[:,0].min()-1,X[:,0].max()+1
y_min,y_max=X[:,1].min()-1,X[:,1].max()+1
xx,yy=np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
z=clf.predict(np.c_[xx.ravel(),yy.ravel()])
 
z=z.reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap=plt.cm.Pastel1)
plt.scatter(X[:,0], X[:,1],s=80, c=Y,  cmap=plt.cm.spring, edgecolors='k')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:KNN")
 
# 把待分类的数据点用五星表示出来
plt.scatter(6.75,4.82,marker='*',c='red',s=200)
 
# 对待分类的数据点的分类进行判断
res = clf.predict([[6.75,4.82]])
plt.text(6.9,4.5,'Classification flag: '+str(res))
 
plt.show()

进行数据预测
注意这里输入的数要用中括号包裹起来,就是说输入的时候尺度要对应

#进行预测
Y_predict = clf.predict([[4,5]])
Y_predict

手动实现
算法的定义

# 计算欧氏距离 
def euclideanDistance(instance1, instance2, length):
    distance = 0
    for x in range(length):
        distance += pow((instance1[x] - instance2[x]), 2)
    return math.sqrt(distance)
 
# 选取距离最近的K个实例
def getNeighbors(trainingSet, testInstance, k):
    distances = []
    length = len(testInstance) - 1
    for x in range(len(trainingSet)):
        dist = euclideanDistance(testInstance, trainingSet[x], length)
        distances.append((trainingSet[x], dist))
    distances.sort(key=operator.itemgetter(1))
    
    neighbors = []
    for x in range(k):
        neighbors.append(distances[x][0])
    return neighbors
 
#  获取距离最近的K个实例中占比例较大的分类
def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True)
    return sortedVotes[0][0]
 
# 计算准确率
def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(testSet))) * 100.0
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值