KNN

KNN(K-NearestNeighbor)

一.K近邻算法的基本概念,原理

K近邻算法是一种基本分类和回归方法

即给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中,(类似于现实生活中少数服从多数的意思)

二.特征归一化

  1. 距离的度量
    L p ( x i , x j ) = ( ∑ = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p L_p(x_i,x_j)=(\sum_{=1}^n|x_i^{(l)}-x_j^{(l)}|^p)^\frac{1}{p} Lp(xi,xj)=(=1nxi(l)xj(l)p)p1

    1. 当p=2时,为欧氏距离(Euclidean distance),即

    L 2 ( x i , y i ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ 2 ) 1 2 L_2(x_i,y_i)=(\sum_{l=1}^n|x_i^{(l)}-x_j^{(l)}|^2)^{\frac{1}{2}} L2(xi,yi)=(l=1nxi(l)xj(l)2)21

    ​ (公式中的l表示的应该是表示第几个样本)

    1. 当p=1时,为曼哈顿距离(Manhattan distance),即

    L 1 ( x i , x j ) = ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ L_1(x_i,x_j)=\sum_{l=1}^n|x_i^{(l)}-x_j^{(l)}| L1(xi,xj)=l=1nxi(l)xj(l)

    其中当p=2的时候,就是我们常见的欧式距离,一般都用欧氏距离来衡量我们高维空间中两点的距离

  2. 特征归一化的必要性

    eg:用一个人的身高(cm)和脚码大小来作为特征值,类别为男性、女性,首先有5个训练样本,如下:

    A [(179,42),男] B [(178,43),男] C [(165,36)女] D [(177,42),男] E [(160,35),女]
    

    通过以上样本可以得出,***第一维身高特征是第二维脚码特征的4倍左右,那么在进行距离度量的时候,我们就会偏向于第一维特征,***这样就会造成两个特征不是等价重要,最终可能会导致距离计算错误,从而导致预测错误。

    举例证明:

    给个预测样本F (167,43),来预测是男性还是女性,采取k=3

    用欧式距离分别算出F离训练样本的欧式距离,然后选组最近的3个,以少数服从多数的原则选取预测结果,计算如下:
    A F = ( 167 − 179 ) 2 + ( 43 − 42 ) 2 = 145 B F = ( 167 − 178 ) 2 + ( 43 − 43 ) 2 = 121 C F = ( 167 − 165 ) 2 + ( 43 − 36 ) 2 = 53 D F = ( 167 − 177 ) 2 + ( 43 − 42 ) 2 = 101 E F = ( 167 − 160 ) 2 + ( 43 − 35 ) 2 = 103 AF = \sqrt{(167-179)^2+(43-42)^2} = \sqrt{145} \\ BF = \sqrt{(167-178)^2+(43-43)^2} = \sqrt{121} \\ CF = \sqrt{(167-165)^2+(43-36)^2} = \sqrt{53} \\ DF = \sqrt{(167-177)^2+(43-42)^2} = \sqrt{101} \\ EF = \sqrt{(167-160)^2+(43-35)^2} = \sqrt{103} \\ AF=(167179)2+(4342)2 =145 BF=(167178)2+(4343)2 =121 CF=(167165)2+(4336)2 =53 DF=(167177)2+(4342)2 =101 EF=(167160)2+(4335)2 =103
    由计算结果得出,最近的三个样本分别是C、D、E,那么可以得到预测结果为女性

    但是,一个女性的脚是43码的概率远远小于男性,但预测结果却是女性。这是因为各个特征的量纲不同,在这里导致了身高的重要性远远大于脚码了,这是不客观的。所以,我们应该在这里让每个特征同等重要,这也是需要归一化的原因!!!

    感谢大佬

  3. 去量纲,方法如下:

    1. 线性归一化(Min-Max-Normalization):一般情况下Min=0,Max=1
      x n e w = x − m i n ( x ) m a x ( x ) − m i n ( x ) x_{new}=\frac{x-min(x)}{max(x)-min(x)} xnew=max(x)min(x)xmin(x)

    2. 标准差标准化(Z-Score-Normalization):其中mean(x)为平均值,std(x)为标准差
      x n e w = x − m e a n ( x ) s t d ( x ) x_{new}=\frac{x-mean(x)}{std(x)} xnew=std(x)xmean(x)

三.底层算法

class KNN:
    def __init__(self,x_train,y_train,n_neighbors = 3,p = 2):
        self.n = n_neighbors
        self.p = p
        self.x_train = x_train
        self.y_train = y_train
        
    def predict(self, X):
        #X:要预测的样本点的特征
        knn_list = []
        #K个邻居,【(X和x_train第一个样本点的距离,y_train:第一个样本点的标签)】
        for i in range(self.n):
            dist = np.linalg.norm(X - self.x_train[i],ord = self.p)
            #dist :返回X和样本点的距离
            knn_list.append((dist,y_train[i]))
            #将结果存入knn_list
        
        for i in range(self.n,len(self.x_train)):
            #从第四(k)个点开始迭代
            max_index = knn_list.index(max(knn_list , key = lambda x:x[0]))
            #返回原本knn_list的最大dist的索引
            dist = np.linalg.norm(X - self.x_train[i],ord = self.p)
            #计算X和第4(k)个点的距离
            if knn_list[max_index][0]>dist:
                knn_list[max_index] = (dist,self.y_train[i])
            #如果原本的点的距离大于新点的距离,那么,我们就把新点的距离和标签,替换到knn_list里面。
                
                
        knn = [k[-1] for k in knn_list]
        #knn 返回,原本knn_list里的所有标签
        count_pairs = Counter(knn)
        max_count = sorted(count_pairs.items() ,key = lambda x:x[1])[-1][0]
        #计算所有标签的频数,并返回频数最大的标签
        return max_count
    
    def score(self,x_test,y_test):
        #记录预测正确的样本数/总xtest的样本个数=准确率
        right_count = 0
        for x,y in zip(x_test,y_test):
            label = self.predict(x)
            if label == y:
                right_count += 1 
        return right_count/ len(x_test)

四.KNN类的方法说明

  1. fit():训练函数,接收参数有两个,训练集特征X和训练集标签y

  2. predict():预测函数,输入参数为测试集特征X

  3. predict_prob:也是预测函数,只不过输出的是基于概率的预测

  4. score():打分函数,接收参数有三个

    1. X:接收输入的数组类型测试样本,一般是二维样本,每一行是一个样本,每一列是一个属性

    2. y:X这些预测样本的真实标签,一维数组或者二维数组

    3. samples_weight=None,是一个和X第一位一样长的个样本对准确率影响的权重,一般默认为None,输出为一个float型数,表示准确率,一般不用写。

      内部计算是按照predict()函数计算的结果记性计算的。其实该函数并不是KNeighborsClassifier这个类的方法,而是 它的父类KNeighborsMixin继承下来的方法

五.分类

测试
# 导入划分数据集的包
from sklearn.model_selection import train_test_split

# 划分数据集:分别为特征-(训练集、测试集),标签-(训练集、测试集),测试集占比为n
xtrain,xtest,ytrain,ytest = train_test_split(X,y,test_size=n)
# X -> 拿来进行训练的特征量,
# y -> 根据X得出的标签
调包KNN(K近邻)
# 导入sklearn中的KNN类
from sklearn.neighbors import KNeighborsClassifier

# 实例化KNN
knn= KNeighborsClassifier(
		n_neighbors=5,
		weights='uniform',
		algorithm='auto',
		leaf_size=30,
		p=2,
		metric='minkowski',
		metric_params=None,
		n_jobs=None,
)
"""
参数解释
n_neighbors:指定以最近的几个最近邻样本具有投票权,默认参数为5
weights:每个拥有投票权的样本是按什么比重投票,'uniform'表示等比重,'distance'表示按距离反比
algorithm:即内部采用什么算法实现
		  'ball_tree':球树、'kd_tree':kd数、'brute':暴力搜索、'auto':自动根据数据的类型		  和结构选择合适的算法。
left_size:给出kd_tree或者ball_tree叶节点规模
p:p=2为欧氏距离,p=1为曼哈顿距离,默认为2
metric:距离度量对象,即怎样度量距离,默认为闵氏距离
metric_params:距离度量函数的额外关键字参数,一般不用管
n_jobs:指并行计算的线程数量,默认为1表示一个线程,为-1表示cpu的内核数,如果不是很追求速度的话就不用管
"""
# 将KNN用fit方法传入参数
knn.fit(xtrain,ytrain)

# 用训练集预测准确率
knn.score(xtest,ytest)

# 训练集预测结果
y_hat = knn.predict(xtest)

# 取出预测错误的点
error = xtest[(ytest != y_hat)]

六.回归

测试在上面已经写过,所以这里直接调包进行回归

# 调包
from sklearn.neighbors import KNeighborsRegressor

# 在这里可以直接将KNN实例化后使用fit方法
knn = KNeighborsRegressor.fit(xtrain,ytrain)

# data 表示你需要预测的数据
knn.predict([data])

knn.score(xtest,ytest)

# 计算均方误差、平均绝对误差回归损失
from sklearn.metrics import mean_squared_error,mean_absolute_error

mse = mean_squared_error(ytest,y_pred=knn.predict(xtest))
mae = mean_absolute_error(ytest,y_pred=knn.predict(xtest))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值