-
Notifications
You must be signed in to change notification settings - Fork 0
/
NNDSVD.m
126 lines (109 loc) · 3.67 KB
/
NNDSVD.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
function [W,H] = NNDSVD(A,k,flag)
%
% This function implements the NNDSVD algorithm described in [1] for
% initialization of Nonnegative Matrix Factorization Algorithms.
%
% [W,H] = nndsvd(A,k,flag);
%
% INPUT
% ------------
%
% A : the input nonnegative m x n matrix A
% k : the rank of the computed factors W,H
% flag : indicates the variant of the NNDSVD Algorithm
% flag = 0 --> NNDSVD
% flag = 1 --> NNDSVDa
% flag = 2 --> NNDSVDar
%
% OUTPUT
% -------------
%
% W : nonnegative m x k matrix
% H : nonnegative k x n matrix
%
%
% References:
%
% [1] C. Boutsidis and E. Gallopoulos, SVD-based initialization: A head
% start for nonnegative matrix factorization, Pattern Recognition,
% Elsevier
%
% This code is kindly provided by the authors for research porpuses.
% - Efstratios Gallopoulos ([email protected])
% - Christos Boutsidis ([email protected])
%
% For any problems or questions please send an email to [email protected]
%--------------------------------------------------------------------------
%----------------------check the input matrix------------------------------
if numel(find(A<0)) > 0
error('The input matrix contains negative elements !')
end
%--------------------------------------------------------------------------
%size of the input matrix
[m,n] = size(A);
%the matrices of the factorization
W = zeros(m,k);
H = zeros(k,n);
% 1st SVD --> partial SVD rank-k to the input matrix A.
[U,S,V] = svds(A,k);
%choose the first singular triplet to be nonnegative
W(:,1) = sqrt(S(1,1)) * abs(U(:,1) );
H(1,:) = sqrt(S(1,1)) * abs(V(:,1)');
% 2nd SVD for the other factors (see table 1 in our paper)
for i=2:k
%k
%size(U)
%size(V)
uu = U(:,i); vv = V(:,i);
uup = pos(uu); uun = neg(uu) ;
vvp = pos(vv); vvn = neg(vv);
n_uup = norm(uup);
n_vvp = norm(vvp) ;
n_uun = norm(uun) ;
n_vvn = norm(vvn) ;
termp = n_uup*n_vvp; termn = n_uun*n_vvn;
if (termp >= termn)
W(:,i) = sqrt(S(i,i)*termp)*uup/n_uup;
H(i,:) = sqrt(S(i,i)*termp)*vvp'/n_vvp;
else
W(:,i) = sqrt(S(i,i)*termn)*uun/n_uun;
H(i,:) = sqrt(S(i,i)*termn)*vvn'/n_vvn;
end
end
%------------------------------------------------------------
%actually these numbers are zeros
W((W<0.0000000001))=0.1;
H((H<0.0000000001))=0.1;
% NNDSVDa: fill in the zero elements with the average
if flag==1
ind1 = find(W==0) ;
ind2 = find(H==0) ;
average = mean(A(:)) ;
W( ind1 ) = average ;
H( ind2 ) = average ;
% NNDSVDar: fill in the zero elements with random values in the space [0:average/100]
elseif flag==2
ind1 = find(W==0) ;
ind2 = find(H==0) ;
n1 = numel(ind1);
n2 = numel(ind2);
average = mean(A(:)) ;
W( ind1 ) = (average*rand(n1,1)./100) ;
H( ind2 ) = (average*rand(n2,1)./100) ;
end
end
%--------------------------------------------------------------------------
%end of the nndsvd function
%This function sets to zero the negative elements of a matrix
%--------------------------------------------------------------------------
function [Ap] = pos(A)
Ap = (A>=0).*A;
end
%--------------------------------------------------------------------------
%This functions sets to zero the positive elements of a matrix and takes
%the absolute value of the negative elements
%--------------------------------------------------------------------------
function [Am] = neg(A);
Am = (A<0).*(-A);
end
%--------------------------------------------------------------------------