k最近邻分类;matlab_贪心学院 机器学习特训营 第二课 K-NN最近邻 笔记及作业

本文详细介绍了K近邻(KNN)算法,包括其作为分类器和回归模型的使用。讲解了通过iris数据集进行KNN分类,K的选择对模型稳定性的影响,以及如何通过交叉验证选择最佳的K值。还讨论了特征缩放的重要性,如线性归一化和标准差标准化,并给出了二手车股价案例展示KNN在回归问题上的应用。最后,探讨了KNN的时间复杂度、处理高维数据的方法以及算法的其他延伸内容。
摘要由CSDN通过智能技术生成

李文哲老师详细的讲解了KNN模型,讲的非常详细,直播时因为内容多,额外占用了老师很多的时间,感谢李文哲老师辛苦的付出,感谢幕后做录制上传视频的老师和助教老师们。因为直播时内容太多,当时听的很多不明白,也不知问什么,这篇笔记是看回播写的。

老师介绍KNN是一个AI领域的 The "hello world" Algorithm ,类似于编程入门的经典hello world

KNN算法称:K-Nearest Neighbors

KNN算法即可以作为分类器也可以作为回归模型来使用,今天主要做分类器来演示

KNN是最容易理解的算法也是最容易实现的算法(自己写代码实现)

KNN使用最近的距离来为目标元素分类

KNN中K表示距离目标最近的K个元素,使用K个元素来投票确定K的分类(K为奇数,防止平手,当类别大于2时也会出现平手这种情况时无法避免平手,平手时可以随机返回或用特殊方法来处理避免平手)

K如何影响算法的行为?

通过经典的iris三分类示例讲解KNN的分类使用

# 读取相应的库
from sklearn import datasets #使用sklearn自带的数据
from sklearn.model_selection import train_test_split #把数据分成训练和测试数据集
from sklearn.neighbors import KNeighborsClassifier #从包中引入KNeighborsClassifier算法,包中会有其他的算法
import numpy as np

# 读取数据 X, y
iris = datasets.load_iris() #加载数据,可到UCI dataset上查看数据描述,这个数据集是一个三分类问题
X = iris.data #特征,矩阵类型:N*d N:samples 样本的个数 d:dimension 维度 
y = iris.target #label:标签 (这里是0,1,2),向量
print (X, y)

# 把数据分成训练数据和测试数据
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2003)#指定随机种子,抽取时使用,保证每次一致

# 构建KNN模型, K值为3、 并做训练
clf = KNeighborsClassifier(n_neighbors=3) #这个值就是K
clf.fit(X_train, y_train)  #训练 (KNN训练时没有训练的过程,只做了数据的内存分配)

# 计算准确率
from sklearn.metrics import accuracy_score
correct = np.count_nonzero((clf.predict(X_test)==y_test)==True)#准确率的计算
print ("Accuracy is: %.3f" %(correct/len(X_test)))#准确率的计算
#print(accuracy_score(y_test, clf.predict(X_test))) #这里是使用sklearn自定义的函数计算准确率

参数有两大类

  1. 模型参数:通过训练数据来学习的(KNN里面没有模型参数)
  2. 超参数:不属于模型的参数,模型外面的参数,指导模型训练(类似开关模型按超参数指定的开关进行训练,用不同的开关学习的模型是不一样的,KNN的超参数就是K,调优是调试超参数)

3b3bf633ebf768b17fd9824ae1a6ac05.png

欧式距离以及KNN实现

  • 实现KNN算法需要考虑的几大问题
    • 把一个物体表示成向量或矩阵(特征工程,使用特征描述物体,模型的第一步就是做特征工程,不同的业务需求使用或关注的特征不一样)
    • 标记号每个物体的标签(i.e., offer/no offer,KNN需要提前标记标签,很多图像问题使用人工打标记)
    • 计算两个物体之间的距离/相似度(最重要的问题,最简单的距离计算:欧式距离 )
    • 选择合适的K (KNN中最重要的话题,见后面)
  • 从零开始自己写一个KNN算法
from sklearn import datasets
from collections import Counter  # 为了做投票
from sklearn.model_selection import train_test_split
import numpy as np

# 导入iris数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2003)

#欧式距离计算,两维
def euc_dis(instance1, instance2):
    """
    计算两个样本instance1和instance2之间的欧式距离
    instance1: 第一个样本, array型
    instance2: 第二个样本, array型
    """
    # TODO
    dist = np.sqrt(sum((instance1 - instance2)**2))
    return dist
    
#knn核心函数 
def knn_classify(X, y, testInstance, k):
    """
    给定一个测试数据testInstance, 通过KNN算法来预测它的标签。 
    X: 训练数据的特征
    y: 训练数据的标签
    testInstance: 测试数据,这里假定一个测试数据 array型
    k: 选择多少个neighbors? 
    """
    # TODO  返回testInstance的预测标签 = {0,1,2}
    #时间复杂度:O(N)  N:样本个数
    distances = [euc_dis(x, testInstance) for x in X]
    #时间复杂度:O(NlogN) 优化:使用 priority queue(优先级队列)->O(NlogK)
    kneighbors = np.argsort(distances)[:k]
    count = Counter(y[kneighbors])
    print(count)#展示投票结果
    return count.most_common()[0][0] #选取出现次数最大的那一项

