├── ClusteringMeasure ├── Accuracy.m ├── Contingency.m ├── RandIndex.m ├── bestMap.m ├── compute_f.m ├── compute_nmi.m └── hungarian.m ├── LRR ├── NormalizeData.m ├── SpectralClustering.m ├── demo.m ├── demo_LRR.m ├── exact_alm_lrr_l1v2.m ├── exact_alm_lrr_l21v2.m ├── inexact_alm_lrr_l1.m ├── inexact_alm_lrr_l21.m ├── solve_l1l2.m └── solve_lrr.m ├── TensorRank ├── Matrix2Vector.m ├── Tensor2Matrix.m ├── Tensor2Vector.m ├── Vector2Tensor.m ├── softth.m ├── updateG_tensor.m └── updateG_unfold.m ├── demo.m └── lt_msc.m /ClusteringMeasure/Accuracy.m: -------------------------------------------------------------------------------- 1 | function ACC = Accuracy(C,gt) 2 | C = bestMap(gt,C); 3 | ACC = length(find(gt == C))/length(gt); 4 | end -------------------------------------------------------------------------------- /ClusteringMeasure/Contingency.m: -------------------------------------------------------------------------------- 1 | function Cont=Contingency(Mem1,Mem2) 2 | %CONTINGENCY Form contigency matrix for two vectors 3 | % C=Contingency(Mem1,Mem2) returns contingency matrix for two 4 | % column vectors Mem1, Mem2. These define which cluster each entity 5 | % has been assigned to. 6 | % 7 | % See also RANDINDEX. 8 | % 9 | 10 | %(C) David Corney (2000) D.Corney@cs.ucl.ac.uk 11 | 12 | if nargin < 2 | min(size(Mem1)) > 1 | min(size(Mem2)) > 1 13 | error('Contingency: Requires two vector arguments') 14 | return 15 | end 16 | 17 | Cont=zeros(max(Mem1),max(Mem2)); 18 | 19 | for i = 1:length(Mem1); 20 | Cont(Mem1(i),Mem2(i))=Cont(Mem1(i),Mem2(i))+1; 21 | end 22 | -------------------------------------------------------------------------------- /ClusteringMeasure/RandIndex.m: -------------------------------------------------------------------------------- 1 | function [AR,RI,MI,HI]=RandIndex(c1,c2) 2 | %RANDINDEX - calculates Rand Indices to compare two partitions 3 | % ARI=RANDINDEX(c1,c2), where c1,c2 are vectors listing the 4 | % class membership, returns the "Hubert & Arabie adjusted Rand index". 5 | % [AR,RI,MI,HI]=RANDINDEX(c1,c2) returns the adjusted Rand index, 6 | % the unadjusted Rand index, "Mirkin's" index and "Hubert's" index. 7 | % 8 | % See L. Hubert and P. Arabie (1985) "Comparing Partitions" Journal of 9 | % Classification 2:193-218 10 | 11 | %(C) David Corney (2000) D.Corney@cs.ucl.ac.uk 12 | 13 | if nargin < 2 | min(size(c1)) > 1 | min(size(c2)) > 1 14 | error('RandIndex: Requires two vector arguments') 15 | return 16 | end 17 | 18 | C=Contingency(c1,c2); %form contingency matrix 19 | 20 | n=sum(sum(C)); 21 | nis=sum(sum(C,2).^2); %sum of squares of sums of rows 22 | njs=sum(sum(C,1).^2); %sum of squares of sums of columns 23 | 24 | t1=nchoosek(n,2); %total number of pairs of entities 25 | t2=sum(sum(C.^2)); %sum over rows & columnns of nij^2 26 | t3=.5*(nis+njs); 27 | 28 | %Expected index (for adjustment) 29 | nc=(n*(n^2+1)-(n+1)*nis-(n+1)*njs+2*(nis*njs)/n)/(2*(n-1)); 30 | 31 | A=t1+t2-t3; %no. agreements 32 | D= -t2+t3; %no. disagreements 33 | 34 | if t1==nc 35 | AR=0; %avoid division by zero; if k=1, define Rand = 0 36 | else 37 | AR=(A-nc)/(t1-nc); %adjusted Rand - Hubert & Arabie 1985 38 | end 39 | 40 | RI=A/t1; %Rand 1971 %Probability of agreement 41 | MI=D/t1; %Mirkin 1970 %p(disagreement) 42 | HI=(A-D)/t1; %Hubert 1977 %p(agree)-p(disagree) 43 | 44 | -------------------------------------------------------------------------------- /ClusteringMeasure/bestMap.m: -------------------------------------------------------------------------------- 1 | function [newL2] = bestMap(L1,L2) 2 | %bestmap: permute labels of L2 to match L1 as good as possible 3 | % [newL2] = bestMap(L1,L2); 4 | % 5 | % version 2.0 --May/2007 6 | % version 1.0 --November/2003 7 | % 8 | % Written by Deng Cai (dengcai AT gmail.com) 9 | 10 | 11 | %=========== 12 | 13 | L1 = L1(:); 14 | L2 = L2(:); 15 | if size(L1) ~= size(L2) 16 | error('size(L1) must == size(L2)'); 17 | end 18 | 19 | Label1 = unique(L1); 20 | nClass1 = length(Label1); 21 | Label2 = unique(L2); 22 | nClass2 = length(Label2); 23 | 24 | nClass = max(nClass1,nClass2); 25 | G = zeros(nClass); 26 | for i=1:nClass1 27 | for j=1:nClass2 28 | G(i,j) = length(find(L1 == Label1(i) & L2 == Label2(j))); 29 | end 30 | end 31 | 32 | [c,t] = hungarian(-G); 33 | newL2 = zeros(size(L2)); 34 | for i=1:nClass2 35 | newL2(L2 == Label2(i)) = Label1(c(i)); 36 | end 37 | -------------------------------------------------------------------------------- /ClusteringMeasure/compute_f.m: -------------------------------------------------------------------------------- 1 | function [f,p,r] = compute_f(T,H) 2 | 3 | if length(T) ~= length(H), 4 | size(T) 5 | size(H) 6 | end; 7 | 8 | N = length(T); 9 | numT = 0; 10 | numH = 0; 11 | numI = 0; 12 | for n=1:N, 13 | Tn = (T(n+1:end))==T(n); 14 | Hn = (H(n+1:end))==H(n); 15 | numT = numT + sum(Tn); 16 | numH = numH + sum(Hn); 17 | numI = numI + sum(Tn .* Hn); 18 | end; 19 | p = 1; 20 | r = 1; 21 | f = 1; 22 | if numH > 0, 23 | p = numI / numH; 24 | end; 25 | if numT > 0, 26 | r = numI / numT; 27 | end; 28 | if (p+r) == 0, 29 | f = 0; 30 | else 31 | f = 2 * p * r / (p + r); 32 | end; 33 | -------------------------------------------------------------------------------- /ClusteringMeasure/compute_nmi.m: -------------------------------------------------------------------------------- 1 | function [A nmi avgent] = compute_nmi (T, H) 2 | 3 | N = length(T); 4 | classes = unique(T); 5 | clusters = unique(H); 6 | num_class = length(classes); 7 | num_clust = length(clusters); 8 | 9 | %%compute number of points in each class 10 | for j=1:num_class 11 | index_class = (T(:)==classes(j)); 12 | D(j) = sum(index_class); 13 | end 14 | 15 | %%mutual information 16 | mi = 0; 17 | A = zeros(num_clust, num_class); 18 | avgent = 0; 19 | for i=1:num_clust 20 | %number of points in cluster 'i' 21 | index_clust = (H(:)==clusters(i)); 22 | B(i) = sum(index_clust); 23 | for j=1:num_class 24 | index_class = (T(:)==classes(j)); 25 | %%compute number of points in class 'j' that end up in cluster 'i' 26 | A(i,j) = sum(index_class.*index_clust); 27 | if (A(i,j) ~= 0) 28 | miarr(i,j) = A(i,j)/N * log2 (N*A(i,j)/(B(i)*D(j))); 29 | %%average entropy calculation 30 | avgent = avgent - (B(i)/N) * (A(i,j)/B(i)) * log2 (A(i,j)/B(i)); 31 | else 32 | miarr(i,j) = 0; 33 | end 34 | mi = mi + miarr(i,j); 35 | 36 | 37 | 38 | end 39 | end 40 | 41 | %%class entropy 42 | class_ent = 0; 43 | for i=1:num_class 44 | class_ent = class_ent + D(i)/N * log2(N/D(i)); 45 | end 46 | 47 | %%clustering entropy 48 | clust_ent = 0; 49 | for i=1:num_clust 50 | clust_ent = clust_ent + B(i)/N * log2(N/B(i)); 51 | end 52 | 53 | %%normalized mutual information 54 | nmi = 2*mi / (clust_ent + class_ent); -------------------------------------------------------------------------------- /ClusteringMeasure/hungarian.m: -------------------------------------------------------------------------------- 1 | function [C,T]=hungarian(A) 2 | %HUNGARIAN Solve the Assignment problem using the Hungarian method. 3 | % 4 | %[C,T]=hungarian(A) 5 | %A - a square cost matrix. 6 | %C - the optimal assignment. 7 | %T - the cost of the optimal assignment. 8 | %s.t. T = trace(A(C,:)) is minimized over all possible assignments. 9 | 10 | % Adapted from the FORTRAN IV code in Carpaneto and Toth, "Algorithm 548: 11 | % Solution of the assignment problem [H]", ACM Transactions on 12 | % Mathematical Software, 6(1):104-111, 1980. 13 | 14 | % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. 15 | % Department of Computing Science, Ume? University, 16 | % Sweden. 17 | % All standard disclaimers apply. 18 | 19 | % A substantial effort was put into this code. If you use it for a 20 | % publication or otherwise, please include an acknowledgement or at least 21 | % notify me by email. /Niclas 22 | 23 | [m,n]=size(A); 24 | 25 | if (m~=n) 26 | error('HUNGARIAN: Cost matrix must be square!'); 27 | end 28 | 29 | % Save original cost matrix. 30 | orig=A; 31 | 32 | % Reduce matrix. 33 | A=hminired(A); 34 | 35 | % Do an initial assignment. 36 | [A,C,U]=hminiass(A); 37 | 38 | % Repeat while we have unassigned rows. 39 | while (U(n+1)) 40 | % Start with no path, no unchecked zeros, and no unexplored rows. 41 | LR=zeros(1,n); 42 | LC=zeros(1,n); 43 | CH=zeros(1,n); 44 | RH=[zeros(1,n) -1]; 45 | 46 | % No labelled columns. 47 | SLC=[]; 48 | 49 | % Start path in first unassigned row. 50 | r=U(n+1); 51 | % Mark row with end-of-path label. 52 | LR(r)=-1; 53 | % Insert row first in labelled row set. 54 | SLR=r; 55 | 56 | % Repeat until we manage to find an assignable zero. 57 | while (1) 58 | % If there are free zeros in row r 59 | if (A(r,n+1)~=0) 60 | % ...get column of first free zero. 61 | l=-A(r,n+1); 62 | 63 | % If there are more free zeros in row r and row r in not 64 | % yet marked as unexplored.. 65 | if (A(r,l)~=0 & RH(r)==0) 66 | % Insert row r first in unexplored list. 67 | RH(r)=RH(n+1); 68 | RH(n+1)=r; 69 | 70 | % Mark in which column the next unexplored zero in this row 71 | % is. 72 | CH(r)=-A(r,l); 73 | end 74 | else 75 | % If all rows are explored.. 76 | if (RH(n+1)<=0) 77 | % Reduce matrix. 78 | [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR); 79 | end 80 | 81 | % Re-start with first unexplored row. 82 | r=RH(n+1); 83 | % Get column of next free zero in row r. 84 | l=CH(r); 85 | % Advance "column of next free zero". 86 | CH(r)=-A(r,l); 87 | % If this zero is last in the list.. 88 | if (A(r,l)==0) 89 | % ...remove row r from unexplored list. 90 | RH(n+1)=RH(r); 91 | RH(r)=0; 92 | end 93 | end 94 | 95 | % While the column l is labelled, i.e. in path. 96 | while (LC(l)~=0) 97 | % If row r is explored.. 98 | if (RH(r)==0) 99 | % If all rows are explored.. 100 | if (RH(n+1)<=0) 101 | % Reduce cost matrix. 102 | [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR); 103 | end 104 | 105 | % Re-start with first unexplored row. 106 | r=RH(n+1); 107 | end 108 | 109 | % Get column of next free zero in row r. 110 | l=CH(r); 111 | 112 | % Advance "column of next free zero". 113 | CH(r)=-A(r,l); 114 | 115 | % If this zero is last in list.. 116 | if(A(r,l)==0) 117 | % ...remove row r from unexplored list. 118 | RH(n+1)=RH(r); 119 | RH(r)=0; 120 | end 121 | end 122 | 123 | % If the column found is unassigned.. 124 | if (C(l)==0) 125 | % Flip all zeros along the path in LR,LC. 126 | [A,C,U]=hmflip(A,C,LC,LR,U,l,r); 127 | % ...and exit to continue with next unassigned row. 128 | break; 129 | else 130 | % ...else add zero to path. 131 | 132 | % Label column l with row r. 133 | LC(l)=r; 134 | 135 | % Add l to the set of labelled columns. 136 | SLC=[SLC l]; 137 | 138 | % Continue with the row assigned to column l. 139 | r=C(l); 140 | 141 | % Label row r with column l. 142 | LR(r)=l; 143 | 144 | % Add r to the set of labelled rows. 145 | SLR=[SLR r]; 146 | end 147 | end 148 | end 149 | 150 | % Calculate the total cost. 151 | T=sum(orig(logical(sparse(C,1:size(orig,2),1)))); 152 | 153 | 154 | function A=hminired(A) 155 | %HMINIRED Initial reduction of cost matrix for the Hungarian method. 156 | % 157 | %B=assredin(A) 158 | %A - the unreduced cost matris. 159 | %B - the reduced cost matrix with linked zeros in each row. 160 | 161 | % v1.0 96-06-13. Niclas Borlin, niclas@cs.umu.se. 162 | 163 | [m,n]=size(A); 164 | 165 | % Subtract column-minimum values from each column. 166 | colMin=min(A); 167 | A=A-colMin(ones(n,1),:); 168 | 169 | % Subtract row-minimum values from each row. 170 | rowMin=min(A')'; 171 | A=A-rowMin(:,ones(1,n)); 172 | 173 | % Get positions of all zeros. 174 | [i,j]=find(A==0); 175 | 176 | % Extend A to give room for row zero list header column. 177 | A(1,n+1)=0; 178 | for k=1:n 179 | % Get all column in this row. 180 | cols=j(k==i)'; 181 | % Insert pointers in matrix. 182 | A(k,[n+1 cols])=[-cols 0]; 183 | end 184 | 185 | 186 | function [A,C,U]=hminiass(A) 187 | %HMINIASS Initial assignment of the Hungarian method. 188 | % 189 | %[B,C,U]=hminiass(A) 190 | %A - the reduced cost matrix. 191 | %B - the reduced cost matrix, with assigned zeros removed from lists. 192 | %C - a vector. C(J)=I means row I is assigned to column J, 193 | % i.e. there is an assigned zero in position I,J. 194 | %U - a vector with a linked list of unassigned rows. 195 | 196 | % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. 197 | 198 | [n,np1]=size(A); 199 | 200 | % Initalize return vectors. 201 | C=zeros(1,n); 202 | U=zeros(1,n+1); 203 | 204 | % Initialize last/next zero "pointers". 205 | LZ=zeros(1,n); 206 | NZ=zeros(1,n); 207 | 208 | for i=1:n 209 | % Set j to first unassigned zero in row i. 210 | lj=n+1; 211 | j=-A(i,lj); 212 | 213 | % Repeat until we have no more zeros (j==0) or we find a zero 214 | % in an unassigned column (c(j)==0). 215 | 216 | while (C(j)~=0) 217 | % Advance lj and j in zero list. 218 | lj=j; 219 | j=-A(i,lj); 220 | 221 | % Stop if we hit end of list. 222 | if (j==0) 223 | break; 224 | end 225 | end 226 | 227 | if (j~=0) 228 | % We found a zero in an unassigned column. 229 | 230 | % Assign row i to column j. 231 | C(j)=i; 232 | 233 | % Remove A(i,j) from unassigned zero list. 234 | A(i,lj)=A(i,j); 235 | 236 | % Update next/last unassigned zero pointers. 237 | NZ(i)=-A(i,j); 238 | LZ(i)=lj; 239 | 240 | % Indicate A(i,j) is an assigned zero. 241 | A(i,j)=0; 242 | else 243 | % We found no zero in an unassigned column. 244 | 245 | % Check all zeros in this row. 246 | 247 | lj=n+1; 248 | j=-A(i,lj); 249 | 250 | % Check all zeros in this row for a suitable zero in another row. 251 | while (j~=0) 252 | % Check the in the row assigned to this column. 253 | r=C(j); 254 | 255 | % Pick up last/next pointers. 256 | lm=LZ(r); 257 | m=NZ(r); 258 | 259 | % Check all unchecked zeros in free list of this row. 260 | while (m~=0) 261 | % Stop if we find an unassigned column. 262 | if (C(m)==0) 263 | break; 264 | end 265 | 266 | % Advance one step in list. 267 | lm=m; 268 | m=-A(r,lm); 269 | end 270 | 271 | if (m==0) 272 | % We failed on row r. Continue with next zero on row i. 273 | lj=j; 274 | j=-A(i,lj); 275 | else 276 | % We found a zero in an unassigned column. 277 | 278 | % Replace zero at (r,m) in unassigned list with zero at (r,j) 279 | A(r,lm)=-j; 280 | A(r,j)=A(r,m); 281 | 282 | % Update last/next pointers in row r. 283 | NZ(r)=-A(r,m); 284 | LZ(r)=j; 285 | 286 | % Mark A(r,m) as an assigned zero in the matrix . . . 287 | A(r,m)=0; 288 | 289 | % ...and in the assignment vector. 290 | C(m)=r; 291 | 292 | % Remove A(i,j) from unassigned list. 293 | A(i,lj)=A(i,j); 294 | 295 | % Update last/next pointers in row r. 296 | NZ(i)=-A(i,j); 297 | LZ(i)=lj; 298 | 299 | % Mark A(r,m) as an assigned zero in the matrix . . . 300 | A(i,j)=0; 301 | 302 | % ...and in the assignment vector. 303 | C(j)=i; 304 | 305 | % Stop search. 306 | break; 307 | end 308 | end 309 | end 310 | end 311 | 312 | % Create vector with list of unassigned rows. 313 | 314 | % Mark all rows have assignment. 315 | r=zeros(1,n); 316 | rows=C(C~=0); 317 | r(rows)=rows; 318 | empty=find(r==0); 319 | 320 | % Create vector with linked list of unassigned rows. 321 | U=zeros(1,n+1); 322 | U([n+1 empty])=[empty 0]; 323 | 324 | 325 | function [A,C,U]=hmflip(A,C,LC,LR,U,l,r) 326 | %HMFLIP Flip assignment state of all zeros along a path. 327 | % 328 | %[A,C,U]=hmflip(A,C,LC,LR,U,l,r) 329 | %Input: 330 | %A - the cost matrix. 331 | %C - the assignment vector. 332 | %LC - the column label vector. 333 | %LR - the row label vector. 334 | %U - the 335 | %r,l - position of last zero in path. 336 | %Output: 337 | %A - updated cost matrix. 338 | %C - updated assignment vector. 339 | %U - updated unassigned row list vector. 340 | 341 | % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. 342 | 343 | n=size(A,1); 344 | 345 | while (1) 346 | % Move assignment in column l to row r. 347 | C(l)=r; 348 | 349 | % Find zero to be removed from zero list.. 350 | 351 | % Find zero before this. 352 | m=find(A(r,:)==-l); 353 | 354 | % Link past this zero. 355 | A(r,m)=A(r,l); 356 | 357 | A(r,l)=0; 358 | 359 | % If this was the first zero of the path.. 360 | if (LR(r)<0) 361 | ...remove row from unassigned row list and return. 362 | U(n+1)=U(r); 363 | U(r)=0; 364 | return; 365 | else 366 | 367 | % Move back in this row along the path and get column of next zero. 368 | l=LR(r); 369 | 370 | % Insert zero at (r,l) first in zero list. 371 | A(r,l)=A(r,n+1); 372 | A(r,n+1)=-l; 373 | 374 | % Continue back along the column to get row of next zero in path. 375 | r=LC(l); 376 | end 377 | end 378 | 379 | 380 | function [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR) 381 | %HMREDUCE Reduce parts of cost matrix in the Hungerian method. 382 | % 383 | %[A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR) 384 | %Input: 385 | %A - Cost matrix. 386 | %CH - vector of column of 'next zeros' in each row. 387 | %RH - vector with list of unexplored rows. 388 | %LC - column labels. 389 | %RC - row labels. 390 | %SLC - set of column labels. 391 | %SLR - set of row labels. 392 | % 393 | %Output: 394 | %A - Reduced cost matrix. 395 | %CH - Updated vector of 'next zeros' in each row. 396 | %RH - Updated vector of unexplored rows. 397 | 398 | % v1.0 96-06-14. Niclas Borlin, niclas@cs.umu.se. 399 | 400 | n=size(A,1); 401 | 402 | % Find which rows are covered, i.e. unlabelled. 403 | coveredRows=LR==0; 404 | 405 | % Find which columns are covered, i.e. labelled. 406 | coveredCols=LC~=0; 407 | 408 | r=find(~coveredRows); 409 | c=find(~coveredCols); 410 | 411 | % Get minimum of uncovered elements. 412 | m=min(min(A(r,c))); 413 | 414 | % Subtract minimum from all uncovered elements. 415 | A(r,c)=A(r,c)-m; 416 | 417 | % Check all uncovered columns.. 418 | for j=c 419 | % ...and uncovered rows in path order.. 420 | for i=SLR 421 | % If this is a (new) zero.. 422 | if (A(i,j)==0) 423 | % If the row is not in unexplored list.. 424 | if (RH(i)==0) 425 | % ...insert it first in unexplored list. 426 | RH(i)=RH(n+1); 427 | RH(n+1)=i; 428 | % Mark this zero as "next free" in this row. 429 | CH(i)=j; 430 | end 431 | % Find last unassigned zero on row I. 432 | row=A(i,:); 433 | colsInList=-row(row<0); 434 | if (length(colsInList)==0) 435 | % No zeros in the list. 436 | l=n+1; 437 | else 438 | l=colsInList(row(colsInList)==0); 439 | end 440 | % Append this zero to end of list. 441 | A(i,l)=-j; 442 | end 443 | end 444 | end 445 | 446 | % Add minimum to all doubly covered elements. 447 | r=find(coveredRows); 448 | c=find(coveredCols); 449 | 450 | % Take care of the zeros we will remove. 451 | [i,j]=find(A(r,c)<=0); 452 | 453 | i=r(i); 454 | j=c(j); 455 | 456 | for k=1:length(i) 457 | % Find zero before this in this row. 458 | lj=find(A(i(k),:)==-j(k)); 459 | % Link past it. 460 | A(i(k),lj)=A(i(k),j(k)); 461 | % Mark it as assigned. 462 | A(i(k),j(k))=0; 463 | end 464 | 465 | A(r,c)=A(r,c)+m; -------------------------------------------------------------------------------- /LRR/NormalizeData.m: -------------------------------------------------------------------------------- 1 | 2 | function [ProcessData]=NormalizeData(X) 3 | 4 | [nFea,nSmp] = size(X); 5 | for i = 1:nSmp 6 | ProcessData(:,i) = X(:,i) ./ max(1e-12,norm(X(:,i))); 7 | end -------------------------------------------------------------------------------- /LRR/SpectralClustering.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % This function takes an adjacency matrix of a graph and computes the 3 | % clustering of the nodes using the spectral clustering algorithm of 4 | % Ng, Jordan and Weiss. 5 | % CMat: NxN adjacency matrix 6 | % n: number of groups for clustering 7 | % groups: N-dimensional vector containing the memberships of the N points 8 | % to the n groups obtained by spectral clustering 9 | %-------------------------------------------------------------------------- 10 | % Copyright @ Ehsan Elhamifar, 2012 11 | %-------------------------------------------------------------------------- 12 | 13 | function groups = SpectralClustering(CKSym,n) 14 | 15 | warning off; 16 | N = size(CKSym,1); 17 | MAXiter = 1000; % Maximum number of iterations for KMeans 18 | REPlic = 20; % Number of replications for KMeans 19 | 20 | % Normalized spectral clustering according to Ng & Jordan & Weiss 21 | % using Normalized Symmetric Laplacian L = I - D^{-1/2} W D^{-1/2} 22 | 23 | DN = diag( 1./sqrt(sum(CKSym)+eps) ); 24 | LapN = speye(N) - DN * CKSym * DN; 25 | [uN,sN,vN] = svd(LapN); 26 | kerN = vN(:,N-n+1:N); 27 | for i = 1:N 28 | kerNS(i,:) = kerN(i,:) ./ norm(kerN(i,:)+eps); 29 | end 30 | groups = kmeans(kerNS,n,'maxiter',MAXiter,'replicates',REPlic,'EmptyAction','singleton'); -------------------------------------------------------------------------------- /LRR/demo.m: -------------------------------------------------------------------------------- 1 | function [] = demo() 2 | A = randn(100,200); 3 | X = randn(100,100); 4 | A = X; 5 | lambda = 0.01; 6 | 7 | disp('solve min |Z|_* + lambda |E|_21 s.t. X = AZ + E by exact ALM ...'); 8 | 9 | tic; 10 | [Z1,E1] = solve_lrr(X,A,lambda,0,0); 11 | obj1 = sum(svd(Z1)) + lambda*sum(sqrt(sum(E1.^2,1))); 12 | toc; 13 | 14 | disp(['objective value=' num2str(obj1)]); 15 | 16 | disp('solve min |Z|_* + lambda |E|_21 s.t. X = AZ + E by inexact ALM ...'); 17 | 18 | tic; 19 | [Z2,E2] = solve_lrr(X,A,lambda,0,1); 20 | obj2 = sum(svd(Z2)) + lambda*sum(sqrt(sum(E2.^2,1))); 21 | toc; 22 | disp(['objective value=' num2str(obj2)]); 23 | 24 | diff = max(max(abs(Z1 - Z2))); 25 | 26 | warning(['difference of the solution found by those two approaches: |Z1 - Z2|_inf=' num2str(diff)]); 27 | 28 | disp('solve min |Z|_* + lambda |E|_1 s.t. X = AZ + E by exact ALM ...'); 29 | tic; 30 | [Z1,E1] = solve_lrr(X,A,lambda,1,0); 31 | obj1 = sum(svd(Z1)) + lambda*sum(sqrt(sum(E1.^2,1))); 32 | toc; 33 | 34 | disp(['objective value=' num2str(obj1)]); 35 | 36 | disp('solve min |Z|_* + lambda |E|_1 s.t. X = AZ + E by inexact ALM ...'); 37 | tic; 38 | [Z2,E2] = solve_lrr(X,A,lambda,1,1); 39 | obj2 = sum(svd(Z2)) + lambda*sum(sqrt(sum(E2.^2,1))); 40 | toc; 41 | disp(['objective value=' num2str(obj2)]); 42 | 43 | diff = max(max(abs(Z1 - Z2))); 44 | 45 | warning(['difference of the solution found by those two approaches: |Z1 - Z2|_inf=' num2str(diff) ]); 46 | -------------------------------------------------------------------------------- /LRR/demo_LRR.m: -------------------------------------------------------------------------------- 1 | %% For convinience, we assume the order of the tensor is always 3; 2 | clear; 3 | addpath('..\ClusteringMeasure'); 4 | addpath('..\Nuclear_norm_l21_Algorithm'); 5 | load('yale.mat'); % lambda = 10 bestComb:X3,X2 6 | cls_num = length(unique(gt)); 7 | 8 | %data preparation... 9 | X{1} = X2; X{2} = X3; X{3} = X1; 10 | for v=1:3 11 | [X{v}]=NormalizeData(X{v}); 12 | %X{v} = zscore(X{v},1); 13 | end 14 | % Initialize... 15 | lambda = [0.1:0.4:5]; 16 | num = size(lambda, 2); 17 | ACC = []; 18 | for j = 1:num 19 | %[Z{1}, E{1}] = inexact_alm_lrr_l21(X{1}, X{1}, lambda(j), 1); 20 | [Z{1}, E{1}] = inexact_alm_lrr_l21(X{1}, X{1}, 1.5, 1); 21 | A = 0.5*(abs(Z{1})+abs(Z{1}')); 22 | C = SpectralClustering(A, cls_num); 23 | ACC = [ACC, Accuracy(C,double(gt))]; 24 | end 25 | -------------------------------------------------------------------------------- /LRR/exact_alm_lrr_l1v2.m: -------------------------------------------------------------------------------- 1 | function [Z_hat, E_hat] = exact_alm_lrr_l1v2(D, A, lambda, tol, maxIter,display) 2 | 3 | % Aug 2013 4 | % This matlab code implements the Exact ALM algorithm for 5 | % min_{Z,E} |Z|_* + lambda |E|_1 s.t. D = AZ + E 6 | % 7 | % D - m x n matrix of observations/data (required input) 8 | % A - m x k matrix of the dictionary (required input) 9 | 10 | % lambda - weight on sparse error term in the cost function 11 | % 12 | % tol - tolerance for stopping criterion. 13 | % - DEFAULT 1e-7 if omitted or -1. 14 | % 15 | % maxIter - maximum number of iterations 16 | % - DEFAULT 1000, if omitted or -1. 17 | % 18 | [m n] = size(D); 19 | k = size(A,2); 20 | n_max = max(m,n); 21 | 22 | 23 | if nargin < 3 || isempty(lambda) 24 | lambda = 1 / sqrt(n_max); 25 | end 26 | 27 | if nargin < 4 || isempty(tol) 28 | tol = 1e-7; 29 | end 30 | 31 | if nargin < 5 || isempty(maxIter) 32 | maxIter = 1000; 33 | end 34 | 35 | if nargin<6 || isempty(display) 36 | display = false; 37 | end 38 | 39 | maxIter_primal = 10000; 40 | % initialize 41 | Y = sign(D); 42 | norm_two = norm(Y,2); 43 | norm_inf = norm( Y(:), inf) / lambda; 44 | dual_norm = max(norm_two, norm_inf); 45 | Y = Y / dual_norm; 46 | 47 | W = zeros(k,n); 48 | 49 | Z_hat = zeros(k,n); 50 | E_hat = zeros(m,n); 51 | %parameters 52 | dnorm = norm(D, 'fro'); 53 | tolProj1 = 1e-6 * dnorm; 54 | 55 | anorm = norm(A,2); 56 | tolProj2 = 1e-6 * dnorm/anorm; 57 | 58 | mu = .5/norm_two; % this one can be tuned 59 | rho = 6; % this one can be tuned 60 | 61 | %pre-computation 62 | if m>=k 63 | inv_ata = inv(eye(k) + A'*A); 64 | else 65 | inv_ata = eye(k) - A'/(eye(m)+A*A')*A; 66 | end 67 | 68 | iter = 0; 69 | while iter < maxIter 70 | iter = iter + 1; 71 | 72 | % solve the primal problem by alternative projection 73 | primal_iter = 0; 74 | 75 | while primal_iter < maxIter_primal 76 | primal_iter = primal_iter + 1; 77 | temp_Z = Z_hat; 78 | temp_E = E_hat; 79 | 80 | %update J 81 | temp = temp_Z + W/mu; 82 | [U S V] = svd(temp, 'econ'); 83 | 84 | diagS = diag(S); 85 | svp = length(find(diagS > 1/mu)); 86 | diagS = max(0,diagS - 1/mu); 87 | 88 | if svp < 0.5 %svp = 0 89 | svp = 1; 90 | end 91 | J_hat = U(:,1:svp)*diag(diagS(1:svp))*V(:,1:svp)'; 92 | 93 | % update Z 94 | temp = J_hat + A'*(D - temp_E) + (A'*Y-W)/mu; 95 | Z_hat = inv_ata*temp; 96 | 97 | %update E 98 | temp = D - A*Z_hat + Y/mu; 99 | E_hat = max(0,temp - lambda/mu) + min(0, temp + lambda/mu); 100 | 101 | if norm(E_hat - temp_E, 'fro') < tolProj1 && norm(Z_hat - temp_Z)0))... 116 | ', stopCriterion ' num2str(stopCriterion)]); 117 | end 118 | 119 | if stopCriterion < tol 120 | break; 121 | end 122 | 123 | 124 | end 125 | 126 | end 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /LRR/exact_alm_lrr_l21v2.m: -------------------------------------------------------------------------------- 1 | function [Z_hat, E_hat] = exact_alm_lrr_l21v2(D, A, lambda, tol, maxIter,display) 2 | 3 | % Aug 2013 4 | % This matlab code implements the Exact ALM algorithm for 5 | % min_{Z,E} |Z|_* + lambda |E|_2,1 s.t. D = AZ + E 6 | % 7 | % D - m x n matrix of observations/data (required input) 8 | % A - m x k matrix of the dictionary (required input) 9 | 10 | % lambda - weight on sparse error term in the cost function 11 | % 12 | % tol - tolerance for stopping criterion. 13 | % - DEFAULT 1e-7 if omitted or -1. 14 | % 15 | % maxIter - maximum number of iterations 16 | % - DEFAULT 1000, if omitted or -1. 17 | % 18 | [m n] = size(D); 19 | k = size(A,2); 20 | 21 | 22 | if nargin < 4 || isempty(tol) 23 | tol = 1e-7; 24 | end 25 | 26 | if nargin < 5 || isempty(maxIter) 27 | maxIter = 1000; 28 | end 29 | 30 | if nargin<6 || isempty(display) 31 | display = false; 32 | end 33 | 34 | maxIter_primal = 10000; 35 | % initialize 36 | Y = sign(D); 37 | norm_two = norm(Y,2); 38 | norm_inf = norm( Y(:), inf) / lambda; 39 | dual_norm = max(norm_two, norm_inf); 40 | Y = Y / dual_norm; 41 | 42 | W = zeros(k,n); 43 | 44 | Z_hat = zeros(k,n); 45 | E_hat = zeros(m,n); 46 | %parameters 47 | dnorm = norm(D, 'fro'); 48 | tolProj1 = 1e-6 * dnorm; 49 | 50 | anorm = norm(A,2); 51 | tolProj2 = 1e-6 * dnorm/anorm; 52 | 53 | mu = .5/norm_two; % this one can be tuned 54 | rho = 6; % this one can be tuned 55 | 56 | %pre-computation 57 | if m>=k 58 | inv_ata = inv(eye(k) + A'*A); 59 | else 60 | inv_ata = eye(k) - A'/(eye(m)+A*A')*A; 61 | end 62 | 63 | iter = 0; 64 | while iter < maxIter 65 | iter = iter + 1; 66 | 67 | % solve the primal problem by alternative projection 68 | primal_iter = 0; 69 | 70 | while primal_iter < maxIter_primal 71 | primal_iter = primal_iter + 1; 72 | temp_Z = Z_hat; 73 | temp_E = E_hat; 74 | 75 | %update J 76 | temp = temp_Z + W/mu; 77 | [U S V] = svd(temp, 'econ'); 78 | 79 | diagS = diag(S); 80 | svp = length(find(diagS > 1/mu)); 81 | diagS = max(0,diagS - 1/mu); 82 | 83 | if svp < 0.5 %svp = 0 84 | svp = 1; 85 | end 86 | J_hat = U(:,1:svp)*diag(diagS(1:svp))*V(:,1:svp)'; 87 | 88 | % update Z 89 | temp = J_hat + A'*(D - temp_E) + (A'*Y-W)/mu; 90 | Z_hat = inv_ata*temp; 91 | 92 | %update E 93 | temp = D - A*Z_hat + Y/mu; 94 | E_hat = solve_l1l2(temp, lambda/mu); 95 | 96 | if norm(E_hat - temp_E, 'fro') < tolProj1 && norm(Z_hat - temp_Z)0))... 111 | ', stopCriterion ' num2str(stopCriterion)]); 112 | end 113 | 114 | if stopCriterion < tol 115 | break; 116 | end 117 | 118 | 119 | end 120 | 121 | end 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /LRR/inexact_alm_lrr_l1.m: -------------------------------------------------------------------------------- 1 | function [Z,E] = inexact_alm_lrr_l1(X,A,lambda,display) 2 | % This routine uses Inexact ALM algorithm to solve the following nuclear-norm optimization problem: 3 | % min |Z|_*+lambda*|E|_1 4 | % s.t., X = AZ+E 5 | % inputs: 6 | % X -- D*N data matrix, D is the data dimension, and N is the number 7 | % of data vectors. 8 | % A -- D*M matrix of a dictionary, M is the size of the dictionary 9 | 10 | if nargin<4 11 | display = false; 12 | end 13 | 14 | tol = 1e-8; 15 | maxIter = 1e6; 16 | [d n] = size(X); 17 | m = size(A,2); 18 | rho = 1.1; 19 | max_mu = 1e10; 20 | mu = 1e-6; 21 | atx = A'*X; 22 | inv_a = inv(A'*A+eye(m)); 23 | %% Initializing optimization variables 24 | % intialize 25 | J = zeros(m,n); 26 | Z = zeros(m,n); 27 | E = sparse(d,n); 28 | 29 | Y1 = zeros(d,n); 30 | Y2 = zeros(m,n); 31 | %% Start main loop 32 | iter = 0; 33 | if display 34 | disp(['initial,rank=' num2str(rank(Z))]); 35 | end 36 | while iter1/mu)); 43 | if svp>=1 44 | sigma = sigma(1:svp)-1/mu; 45 | else 46 | svp = 1; 47 | sigma = 0; 48 | end 49 | J = U(:,1:svp)*diag(sigma)*V(:,1:svp)'; 50 | 51 | %udpate Z 52 | Z = inv_a*(atx-A'*E+J+(A'*Y1-Y2)/mu); 53 | 54 | %update E 55 | xmaz = X-A*Z; 56 | temp = xmaz+Y1/mu; 57 | E = max(0,temp - lambda/mu)+min(0,temp + lambda/mu); 58 | 59 | leq1 = xmaz-E; 60 | leq2 = Z-J; 61 | stopC = max(max(max(abs(leq1))),max(max(abs(leq2)))); 62 | if display && (iter==1 || mod(iter,50)==0 || stopC1/mu)); 42 | if svp>=1 43 | sigma = sigma(1:svp)-1/mu; 44 | else 45 | svp = 1; 46 | sigma = 0; 47 | end 48 | J = U(:,1:svp)*diag(sigma)*V(:,1:svp)'; 49 | %udpate Z 50 | Z = inv_a*(atx-A'*E+J+(A'*Y1-Y2)/mu); 51 | %update E 52 | xmaz = X-A*Z; 53 | temp = xmaz+Y1/mu; 54 | E = solve_l1l2(temp,lambda/mu); 55 | 56 | leq1 = xmaz-E; 57 | leq2 = Z-J; 58 | stopC = max(max(max(abs(leq1))),max(max(abs(leq2)))); 59 | if display && (iter==1 || mod(iter,50)==0 || stopClambda 13 | x = (nw-lambda)*w/nw; 14 | else 15 | x = zeros(length(w),1); 16 | end 17 | end -------------------------------------------------------------------------------- /LRR/solve_lrr.m: -------------------------------------------------------------------------------- 1 | function [Z,E] = solve_lrr(X,A,lambda,reg,alm_type,display) 2 | % Aug 2013 3 | % This routine solves the following nuclear-norm optimization problem, 4 | % min |Z|_*+lambda*|E|_L 5 | % s.t., X = AZ+E 6 | % inputs: 7 | % X -- D*N data matrix, D is the data dimension, and N is the number 8 | % of data vectors. 9 | % A -- D*M matrix of a dictionary, M is the size of the dictionary 10 | % lambda -- parameter 11 | % reg -- the norm chosen for characterizing E, 12 | % -- reg=0 (default), use the l21-norm 13 | % -- reg=1 (or ther values except 0), use the l1-norm 14 | % alm_type -- 0 (default) use the exact ALM strategy 15 | % -- 1 use the inexact ALM strategy 16 | % 17 | if nargin < 6 || isempty(display) 18 | display = 1; 19 | end 20 | if nargin<5 || isempty(alm_type) 21 | alm_type = 1 ; 22 | end 23 | 24 | if nargin<4 || isempty(reg) 25 | reg = 0; 26 | end 27 | 28 | Q = orth(A'); 29 | B = A*Q; 30 | 31 | if reg==0 32 | if alm_type ==0 33 | [Z,E] = exact_alm_lrr_l21v2(X,B,lambda,[],[],display); 34 | else 35 | [Z,E] = inexact_alm_lrr_l21(X,B,lambda,display); 36 | end 37 | else 38 | if alm_type == 0 39 | [Z,E] = exact_alm_lrr_l1v2(X,B,lambda,[],[],display); 40 | else 41 | [Z,E] = inexact_alm_lrr_l1(X,B,lambda,display); 42 | end 43 | end 44 | Z = Q*Z; -------------------------------------------------------------------------------- /TensorRank/Matrix2Vector.m: -------------------------------------------------------------------------------- 1 | function v = Matrix2Vector(M,unfolding_mode,dim1,dim2,dim3,K) 2 | v = []; 3 | if(unfolding_mode==1) 4 | M = M'; 5 | v = reshape(M,[dim1*dim2*dim3 1]); 6 | end 7 | if(unfolding_mode==2) 8 | for k=1:K 9 | T{k} = M((k-1)*dim1+1:k*dim1,1:dim1)'; 10 | vv{k} = reshape(T{k},[dim1*dim2 1]); 11 | v = [v;vv{k}]; 12 | end 13 | % M1 = M(1:dim1,:); 14 | % M2 = M(dim1+1:2*dim2,:); 15 | % v1 = reshape(M1,[dim1*dim2 1]); 16 | % v2 = reshape(M2,[dim1*dim2 1]); 17 | % v = [v1;v2]; 18 | end 19 | if(unfolding_mode==3) 20 | v = reshape(M,[dim1*dim2*dim3 1]); 21 | end 22 | end -------------------------------------------------------------------------------- /TensorRank/Tensor2Matrix.m: -------------------------------------------------------------------------------- 1 | function m = Tensor2Matrix(T,unfolding_mode,dim1,dim2,dim3) 2 | m = []; 3 | if(unfolding_mode==1) 4 | for k=1:length(T) 5 | m = [m,T{k}]; 6 | end 7 | end 8 | if(unfolding_mode==2) 9 | for k=1:length(T) 10 | m = [m;T{k}']; 11 | end 12 | end 13 | if(unfolding_mode==3) 14 | for k=1:length(T) 15 | z{k} = reshape(T{k}',[1 dim1*dim2]); 16 | m = [m,z{k}']; 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /TensorRank/Tensor2Vector.m: -------------------------------------------------------------------------------- 1 | function v = Tensor2Vector(T,dim1,dim2,dim3,K) 2 | v = []; 3 | for k=1:K 4 | vv{k} = reshape(T{k},[dim1*dim2 1]); 5 | v = [v;vv{k}]; 6 | end 7 | 8 | % v1 = reshape(T{1},[dim1*dim2 1]); 9 | % v2 = reshape(T{2},[dim1*dim2 1]); 10 | % v = [v1;v2]; 11 | 12 | 13 | % if(unfolding_mode==1) 14 | % z = [T{1};T{2}]; 15 | % v = reshape(z',[1 dim1*dim2*dim3]); 16 | % end 17 | % if(unfolding_mode==2) 18 | % z = [T{1}';T{2}']; 19 | % v = reshape(z',[1 dim1*dim2*dim3]); 20 | % end 21 | % if(unfolding_mode==3) 22 | % z1 = reshape(T{1}',[1 dim1*dim2]); 23 | % z2 = reshape(T{2}',[1 dim1*dim2]); 24 | % v = [z1',z2']; 25 | % v = reshape(v',[1 dim1*dim2*dim3]); 26 | % end 27 | % v = v'; 28 | end -------------------------------------------------------------------------------- /TensorRank/Vector2Tensor.m: -------------------------------------------------------------------------------- 1 | function t = Vector2Tensor(v,dim1,dim2,dim3,K) 2 | % v (input) is the vectorization of tensor t (output, 3-way:dim1,dim2,dim3) 3 | % according the undfolding_mode (input) 4 | % 5 | 6 | L =size(v,1)/K; 7 | for k=1:K 8 | T{k} = reshape(v((k-1)*L+1:k*L),[dim1,dim2]); 9 | t{k} = T{k}; 10 | end 11 | 12 | % M = reshape(v,[dim1 dim2*dim3]); 13 | % M = M'; 14 | % 15 | % for k=1:K 16 | % T{k} = M((k-1)*dim1+1:k*dim1,1:dim1)'; 17 | % t{k} = T{k}; 18 | % end 19 | 20 | 21 | 22 | % T{1} = M(1:dim1,1:dim1)'; 23 | % T{2} = M(dim1+1:dim1*2,1:dim1)'; 24 | % t{1} = T{1}; 25 | % t{2} = T{2}; 26 | % if(unfolding_mode==1) 27 | % M = reshape(v,[dim2*dim3 dim1]); 28 | % T{1} = M(1:dim1,1:dim1); 29 | % T{2} = M(dim1+1:dim1*2,1:dim1); 30 | % end 31 | % if(unfolding_mode==2) 32 | % M = reshape(v,[dim1*dim3 dim2]); 33 | % T{1} = M(1:dim1,1:dim1)'; 34 | % T{2} = M(dim1+1:dim1*2,1:dim1)'; 35 | % end 36 | % if(unfolding_mode==3) 37 | % M = reshape(v,[dim1*dim2 dim3]); 38 | % z1 = M(:,1); 39 | % z2 = M(:,2); 40 | % T{1} = reshape(z1,[dim1 dim2]); 41 | % T{2} = reshape(z2,[dim1 dim2]); 42 | % end 43 | % t{1} = T{1}; 44 | % t{2} = T{2}; 45 | end 46 | 47 | -------------------------------------------------------------------------------- /TensorRank/softth.m: -------------------------------------------------------------------------------- 1 | function E = softth(F,lambda) 2 | %update J 3 | temp = F; 4 | [U S V] = svd(temp, 'econ'); 5 | 6 | diagS = diag(S); 7 | svp = length(find(diagS > lambda)); 8 | diagS = max(0,diagS - lambda); 9 | 10 | if svp < 0.5 %svp = 0 11 | svp = 1; 12 | end 13 | E = U(:,1:svp)*diag(diagS(1:svp))*V(:,1:svp)'; -------------------------------------------------------------------------------- /TensorRank/updateG_tensor.m: -------------------------------------------------------------------------------- 1 | function [my_tensor] = updateG_tensor(WT,K,sX,mu,gamma,V,mode) 2 | %mode = 3; 3 | for v=1:V 4 | W{v} = WT(:,:,v); 5 | end 6 | 7 | w = Tensor2Vector(W,sX(1),sX(2),sX(3),V); 8 | k = Tensor2Vector(K,sX(1),sX(2),sX(3),V); 9 | wk = k+w/mu; 10 | WKten = Vector2Tensor(wk,sX(1),sX(2),sX(3),V); 11 | 12 | WK = Tensor2Matrix(WKten,mode,sX(1),sX(2),sX(3)); 13 | WK1 = softth(WK,gamma{mode}/mu); 14 | my_tensor = reshape(WK1,sX); 15 | 16 | % %----------DEBUG------------% 17 | % kk = reshape(WK,[1,360*360*3])'; 18 | % for v=1:V 19 | % TMP{v} = my_tensor(:,:,v); 20 | % end 21 | % a = 1; 22 | % %%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | -------------------------------------------------------------------------------- /TensorRank/updateG_unfold.m: -------------------------------------------------------------------------------- 1 | function [my_tensor] = updateG_unfold(W,K,sX,mu,gamma,M,V) 2 | K_tensor = cat(3, K{:,:}); 3 | W_tensor = cat(3, W{:,:}); 4 | k = K_tensor(:); 5 | w = W_tensor(:); 6 | % 7 | % a = k+w/mu; 8 | % A_tensor = reshape(a, sX); 9 | % for m=1:M 10 | % if m<=2 11 | % X = reshape(A_tensor,[360*360,3]); 12 | % K_unfold = softth(X,gamma{m}/mu); 13 | % end 14 | % end 15 | 16 | for m=1:1 17 | %5 update Gm 18 | W_mat = Tensor2Matrix(W,m,sX(1),sX(2),sX(3)); 19 | K_mat = Tensor2Matrix(K,m,sX(1),sX(2),sX(3)); 20 | if m==1 21 | K_mat = K_mat+(1/mu*W_mat); 22 | end 23 | K_mat = softth(K_mat,gamma{m}/mu); 24 | 25 | vec = Matrix2Vector(K_mat,m,sX(1),sX(2),sX(3),V); 26 | Kmat = Vector2Tensor(vec,sX(1),sX(2),sX(3),V); 27 | end 28 | vec = Tensor2Vector(Kmat,sX(1),sX(2),sX(3),V); 29 | my_tensor = reshape(vec,sX); 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | 32 | -------------------------------------------------------------------------------- /demo.m: -------------------------------------------------------------------------------- 1 | clear 2 | load('ORL_mtv.mat'); 3 | num_views = length(X); 4 | for v=1:num_views 5 | X{v} = X{v}./(repmat(sqrt(sum(X{v}.^2,1)),size(X{v},1),1)+10e-10); 6 | end 7 | 8 | t1=cputime; 9 | lambda = 0.1; 10 | [acc,nmi,f,ri] = lt_msc(X, gt, lambda); 11 | t2=cputime-t1; -------------------------------------------------------------------------------- /lt_msc.m: -------------------------------------------------------------------------------- 1 | function [acc,nmi,f,ri] = lt_msc(X, gt, lambda) 2 | V = length(X); 3 | cls_num = length(unique(gt)); 4 | %% Note: each column is an sample (same as in LRR) 5 | %% 6 | K = length(X); N = size(X{1},2); %sample number 7 | 8 | for k=1:K 9 | Z{k} = zeros(N,N); %Z{2} = zeros(N,N); 10 | W{k} = zeros(N,N); 11 | G{k} = zeros(N,N); 12 | E{k} = zeros(size(X{k},1),N); %E{2} = zeros(size(X{k},1),N); 13 | Y{k} = zeros(size(X{k},1),N); %Y{2} = zeros(size(X{k},1),N); 14 | end 15 | 16 | w = zeros(N*N*K,1); 17 | g = zeros(N*N*K,1); 18 | dim1 = N;dim2 = N;dim3 = K; 19 | myNorm = 'tSVD_1'; 20 | sX = [N, N, K]; 21 | %set Default 22 | parOP = false; 23 | ABSTOL = 1e-6; 24 | RELTOL = 1e-4; 25 | 26 | 27 | Isconverg = 0;epson = 1e-7; 28 | ModCount = 3; %unfold_mode_number 29 | for v=1:ModCount 30 | para_ten{v} = lambda; 31 | end 32 | iter = 0; 33 | mu = 10e-5; max_mu = 10e10; pho_mu = 2; 34 | rho = 10e-5; max_rho = 10e12; pho_rho = 2; 35 | tic; 36 | 37 | Z_tensor = cat(3, Z{:,:}); 38 | G_tensor = cat(3, G{:,:}); 39 | W_tensor = cat(3, W{:,:}); 40 | 41 | for i=1:ModCount 42 | WT{i} = W_tensor; 43 | end 44 | while(Isconverg == 0) 45 | fprintf('----processing iter %d--------\n', iter+1); 46 | for k=1:K 47 | %1 update Z^k 48 | 49 | %Z{k}=inv(eye(N,N)+X{k}'*X{k})*(X{k}'*X{k} - X{k}'*E{k}+ F3_inv(G_bar){k} 50 | % + (X{k}'*Y{k} - W{k})/\mu); 51 | tmp = (X{k}'*Y{k} + mu*X{k}'*X{k} - mu*X{k}'*E{k} - W{k})./rho + G{k}; 52 | Z{k}=inv(eye(N,N)+ (mu/rho)*X{k}'*X{k})*tmp; 53 | 54 | %2 update E^k 55 | F = []; 56 | for v=1:K 57 | F = [F;X{v}-X{v}*Z{v}+Y{v}/mu]; 58 | end 59 | %F = [X{1}-X{1}*Z{1}+Y{1}/mu;X{2}-X{2}*Z{2}+Y{2}/mu;X{3}-X{3}*Z{3}+Y{3}/mu]; 60 | [Econcat] = solve_l1l2(F,lambda/mu); 61 | 62 | beg_ind = 0; 63 | end_ind = 0; 64 | for v=1:K 65 | if(v>1) 66 | beg_ind = beg_ind+size(X{v-1},1); 67 | else 68 | beg_ind = 1; 69 | end 70 | end_ind = end_ind+size(X{v},1); 71 | E{v} = Econcat(beg_ind:end_ind,:); 72 | end 73 | %3 update Yk 74 | %Y{k} = Y{k} + mu*(X{k}-X{k}*Z{k}-E{k}); 75 | Y{k} = Y{k} + mu*(X{k}-X{k}*Z{k}-E{k}); 76 | end 77 | 78 | %4 update G 79 | Z_tensor = cat(3, Z{:,:}); 80 | W_tensor = cat(3, W{:,:}); 81 | z = Z_tensor(:); 82 | w = W_tensor(:); 83 | % %twist-version 84 | % [g, objV] = wshrinkObj(z + 1/rho*w,1/rho,sX,0,3) ; 85 | % G_tensor = reshape(g, sX); 86 | % %5 update W 87 | % w = w + rho*(z - g); 88 | 89 | for umod=1:ModCount 90 | G_tensor = updateG_tensor(WT{umod},Z,sX,mu,para_ten,V,umod); 91 | WT{umod} = WT{umod}+mu*(Z_tensor-G_tensor); 92 | end 93 | 94 | % %record the iteration information 95 | % history.objval(iter+1) = objV; 96 | % objVal(iter+1) = objV; 97 | %% coverge condition 98 | Isconverg = 1; 99 | for k=1:K 100 | if (norm(X{k}-X{k}*Z{k}-E{k},inf)>epson) 101 | history.norm_Z = norm(X{k}-X{k}*Z{k}-E{k},inf); 102 | % fprintf(' norm_Z %7.10f ', history.norm_Z); 103 | Isconverg = 0; 104 | end 105 | 106 | G{k} = G_tensor(:,:,k); 107 | W_tensor = cat(3, WT{:,:}); 108 | W{k} = W_tensor(:,:,k); 109 | if (norm(Z{k}-G{k},inf)>epson) 110 | history.norm_Z_G = norm(Z{k}-G{k},inf); 111 | %fprintf('norm_Z_G %7.10f \n', history.norm_Z_G); 112 | Isconverg = 0; 113 | end 114 | end 115 | 116 | if (iter>50) 117 | Isconverg = 1; 118 | end 119 | iter = iter + 1; 120 | mu = min(mu*pho_mu, max_mu); 121 | rho = min(rho*pho_rho, max_rho); 122 | end 123 | S = 0; 124 | for k=1:K 125 | S = S + abs(Z{k})+abs(Z{k}'); 126 | end 127 | % figure(1); imagesc(S); 128 | % S_bar = CLR(S, cls_num, 0, 0 ); 129 | % figure(2); imagesc(S_bar); 130 | C = SpectralClustering(S,cls_num); 131 | [A nmi avgent] = compute_nmi(gt,C); 132 | %C = SpectralClustering(abs(Z{1})+abs(Z{1}'),cls_num); 133 | %[A nmi avgent] = compute_nmi(gt,C) 134 | % C = SpectralClustering(abs(Z{2})+abs(Z{2}'),cls_num); 135 | % [A nmi avgent] = compute_nmi(gt,C) 136 | % C = SpectralClustering(abs(Z{3})+abs(Z{3}'),cls_num); 137 | [A nmi avgent] = compute_nmi(gt,C); 138 | acc = Accuracy(C,double(gt)); 139 | [f,p,r] = compute_f(gt,C); 140 | [ar,ri,MI,HI]=RandIndex(gt,C); 141 | toc; 142 | %save('my_new_COIL20MV_res.mat','S','ACC','nmi','AR','f','p','r'); 143 | 144 | 145 | 146 | 147 | --------------------------------------------------------------------------------