MATLAB计算K近邻

在实验中经常会需要计算K近邻,为了避免多次重写,这里用MATLAB实现了一个计算K近邻的函数,该函数要求输入两个参数,第一个参数就是数据矩阵,要求每行为一个多维样本点,第二个参数就是K值了。函数返回K近邻矩阵。计算K近邻比较好的一种算法是利用KD树,这里暂且用的是易于理解的常规方法。使用KD树的代码将来补充。

具体代码实现如下

function [ Result ] = KNN( Data,k )
%计算K近邻的一个通用函数
%要求一行为一个多维变量
%返回Result为一个矩阵,第i行为到第i个数据点的欧几里得距离最短的k个数据点序号的排列,列序数越小距离越近
%计算KNN用KD树要更好一点,这个第一版暂时先用普通方法了

datasize = size(Data);
Distance = zeros(datasize(1),datasize(1));%距离矩阵,存放两点之间的距离

%%%%
 % 计算距离矩阵
 %
%%%%
for i = 1:datasize(1)-1    
    for j = i+1:datasize(1)
        tempsum = 0;
        for ci = 1:datasize(2)
            tempsum = tempsum + (Data(i,ci)-Data(j,ci))*(Data(i,ci)-Data(j,ci));
        end
        Distance(i,j) = sqrt(tempsum);
        Distance(j,i) = sqrt(tempsum);
    end    
end

Result = zeros(datasize(1),k);%结果矩阵
%%%%
 % 计算结果矩阵
 %
%%%%
for i = 1:datasize(1)
    
    for j = 1:datasize(1)
        
        if i==j
            continue;
        end
        
        index = k;
        while index>0 && Result(i,index)==0
            index = index-1;
        end       
        if index == 0
            Result(i,1) = j;
        else
            if Distance(i,j)<Distance(i,Result(i,index))
                while index>0 && Distance(i,j)<Distance(i,Result(i,index))
                    temp = Result(i,index);
                    Result(i,index) = j;
                    if index<k
                        Result(i,index+1) = temp;
                    end
                    index = index-1;
                end
            else
                if index<k
                    Result(i,index+1) = j;
                end
            end
        end
             
    end
        
end



end

使用的测试代码如下所示

clc,clear
load('Wine.mat')
Data = Wine(:,2:14);
Result = KNN(Data,10)

计算结果如下所示


测试使用的是加州大学欧文分校的机器学习测试数据集中的Wine数据集,下载地址是http://archive.ics.uci.edu/ml/datasets/Wine ,也可以从百度网盘链接链接:https://pan.baidu.com/s/1jKowB8E 密码:xift下载MATLAB的mat文件。

另外上面的测试方法其实是不太好的,最好是先将数据normlize一下。

计算一个向量v在数据集矩阵Data中的K近邻代码:

function [ Result ] = vKNN( v,Data,k )
% 对一个向量量v计算它在Data中的k近邻
% v是那个向量,Data是数据集矩阵,k为近邻数
% 要求向量是一个行向量

datasize = size(Data);
Result = zeros(1,k);%结果向量
Distance = zeros(datasize(1),1);%距离矩阵

%距离矩阵计算
for i = 1:datasize(1)
    tempsum = 0;
    for j = 1:datasize(2)
        tempsum = tempsum + (Data(i,j)-v(j))*(Data(i,j)-v(j));
    end
    Distance(i) = sqrt(tempsum);
end

for j = 1:datasize(1)
        
        index = k;
        while index>0 && Result(index)==0
            index = index-1;
        end       
        if index == 0
            Result(1) = j;
        else
            if Distance(j)<Distance(Result(index))
                while index>0 && Distance(j)<Distance(Result(index))
                    temp = Result(index);
                    Result(index) = j;
                    if index<k
                        Result(index+1) = temp;
                    end
                    index = index-1;
                end
            else
                if index<k
                    Result(index+1) = j;
                end
            end
        end
             
end


end

其实已经有一些人开发了一些在MATLAB中计算K近邻的工具箱,VLFeat就是一个例子,它实现了kmeans,KDTree等多种算法。其下载地址为http://www.vlfeat.org/download.html ,下载完成之后解压,在MATLAB命令行中运行其中的toolbox文件夹下的vl_setup.m即可完成该工具箱的配置,在MATLAB命令行中输入vl_version verbose,,命令如果结果显示类似下图,证明配置成功。


下面是一个使用VLFeat求K近邻的一个例子

clc,clear

X = rand(2,100);%一百个二维列向量
kdtree = vl_kdtreebuild(X);%构建kd树

Q = rand(2,1);
[index,distance] = vl_kdtreequery(kdtree, X, Q);%返回X中与Q最近的点

[index, distance] = vl_kdtreequery(kdtree, X, Q, 'NumNeighbors', 10) ;%返回X中Q的K的近邻

scatter(Q(1),Q(2),'p')
hold on

for i = 1:100
    has = 0;
    for j = 1:10
        if index(j)==i
            has = 1;
            break;
        end
    end
    
    if has==1
        scatter(X(1,i),X(2,i),'o')
        hold on
    else
        scatter(X(1,i),X(2,i),'.')
        hold on
    end
        
    
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值