# 预测结果。    
predictions = [knn_classify(X_train, y_train, data, 3) for data in X_test]
correct = np.count_nonzero((predictions==y_test)==True)
#accuracy_score(y_test, clf.predict(X_test))
print ("Accuracy is: %.3f" %(correct/len(X_test)))
  • 选择合适的K

2d48ddc4acbeb212ba89636d5982282c.png

理解K对算法的影响,决策边界非常重要

76a00f1931a0887fee4edb61a5224d5f.png

41be0bd28ca0a9a5e31c01987ff4e45d.png

怎么寻找KNN的决策边界?随着K的增加,决策边界会越来越平滑。模型训练出的决策边界越陡峭,说明模型是不太稳定的;模型训练出的决策边界越平滑,有可能是好事,也有可能是模型的准确率不高,各有利弊。如何选K涉及到超参数的选择,交叉验证的过程可以计算出最好的K的值。可以看示例代码来学习

5dd5cf99f95d85f113597736ed76f793.png
决策边界可视化的方法

3958448146c0cdf312c4182474cfc082.png
示例代码中遍历1-19的K值决策边界图

TODO 明天后续学习


通过交叉验证选择K

问题:随着K值的增加,会怎么变化? 决策边界会变得平滑,稳定性很高, 但可能准确率会降低.需要做交叉验证(CrossValidation,也叫CV) ,通常我们也把它归类为"调参"

交叉验证,测试数据不能用来做训练,需要在训练数据拆分出验证数据

088616ca9250ed1bf155459adaadd8c5.png
交叉验证的数据选择

c25a54f00139b84aa97262b42bc3e069.png
使用5分之1的数据来做交叉验证---5折交叉验证

对K使用交叉验证遍历出准确率最高的K,这个K就是最终答案,这种交叉检验称之为K-fold Cross,这里的K指的是K折,与KNN的K无关.一般使用5或10,使用10比较多,也可以使用100或200. !!!千万不能用测试数据来调参!!! 数据量少的时候可以适当增加折数

4602749db4b8e22bc371e359b0337799.png

特征缩放(KNN核心之一)

欧式距离计算的时候如果量纲差异太大会让 数值小的特征权重会降低或失去作用,解决方案是:

1. 线性归一化(Min-max Normalization),把特征映射到 0-1 之间

a2f7cc2710999520217ff708040ffaac.png

2.标准差标准化(Z-score Normalization) ,把特征映射到 N(0,1) 的高斯分布

401a5cb41a3c0f1c81f0220203846b35.png

具体使用哪种?需要实际测试,哪个方法更好就使用哪个

二手车股价案例(KNN的回归使用)

KNN如何用在回归问题上?

266c9fa0a822a4eaab96f6bbe030bc3b.png

执行老师的例子

cbc88694cef961c16cda2e3ce6ef00e1.png

4a8c7fe145790e48233d0ae9e267bf9b.png

d2f5640ad710692a2b042098df329385.png

下面这张图片是老师在代码中间注释的一段,也执行看了一下

06d8be183053613e9a57ade1dac66dd6.png

fa5d85e7207d0210daa21c56bbe66435.png

3da980ef8748ee7e81b093c66d2104eb.png

KNN的延伸内容

1.时间的复杂度:KNN的时间复杂度很高,因为新的点需要与所有点计算距离,不适合实时系统

032e7601faedfb6dab6820abe9a285da.png

解决方案:

1) 使用KD-Tree 使用各个点来构建一颗树,让相邻的点落在同一个节点上(课后查看KD-Tree)

7fac6c65bb9aacd9356cb5f5ce944604.png
KD-Tree只能用在维度比较低的数据上,不能用在高维空间

2) 类似哈希算法– Locality Sensitivity Hashing (LSH) 可解决高纬度问题,但它是一个近似的算法,不是一个精确的算法; 不能保证最好,只是近似; 损失了精确率得到了快速搜索, LSH在搜索领域非常常见

cb2cbf253f4680023676330d9dc58e28.png

2.如何处理特征的相关性

5423b944914d1c48255edf1008bf8631.png
可以看看这个LMNN的算法

3.怎么处理样本的重要性

337038a49ff625d976753471b2b1996a.png
加权处理,使用Weighted KNN

4. 能不能利用Kernel Trick

887140ef1cc816ccf584bda4465b0d6a.png

总结

19ad503b1aa8919d1bdb79813ae8fce1.png

老师答疑的时候看到了自己的留言^_^

7bd3db54f4ba80699551abb7be5a9a1e.png

低纬空间里,KNN真的很好用,KNN可以作为搭建AI机器学习框架时的一个baseline的基准

同学提问:大类吞小类问题(数据的不平衡)

de0fbaf90e60ccd92bb74ef3f9fdca17.png

感谢李文哲老师多花费自己的时间来详细讲解KNN和KNN的延伸知识.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值