Mercurial > hg > segmentation
comparison pymf/nndsvd.py @ 0:26838b1f560f
initial commit of a segmenter project
author | mi tian |
---|---|
date | Thu, 02 Apr 2015 18:09:27 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:26838b1f560f |
---|---|
1 #!/usr/bin/python | |
2 # | |
3 # Copyright (C) Christian Thurau, 2010. | |
4 # Licensed under the GNU General Public License (GPL). | |
5 # http://www.gnu.org/licenses/gpl.txt | |
6 #$Id$ | |
7 """ | |
8 PyMF Non-negative Double Singular Value Decompositions. | |
9 | |
10 NNDSVD: Class for Non-negative Double Singular Value Decompositions [1] | |
11 | |
12 [1] C. Boutsidis and E. Gallopoulos (2008), SVD based initialization: A head | |
13 start for nonnegative matrix factorization, Pattern Recognition, 41, 1350-1362 | |
14 """ | |
15 | |
16 | |
17 import numpy as np | |
18 | |
19 from nmf import NMF | |
20 from svd import SVD | |
21 | |
22 __all__ = ["NNDSVD"] | |
23 | |
24 class NNDSVD(NMF): | |
25 """ | |
26 NNDSVD(data, num_bases=4) | |
27 | |
28 | |
29 Non-negative Double Singular Value Decompositions. Factorize a data | |
30 matrix into two matrices s.t. F = | data - W*H | = | is minimal. H, and | |
31 W are restricted to non-negative data. NNDSVD is primarily used for | |
32 initializing NMF. | |
33 | |
34 Parameters | |
35 ---------- | |
36 data : array_like, shape (_data_dimension, _num_samples) | |
37 the input data | |
38 num_bases: int, optional | |
39 Number of bases to compute (column rank of W and row rank of H). | |
40 4 (default) | |
41 | |
42 Attributes | |
43 ---------- | |
44 W : "data_dimension x num_bases" matrix of basis vectors | |
45 H : "num bases x num_samples" matrix of coefficients | |
46 ferr : frobenius norm (after calling .factorize()) | |
47 | |
48 Example | |
49 ------- | |
50 Applying NNDSVD to some rather stupid data set: | |
51 | |
52 >>> import numpy as np | |
53 >>> data = np.array([[1.0, 0.0, 2.0], [0.0, 1.0, 1.0]]) | |
54 >>> nndsvd_mdl = NNDSVD(data, num_bases=2) | |
55 >>> nndsvd_mdl.factorize() | |
56 | |
57 The basis vectors are now stored in nndsvd_mdl.W, the coefficients in | |
58 nndsvd_mdl.H. To initialize NMF with nndsvd_mdl.W, nndsvd_mdl.H | |
59 simply copy W to nmf_mdl.W and H to nmf_mdl.H: | |
60 | |
61 >>> data = np.array([[1.5], [1.2]]) | |
62 >>> W = np.array([[1.0, 0.0], [0.0, 1.0]]) | |
63 >>> nmf_mdl = NMF(data, num_bases=2) | |
64 >>> nmf_mdl.W = nndsvd_mdl.W | |
65 >>> nmf_mdl.H = nndsvd_mdl.H | |
66 >>> nmf_mdl.factorize(niter=20) | |
67 | |
68 The result is a set of (more optimal) coefficients nmf_mdl.H, nmf_mdl.W. | |
69 """ | |
70 def init_w(self): | |
71 self.W = np.zeros((self._data_dimension, self._num_bases)) | |
72 | |
73 def init_h(self): | |
74 self.H = np.zeros((self._num_bases, self._num_samples)) | |
75 | |
76 def update_h(self): | |
77 pass | |
78 | |
79 def update_w(self): | |
80 svd_mdl = SVD(self.data) | |
81 svd_mdl.factorize() | |
82 | |
83 U, S, V = svd_mdl.U, svd_mdl.S, svd_mdl.V | |
84 | |
85 # The first left singular vector is nonnegative | |
86 # (abs is only used as values could be all negative) | |
87 self.W[:,0] = np.sqrt(S[0,0]) * np.abs(U[:,0]) | |
88 | |
89 #The first right singular vector is nonnegative | |
90 self.H[0,:] = np.sqrt(S[0,0]) * np.abs(V[0,:].T) | |
91 | |
92 for i in range(1,self._num_bases): | |
93 # Form the rank one factor | |
94 Tmp = np.dot(U[:,i:i+1]*S[i,i], V[i:i+1,:]) | |
95 | |
96 # zero out the negative elements | |
97 Tmp = np.where(Tmp < 0, 0.0, Tmp) | |
98 | |
99 # Apply 2nd SVD | |
100 svd_mdl_2 = SVD(Tmp) | |
101 svd_mdl_2.factorize() | |
102 u, s, v = svd_mdl_2.U, svd_mdl_2.S, svd_mdl_2.V | |
103 | |
104 # The first left singular vector is nonnegative | |
105 self.W[:,i] = np.sqrt(s[0,0]) * np.abs(u[:,0]) | |
106 | |
107 #The first right singular vector is nonnegative | |
108 self.H[i,:] = np.sqrt(s[0,0]) * np.abs(v[0,:].T) | |
109 | |
110 def factorize(self, niter=1, show_progress=False, | |
111 compute_w=True, compute_h=True, compute_err=True): | |
112 | |
113 # enforce certain default values, otherwise it won't work | |
114 NMF.factorize(self, niter=1, show_progress=show_progress, | |
115 compute_w=True, compute_h=True, compute_err=compute_err) | |
116 | |
117 if __name__ == "__main__": | |
118 import doctest | |
119 doctest.testmod() |