Bag-Of-Words中K-Means聚类的效率优化

转自:http://www.zhizhihu.com/html/y2010/2257.html

 

        最初的Bag of words,也叫做“词袋”,在信息检索中,Bag of words model假定对于一个文本,忽略其词序和语法,句法,将其仅仅看做是一个词集合,或者说是词的一个组合,文本中每个词的出现都是独立的,不依赖于其他词 是否出现,或者说当这篇文章的作者在任意一个位置选择一个词汇都不受前面句子的影响而独立选择的。

        穿越到2011年10月24号写了篇博客《一个用BoW|Pyramid BoW+SVM进行图像分类的Matlab Demo》,希望有帮助。

       

        现在Computer Vision中的Bag of words来表示图像的特征描述也是很流行的。大体思想是这样的,假设有5类图像,每一类中有10幅图像,这样首先对每一幅图像划分成patch(可以是刚性分割也可以是像SIFT基于关键点检测的),这样,每一个图像就由很多个patch表示每一个patch用一个特征向量来表示,咱就假设用Sift表示的,一幅图像可能会有成百上千个patch,每一个patch特征向量的维数128。

        接下来就要进行构建Bag of words模型了,假设Dictionary词典的Size为100,即有100个词。那么咱们可以用K-means算法对所有的patch进行聚类,k=100,我们知道,等k-means收敛时,我们也得到了每一个cluster最后的质心,那么这100个质心(维数128)就是词典里的100个词了,词典构建完毕。

        词典构建完了怎么用呢?是这样的,先初始化一个100个bin的初始值为0的直方图h。每一幅图像不是有很多patch么?我们就再次计算这些patch和和每一个质心的距离,看看每一个patch离哪一个质心最近,那么直方图h中相对应的bin就加1,然后计算完这幅图像所有的patches之后,就得到了一个bin=100的直方图,然后进行归一化,用这个100维的向量来表示这幅图像。对所有图像计算完成之后,就可以进行分类聚类训练预测之类的了

        那么,这里影响效率的一个方面是构建词典时的K-means聚类,我在用的时候遇到了两个问题:1、内存溢出。这是由于一般的K-means函数的输入是待聚类的完整的矩阵,在这里就是所有patches的特征向量f合成的一个大矩阵,由于这个矩阵太大,内存不顶了。我内存为4G。2、效率低。因为需要计算每一个patch和每一个质心的欧拉距离,还有比较大小,那么要是循环下来这个效率是很低的。

        为了解决这个问题,我采用一下策略,不使用整一个数据矩阵X作为输入的k-means,而是自己写循环,每次处理一幅图像的所有patches,对于效率的问题,因为matlab强大的矩阵处理能力,可以有效避免耗时费力的自己编写的循环迭代。

        我自己的代码下载:

        代码下载链接:PG_BOW_DEMO.zip,如果无法下载,当然可以再发邮件问我要,pagelee.sd at gmail.com。

        Demo中的图像是我自己研究中用到的一些Action的图像,我都采集的简单的一共6类,每一类60幅,40训练20测试。请注意图像的版权问题,自己研究即可,不能商用。

分类器用的是libsvm,最好自己mex重新编译一下。

        Demo中的版权我也已经注明。

        具体我用的代码形式:

</span>   %% for n=1:niters % Save old centres to check for termination if n>1 e2=max(max(abs(centres - old_centres))) ; elsee2=0; end  old_centres = centres; tempc=centres; num_points=ones(1,ncentres);   for f = 1:nimages %省略了一些读取特征的细节 data = features.data;%每个图像的所有patch的特征矩阵 [ndata, data_dim] = size(data);   id = eye(ncentres); d2 = distance(data,centres);%计算两个矩阵的欧式距离,这样计算以及下面几句代码都大大提高计算效率 % Assign each point to nearest centre [minvals, index] = min(d2', [], 1); post = id(index,:); % matrix, if word i is in cluster j, post(i,j)=1, else 0;   num_points = num_points + sum(post, 1);   for j = 1:ncentres tempc(j,:) =  tempc(j,:)+sum(data(find(post(:,j)),:), 1); end  end  for j = 1:ncentres if num_points(j)>0 centres(j,:) =  tempc(j,:)/num_points(j); endendif n > 1 % Test for termination   newError=max(max(abs(centres - old_centres))); if newError<minError minError=newError; end  if newError < 0.01 %某个聚类要收敛的阈值 fprintf('Saving texton dictionary\n'); save (['/','centres'],'centres');      % save the settings of descriptor in opts.globaldatapath break; end  fprintf('The %d th interation finished \n',n); endend

下面是求欧式距离的distance函数:

</span>   function d = distance(a,b) % DISTANCE - computes Euclidean distance matrix % % E = distance(A,B) % %    A - (MxD) matrix %    B - (NxD) matrix % % Returns: %    E - (MxN) Euclidean distances between vectors in A and B % % % Description : %    This fully vectorized (VERY FAST!) m-file computes the %    Euclidean distance between two vectors by: % %                 ||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B ) % % Example : %    A = rand(100,400); B = rand(200,400); %    d = distance(A,B);   % Author   : Roland Bunschoten %            University of Amsterdam %            Intelligent Autonomous Systems (IAS) group %            Kruislaan 403  1098 SJ Amsterdam %            tel.(+31)20-5257524 %            bunschot@wins.uva.nl % Last Rev : Oct 29 16:35:48 MET DST 1999 % Tested   : PC Matlab v5.2 and Solaris Matlab v5.3 % Thanx    : Nikos Vlassis   % Copyright notice: You are free to modify, extend and distribute %    this code granted that the author of the original code is %    mentioned as the original author of the code.   if (nargin ~= 2) b=a; end  if (size(a,2) ~= size(b,2)) error('A and B should be of same dimensionality'); end  %aa=sum(a.*a,1); bb=sum(b.*b,1); ab=a'*b; %d = sqrt(abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab)); aa=sum(a.*a,2); bb=sum(b.*b,2); ab=a*b'; d = sqrt(abs(repmat(aa,[1 size(bb,1)]) + repmat(bb',[size(aa,1) 1]) - 2*ab));


另外从水木上看到一个人写的短小精悍的kmeans,大家参考下吧:

function label = litekmeans(X, k) n = size(X,2); last = 0; label = ceil(k*rand(1,n));  % random initialization while any(label ~= last) [~,~,label] = unique(label);   % remove empty clusters E = sparse(1:n,label,1,n,k,n);  % transform label into indicator matrix center = X*(E*spdiags(1./sum(E,1)',0,k,k));    % compute center of each cluster last = label; [~,label] = max(bsxfun(@minus,center'*X,0.5*sum(center.^2,1)'),[],1); % assign samples to the nearest centers end


 

另外在最新的一篇博文《一个用BoW|Pyramid BoW+SVM进行图像分类的Matlab Demo》详细讲了怎么结合SVM分类的问题和Matlab Demo,很直观,希望有用。

下面再次说一下基本的理解:

1、个人感觉Bag of Words/Bag of Features原理都差不多,个人还是当一个概念来理解的,可能bag of features涵盖的内容更加具体,特征更有代表性吧。

2、聚类的初始点可以自己选取,也可以随机选取,其实对于聚类的结果虽然有影响,但是最后用于分类的时候影响没那么明显

-------------

刚性分割 其实术语是叫 dense sift 你搜一下;

代码也不是纯碎我写的 主要还是集成了 http://www.di.ens.fr/willow/pdfs/cvpr06b.pdf 的代码 稍微做了自己分为方便的改动。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值