k近邻分类器

  K近邻分类器是机器识别中很常用的一种分类方法,以前在做单样本人脸识别的时候常用的最近邻分类方法就是其中k=1的特殊情况。以前都是用matlab写的代码,最近老师动员大家一起来学python,然后我们就都从K近邻算法开始学习编程了。

K近邻算法

  该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。其实也很好理解,就是现在有n个训练样本,分别对应c个类,现在有一个未知的测试样本,要找到这个测试样本的类别。K近邻的方法就是计算出每个训练样本和测试样本的距离,找到其中最近的K个样本对应的类别,并统计每个类出现的次数,出现的最多的类即使该测试样本对应的类。

Python代码

  这个代码就是随便写写了,我只用了欧氏距离。其实python有自带的KNN的函数,所以还是推荐大家直接调用函数吧。代码若有错误望指正。

    def knn(trn,label,x,k):
    import numpy as np
    dist=np.zeros(numsamples)
    for i in range(numsamples):
        dist[i] = np.sqrt(np.sum(np.square(trn[i] - x)))
    print (dist)

    index=np.argsort(dist)
    print (index)

    numclass=np.max(label)+1
    times=np.zeros(numclass)
    for i in range(k):
        times[label[index[i]]]=times[label[index[i]]]+1
        print(times)

    ind=np.argmax(times)
    return (label[ind])

测试:

    trn1=np.random.randn(10,2)
    trn2=np.random.randn(10,2)
    trn=np.concatenate((trn1,trn2))
    x=np.random.randn(1,2)
    label=[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1]
    k=3
    result=knn(trn,label,x,k)
    print (resut)

matlab代码

  matlab我把这个分成了两个部分,计算距离和分类,因为可选的参数有点多。
首先是计算距离的函数(discompute.m):

    function [D]=discompute(X_trn,X_tst,method)
    %%%%%%%%%%%%%%%%%%%%%
    %   这个函数是来计算训练样本和测试样本之间的距离
    %   X_trn是训练样本,X_tst是测试样本,都是cell矩阵,一个cell存放一张图片
    %   method有四个值可供选择:chi-square(卡方距离)、manhatton(曼哈顿距离)、cosine(余弦距离)、euclidean(欧氏距离)
    %   返回值D即距离,是cell矩阵,一个cell存放一个测试样本和所有训练样本的距离
    %   对于D中的每个cell,行对应着不同的块,列对应着不同的训练样本
    
    if nargin<3 method='chi-square';end
    D=cell(length(X_tst),1);
    switch lower(method)
        case 'chi-square'
            for j=1:length(X_tst)
                x1=X_tst{j};
                for i=1:length(X_trn)
                    x2=X_trn{i};
                    A=(x1-x2).^2./(x1+x2);
                    in=find(isnan(A)==1);
                    A(in)=0;
                    D{j}(:,i)=sum(A,2);     % Chi-square distance
                end
            end
        case 'manhattan'
            for j=1:length(X_tst)
                x1=X_tst{j};
                for i=1:length(X_trn)
                    x2=X_trn{i};
                    D{j}(:,i)=sum(abs(x1-x2),2); %Mahatton distance
                end
            end
        case 'cosine'
            for j=1:length(X_tst)
                x1=X_tst{j};
    %              [x1]=normlizedata(x1,'1-norm');
                for i=1:length(X_trn)
                    x2=X_trn{i};
    %                    [x2]=normlizedata(x2,'1-norm');
                    D{j}(:,i)=1-(diag(x1*x2')./(sqrt(diag(x1*x1')).*sqrt(diag(x2*x2')))); % Cosine distance
                end
            end
        case 'euclidean'
            for j=1:length(X_tst)
                x1=X_tst{j};
                for i=1:length(X_trn)
                    x2=X_trn{i};
                    D{j}(:,i)=(sum(((x1-x2).^2),2)); %Euclidean distance
                end
            end
    end

然后是分类(disclassify.m):

`function [out]=distclassify(D,Y,method,Layer)
    %%%%%%%%%%%%%%%%%%
    %   这个函数是用来进行分类的
    %   参数D是距离(参见discompute.m),Y是所有训练样本的标签
    %   method有四个值可选:vote(投票)、min_dist(最小值)、max_dist(最大值)和sum_dist(总和)。
    %   out返回所有测试样本的标签,是一个行向量
    
    if nargin<2 || nargin>4
        help Distclassify
    else
        numclass=max(Y);
        numtest=length(D);
        if nargin<4 Layer=floor(log(numclass)/log(2));end 
        if nargin<3 method='vote';end
        switch lower(method)
            case 'vote'
                A=zeros(numtest,numclass);
                for i=1:length(D)
                    [~,d]=min(D{i}');
                    for j=1:numclass
                        A(i,j)=sum(Y(j)==d);
                    end
                end
                [~,out]=max(A');
            case 'min_dist'
                A=zeros(numtest,numclass);
                for i=1:numtest
                    A(i,:)=min(D{i});
                end
                [~,out]=min(A');
            case 'max_dist'
                A=zeros(numtest,numclass);
                for i=1:numtest
                    A(i,:)=max(D{i});
                end
                [~,out]=min(A');
            case 'sum_dist'
                A=zeros(numtest,numclass);
                for i=1:length(D)
                    A(i,:)=sum(D{i});
                end
                [~,out]=min(A');
          
        end
    end
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容