function [V_out,clusters_out]=... spectral_clustering(K,number_of_clusters,kmeans_or_not,plots_or_not,type_of_normalization) %function [V_out,clusters_out]=... % spectral_clustering(K,number_of_clusters,... % kmeans_or_not,plots_or_not,type_of_normalization) % %Performs standard spectral clustering. The rows of V_out are normalized %after removing the constant column. The user can choose between additive %or divisive normalization. % %INPUTS: % K = the affinity matrix % number_of_clusters = how many clusters do you want to find % kmeans_or_not = boolean indicating if kmeans needs to be % performed or not % plots_or_not = boolean indicating if plots need to be outputted or not % type_of_normalization = 'A' | 'D', for additive or divisive normalization % %OUTPUTS: % V_out = the eigenvectors output, AFTER removing the constant eigenvector, % and WITH normalizing their rows % clusters_out = the clusters output, if requested by putting kmeans_or_not=1 % % %Author: Tijl De Bie, december 2003. %%%%%%%%%%%%% % Parameters restarts_for_Kmeans=100; %%%%%%%%%%%%% size_K=size(K,1); if issparse(K) D=spdiags(sum(K,2),0,size_K,size_K); else D=diag(sum(K,2)); end % Compute matrix for which eigenvectors need to be computed switch type_of_normalization case 'A' LH=D-K; if issparse(K) RH=speye(size_K); else RH=eye(size_K); end case 'D' LH=D-K; RH=D; otherwise disp('unknown type of normalization') end % Compute eigenvectors, and normalize opts.disp=0; [V,eigenvalues]=eigs(LH,RH,number_of_clusters+1,'SM',opts); [mdismiss,dismiss]=min(abs(diag(eigenvalues))); V(:,dismiss)=[]; for i=1:size(V,2) V(:,i)=V(:,i)/norm(V(:,i)); end %dv=sqrt(diag(V*V'))+1e-8; %V_out=diag(1./dv)*V; V_out=V; dv=sqrt(diag(V*V'))+1e-8; V_out=diag(1./dv)*V; % Perform K-means if requested if kmeans_or_not % Generate initial conditions ic=zeros(number_of_clusters,number_of_clusters,restarts_for_Kmeans); for ct1=1:restarts_for_Kmeans new_ind=ceil(rand*size_K); ic_ct1=V_out(new_ind,:); for ct2=2:number_of_clusters inner_products=V_out*ic_ct1'; worst_inner_products=max(abs(inner_products),[],2); new_ind=find(worst_inner_products==min(worst_inner_products)); new_ind=new_ind(1); ic_ct1=[ic_ct1 ; V_out(new_ind,:)]; end ic(:,:,ct1)=ic_ct1; end % Try to do kmeans with these initial conditions try clusters_out=kmeans(V_out,number_of_clusters,'Start',ic,'EmptyAction','singleton'); catch clusters_out=0; end else clusters_out=[]; end % Give plot output if requested if plots_or_not figure plot(V_out) grid on if kmeans_or_not hold on plot(clusters_out-number_of_clusters/2-0.5) end end