KNN总结

knn既能用于回归,也能用于分类,属于有监督算法的一种,但严格意义上并没有学习过程(最终是计算样本点之间的距离)。

knn分类的核心思想:每次在预测一个样本x时,通过k值确定与其最近的k个邻居,并依次算这几个邻居到样本x的距离,按从小到大排序然后根据最多数邻居的类别作为样本x的预测值。(回归的话是邻居的值做平均赋给样本x,但和分类的核心思想一致均为找出k近邻)

最关键的参数选取:k和距离

(1)k需要交叉验证来找到最合适的值。k值不能过大,过大虽然可以减小噪声,但样本太多导致类别界限不清晰;过小则预测错误概率变大,容易过拟合。

(2)距离:曼哈顿距离(p=1特例),欧氏距离(p=2特例)以及闵可夫斯基距离(p=n)

实现思路:

(1)给出训练集和测试集

(2)计算测试集中每一个数据和训练集中的数据的距离

(3)排序距离结果,找出前k个值

(4)统计k个值中最多出现的标签值作为预测标签

代码:

import math
from sklearn import neighbors
class knnClass(object):
    def __init__(self,k,p,train_dataset,test_data,train_dataset_labels,):
        self.k = k
        self.p = p
        self.train_dataset = train_dataset
        self.test_dataset = test_data
        self.train_dataset_labels = train_dataset_labels


    def knn_main(self):
        if self.p <= 0:
            return

        """计算距离"""
        distance = []
        for train_sample in self.train_dataset:
            dis = 0
            for vec in range(0,len(train_sample)):
                dis += math.pow((train_sample[vec] - self.test_dataset[vec]),self.p)
            dis = pow(dis,1/self.p)
            distance.append(dis)

        """计算最邻近的k个值"""
        index_list = []
        for i in range(0,self.k):
            index_i = distance.index(min(distance))
            index_list.append(index_i)
            distance[index_i] = float('inf')

        """取出最近邻k个值的索引并找到对应标签"""
        k_dis_label = []
        for j in index_list:
            k_dis_label.append(self.train_dataset_labels[j])

        """取出出现最多的标签"""
        predict_label = max(k_dis_label,key=k_dis_label.count)
        return predict_label

def train(k,train_data,test_data,train_data_labels):
    knn = neighbors.KNeighborsClassifier(n_neighbors=k,)
    knn.fit(train_data,train_data_labels)
    return knn.predict(test_data)

if __name__ == '__main__':
    train_data = [[2,9],[3,12],[6,15],[1,5],[2,7],[4,13],[18,6],[15,4],[11,8],[17,3],[12,11],[19,10],[8,19]]
    train_data_labels = [1,1,1,1,1,1,0,0,0,0,0,0,1]
    test_data = [[5,5]]
    test_data_label = 2
    knn_obj = knnClass(1,2,train_data,[5,5],train_data_labels)
    predict_label = knn_obj.knn_main()
    print(predict_label)

    print(train(1,train_data,test_data,train_data_labels))

优点:

1.可以用于非线性分类

2.训练时间复杂度比支持向量机之类的算法低(O(n),n为样本数)

3.和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感

4. 天然适合多分类

5.由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属的类别,因此对于类域的交叉或重叠较多的待分类样本集来说,KNN方法较其他方法更为适合

缺点:

1.计算量大,尤其在特征数非常多的时候(维数灾难);另外,树之类的模型建立需要大量的内存

2.不能很好的解决数据不平衡问题

3.慵懒学习方法,几乎不学习,预测时速度比起逻辑回归之类的算法慢

4.依赖训练数据,如果数据依赖性过大无法准确分类(如距离太近)

优化的考虑:

(1)k值

(2)距离

(3)暴力计算、KD树等

(4)邻居加权

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值