KNN(K-最近邻法) —matlab 和 python 学习记录

本系列文章是自己学习过程中的记录,如果有错误,欢迎各位交流指正。

基本思想: 输入无标签的数据,首先提取新特征,并与测试集中的每一个数据进行比较,然后从样本中提取k个最近邻(最相似)数据特征的分类标签, 统计这K个最近邻数据中出现次数最多的分类,将其作为新数据的类别。
伪代码:(对未知类别属性的数据集中的每个点执行以下操作)
(1)计算已知类别数据集中的点与当前点之间的距离。
(2)按照距离递增排序
(3)选取与当前距离最近的k个点
(4)确定前k个点所在类别出现的频率
(5)返回前k个点出现频率最高的类别作为当前点的预测分类
注:
在样本有限的情况下,KNN算法的误判概率和距离的具体测量有直接关系。通常常用: 欧式距离、马氏距离、曼哈顿距离等。其中欧式距离(二范数)最常用。

matlab代码:

% trainData 训练样本  n*p  (n:个数 p: 维数)
% trainLabel 训练标签 n*1
% testData 测试样本 m*p 
function target = KNN(trainData, trainlabel, testData, k)
classlabel = unique(trainlabel) % 得到样本标签(有哪几种标签)
c = length(classlabel) % 得到标签个数(共几类标签)
n = size(trainData,1) %得到训练样本个数
dist = zeros(n,1) % 存储 一个测试样本与所有训练样本的距离
for j=1:size(testData,1) % 遍历测试集中的每一个样本
    cnt = zeros(c,1) % 存储前k个点所在类别出现的频率(个数)
    for i=1:n % 遍历训练集中的每一个点
        dist(i)=norm(trainData(i,:)-testData(j,:)) %计算一个测试点与所有训练数据距离。
    end
    [d,index] = sort(dist) % 递增排序 d:排序过后的值 index 为d中相对应值在原dist中的索引 
    for i=1:K
        ind = find(classlabel == trainlabel(index(i))) %返回前k个点所在类别对应的标签 返回的ind值为{1,2,.... c}里面的 ** find的用法后面会提及。
        cnt[ind] = cnt[ind]+1 % 标签出现一次 相对应的cnt位置加1.相当于计算前k个点所在类别出现的频率
    end
    [m,ind] = max(cnt) %返回前k个点出现频率最高的类别。 m为最大值,ind为最大值在cnt中对应的索引位置
    target(j) = classlabel(ind) % 返回最终标签
end     

注 find()的用法:
find()的示例:

find()返回的是位置索引。

python 代码
KNN算法: 存在一个样本数据集合(训练样本集),并且每个数据都有标签。输入测试数据后(无标签的新数据)将新数据的每个特征与样本中数据对应的特征进行比较,然后算法提取样本集 中 特征最相似(近邻)的分类标签。一般来说,我们只选择样本数据集 中 前K个最相似数据。

  1. 使用python导入数据
from numpy import * # 导入numpy模块(科学计算包 矩阵运算)
import operator # 导入运算符模块
def creatDataset(): #定义一个函数 生成数据  4个样本 2类 
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #注意格式
    labels = ['A','A','B','B']
    return group, labels

这里有4组数据,每组数据有两个我们已知的属性或特征。
2. 实施KNN算法
根据上面的伪代码来解释每行代码的含义。

def classify(testdata, traindata, labels, k):
    [m,n] = traindata.shape #等价于 m=traindata.shape[0] 获得行数
                            #      n=traindata.shape[1] 列数
    # (1)计算距离  欧式距离(第1步)
    diffMat = tile(testdata,(m,1))-traindata # tile()相当于matla中的 repmat函数,将testdata重组为 m行1列。
    sqdiffMat = diffMat**2  # **表示次方 
    sqdistance = sqdiffMat.sum(axis=1)  # axis=0, 表示按列加。axis=1, 表示按行加行
    distance = sqdistance**0.5 
    sorteddistance = distance.argsort() #返回排序后的索引 (第2步)
    classcount={}#创建一个字典用来存储类别出现的频率
    for i in range(k):# 第三步选前k个点对应的label
        votelabel = labels[sorteddistance[i]]
        classcount[votelabel] = classcount.get(votelabel,0)+1 # 第4步
        #get(ith_label,0) : if dictionary 'vote' exist key 'ith_label', return vote[ith_label]; else return 0
    sortedclasscount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=True)  #reverse=True 从大到小排列
    return sortedclasscount[0][0]


(a) python二维数组:
这里写图片描述

(b) 欧式距离: 计算两个向量点xA和xB之间的距离
(xA0xB0)2+(xA1xB1)2

(c) numpy.sort() 函数
Returns the indices that would sort an array. 返回数组排序后的index(索引) 索引从0开始

这里写图片描述
结果:
这里写图片描述

(d) 字典的get()函数 get(ith_label,0) :
if dictionary ‘vote’ exist key ‘ith_label’, return vote[ith_label]; else return 0
如果字典vote存在ith_label 键 则返回 vote[ith_label]的值 否则返回 0
这里写图片描述

(e) iteritems() 用于返回本身字典列表操作后的迭代
在3.x 里 用 items()替换iteritems() ,可以用于 for 来循环遍历。

(f) 这里写图片描述

(g) key=operator.itemgetter(1) 等价于 lambda x: x[1]
operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号) 要注意,operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。
这里写图片描述

(h) sortedclasscount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=True) 分析

classcount 是一个字典 如 {‘A’:1, ‘B’:2}
item() 返回元组对列表 如 [(‘A’,1), (‘B’,2)]
key=operator.itemgetter(1) 返回一个函数。在这里 就是以元组里面索引是1的元素排序。即按照数字1,2 排序
最终返回 [(‘B’,2),(‘A’,1)]
sortedclasscount[0][0] 先取出 list的第一个元素 (‘B’,2) 再取出元组的第一个元素‘B’. 为最终标签

Python中实现K-最近邻(K-Nearest Neighbors, KNN)算是一种基于实例的学习,用于分类和回归问题。下面是简单的步骤: 1. **导入库**: 首先,你需要导入必要的库,如`numpy`, `pandas`, 和`scikit-learn`,它们分别用于数据处理、数据分析以及KNN。 ```python import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier ``` 2. **数据预处理**: 加载数据集,通常包含特征和标签。例如,使用`load_iris`或`load_digits`等函数从`sklearn.datasets`模块加载示例数据。 ```python from sklearn.datasets import load_iris data = load_iris() X = data.data y = data.target ``` 3. **拆分数据**: 将数据分为训练集和测试集,以便评估模型性能。 ```python X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) ``` 4. **创建并训练模型**: 创建一个`KNeighborsClassifier`对象,并指定k值(通常是奇数,比如5或7)。然后使用训练数据拟合模型。 ```python knn = KNeighborsClassifier(n_neighbors=5) knn.fit(X_train, y_train) ``` 5. **预测**: 对测试集进行预测,并得到预测结果。 ```python predictions = knn.predict(X_test) ``` 6. **评估模型**: 可以使用各种指标来评估模型性能,如准确率、精确度、召回率等。 ```python from sklearn.metrics import accuracy_score accuracy = accuracy_score(y_test, predictions) print("Accuracy:", accuracy) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值