nikcleju@10
|
1 # -*- coding: utf-8 -*-
|
nikcleju@10
|
2 """
|
nikcleju@10
|
3 Created on Sat Nov 05 18:08:40 2011
|
nikcleju@10
|
4
|
nikcleju@10
|
5 @author: Nic
|
nikcleju@10
|
6 """
|
nikcleju@10
|
7
|
nikcleju@19
|
8 import numpy as np
|
nikcleju@22
|
9 import scipy.io
|
nikcleju@22
|
10 import math
|
nikcleju@29
|
11
|
nikcleju@10
|
12 import pyCSalgos
|
nikcleju@19
|
13 import pyCSalgos.GAP.GAP
|
nikcleju@19
|
14 import pyCSalgos.SL0.SL0_approx
|
nikcleju@10
|
15
|
nikcleju@29
|
16 #==========================
|
nikcleju@29
|
17 # Algorithm functions
|
nikcleju@29
|
18 #==========================
|
nikcleju@22
|
19 def run_gap(y,M,Omega,epsilon):
|
nikcleju@19
|
20 gapparams = {"num_iteration" : 1000,\
|
nikcleju@19
|
21 "greedy_level" : 0.9,\
|
nikcleju@19
|
22 "stopping_coefficient_size" : 1e-4,\
|
nikcleju@19
|
23 "l2solver" : 'pseudoinverse',\
|
nikcleju@19
|
24 "noise_level": epsilon}
|
nikcleju@22
|
25 return pyCSalgos.GAP.GAP.GAP(y,M,M.T,Omega,Omega.T,gapparams,np.zeros(Omega.shape[1]))[0]
|
nikcleju@29
|
26
|
nikcleju@22
|
27 def run_sl0(y,M,Omega,D,U,S,Vt,epsilon,lbd):
|
nikcleju@19
|
28
|
nikcleju@19
|
29 N,n = Omega.shape
|
nikcleju@22
|
30 #D = np.linalg.pinv(Omega)
|
nikcleju@22
|
31 #U,S,Vt = np.linalg.svd(D)
|
nikcleju@19
|
32 aggDupper = np.dot(M,D)
|
nikcleju@19
|
33 aggDlower = Vt[-(N-n):,:]
|
nikcleju@19
|
34 aggD = np.concatenate((aggDupper, lbd * aggDlower))
|
nikcleju@19
|
35 aggy = np.concatenate((y, np.zeros(N-n)))
|
nikcleju@19
|
36
|
nikcleju@22
|
37 sigmamin = 0.001
|
nikcleju@22
|
38 sigma_decrease_factor = 0.5
|
nikcleju@20
|
39 mu_0 = 2
|
nikcleju@20
|
40 L = 10
|
nikcleju@22
|
41 return pyCSalgos.SL0.SL0_approx.SL0_approx(aggD,aggy,epsilon,sigmamin,sigma_decrease_factor,mu_0,L)
|
nikcleju@10
|
42
|
nikcleju@27
|
43 def run_bp(y,M,Omega,D,U,S,Vt,epsilon,lbd):
|
nikcleju@27
|
44
|
nikcleju@27
|
45 N,n = Omega.shape
|
nikcleju@27
|
46 #D = np.linalg.pinv(Omega)
|
nikcleju@27
|
47 #U,S,Vt = np.linalg.svd(D)
|
nikcleju@27
|
48 aggDupper = np.dot(M,D)
|
nikcleju@27
|
49 aggDlower = Vt[-(N-n):,:]
|
nikcleju@27
|
50 aggD = np.concatenate((aggDupper, lbd * aggDlower))
|
nikcleju@27
|
51 aggy = np.concatenate((y, np.zeros(N-n)))
|
nikcleju@27
|
52
|
nikcleju@27
|
53 sigmamin = 0.001
|
nikcleju@27
|
54 sigma_decrease_factor = 0.5
|
nikcleju@27
|
55 mu_0 = 2
|
nikcleju@27
|
56 L = 10
|
nikcleju@27
|
57 return pyCSalgos.SL0.SL0_approx.SL0_approx(aggD,aggy,epsilon,sigmamin,sigma_decrease_factor,mu_0,L)
|
nikcleju@27
|
58
|
nikcleju@29
|
59 #==========================
|
nikcleju@29
|
60 # Define tuples (algorithm function, name)
|
nikcleju@29
|
61 #==========================
|
nikcleju@22
|
62 gap = (run_gap, 'GAP')
|
nikcleju@22
|
63 sl0 = (run_sl0, 'SL0_approx')
|
nikcleju@29
|
64 bp = (run_bp, 'BP')
|
nikcleju@10
|
65
|
nikcleju@22
|
66 # Define which algorithms to run
|
nikcleju@22
|
67 # 1. Algorithms not depending on lambda
|
nikcleju@22
|
68 algosN = gap, # tuple
|
nikcleju@22
|
69 # 2. Algorithms depending on lambda (our ABS approach)
|
nikcleju@22
|
70 algosL = sl0, # tuple
|
nikcleju@29
|
71
|
nikcleju@29
|
72 #==========================
|
nikcleju@29
|
73 # Interface functions
|
nikcleju@29
|
74 #==========================
|
nikcleju@29
|
75 def run_multiproc(ncpus=None):
|
nikcleju@29
|
76 d,sigma,deltas,rhos,lambdas,numvects,SNRdb,dosavedata,savedataname = standard_params()
|
nikcleju@29
|
77 run_multi(algosN, algosL, d,sigma,deltas,rhos,lambdas,numvects,SNRdb,dosavedata=dosavedata,savedataname=savedataname,\
|
nikcleju@29
|
78 doparallel=True, ncpus=ncpus)
|
nikcleju@22
|
79
|
nikcleju@29
|
80 def run():
|
nikcleju@29
|
81 d,sigma,deltas,rhos,lambdas,numvects,SNRdb,dosavedata,savedataname = standard_params()
|
nikcleju@29
|
82 run_multi(algosN, algosL, d,sigma,deltas,rhos,lambdas,numvects,SNRdb,dosavedata=dosavedata,savedataname=savedataname,\
|
nikcleju@29
|
83 doparallel=False)
|
nikcleju@19
|
84
|
nikcleju@29
|
85 def standard_params():
|
nikcleju@29
|
86 #Set up standard experiment parameters
|
nikcleju@25
|
87 d = 50.0;
|
nikcleju@22
|
88 sigma = 2.0
|
nikcleju@27
|
89 #deltas = np.arange(0.05,1.,0.05)
|
nikcleju@27
|
90 #rhos = np.arange(0.05,1.,0.05)
|
nikcleju@27
|
91 deltas = np.array([0.05, 0.45, 0.95])
|
nikcleju@27
|
92 rhos = np.array([0.05, 0.45, 0.95])
|
nikcleju@22
|
93 #deltas = np.array([0.05])
|
nikcleju@22
|
94 #rhos = np.array([0.05])
|
nikcleju@22
|
95 #delta = 0.8;
|
nikcleju@22
|
96 #rho = 0.15;
|
nikcleju@27
|
97 numvects = 100; # Number of vectors to generate
|
nikcleju@20
|
98 SNRdb = 20.; # This is norm(signal)/norm(noise), so power, not energy
|
nikcleju@22
|
99 # Values for lambda
|
nikcleju@22
|
100 #lambdas = [0 10.^linspace(-5, 4, 10)];
|
nikcleju@25
|
101 #lambdas = np.concatenate((np.array([0]), 10**np.linspace(-5, 4, 10)))
|
nikcleju@25
|
102 lambdas = np.array([0., 0.0001, 0.01, 1, 100, 10000])
|
nikcleju@29
|
103
|
nikcleju@29
|
104 dosavedata = True
|
nikcleju@29
|
105 savedataname = 'ABSapprox.mat'
|
nikcleju@29
|
106
|
nikcleju@29
|
107
|
nikcleju@29
|
108 return d,sigma,deltas,rhos,lambdas,numvects,SNRdb,dosavedata,savedataname
|
nikcleju@29
|
109
|
nikcleju@29
|
110 #==========================
|
nikcleju@29
|
111 # Main functions
|
nikcleju@29
|
112 #==========================
|
nikcleju@29
|
113 def run_multi(algosN, algosL, d, sigma, deltas, rhos, lambdas, numvects, SNRdb,
|
nikcleju@29
|
114 doparallel=False, ncpus=None,\
|
nikcleju@29
|
115 doshowplot=False, dosaveplot=False, saveplotbase=None, saveplotexts=None,\
|
nikcleju@29
|
116 dosavedata=False, savedataname=None):
|
nikcleju@29
|
117
|
nikcleju@29
|
118 if doparallel:
|
nikcleju@29
|
119 from multiprocessing import Pool
|
nikcleju@29
|
120
|
nikcleju@29
|
121 # TODO: load different engine for matplotlib that allows saving without showing
|
nikcleju@29
|
122 try:
|
nikcleju@29
|
123 import matplotlib.pyplot as plt
|
nikcleju@29
|
124 except:
|
nikcleju@29
|
125 dosaveplot = False
|
nikcleju@29
|
126 doshowplot = False
|
nikcleju@29
|
127 if dosaveplot and doshowplot:
|
nikcleju@29
|
128 import matplotlib.cm as cm
|
nikcleju@29
|
129
|
nikcleju@29
|
130 nalgosN = len(algosN)
|
nikcleju@29
|
131 nalgosL = len(algosL)
|
nikcleju@29
|
132
|
nikcleju@22
|
133 meanmatrix = dict()
|
nikcleju@22
|
134 for i,algo in zip(np.arange(nalgosN),algosN):
|
nikcleju@22
|
135 meanmatrix[algo[1]] = np.zeros((rhos.size, deltas.size))
|
nikcleju@22
|
136 for i,algo in zip(np.arange(nalgosL),algosL):
|
nikcleju@22
|
137 meanmatrix[algo[1]] = np.zeros((lambdas.size, rhos.size, deltas.size))
|
nikcleju@22
|
138
|
nikcleju@29
|
139 # Prepare parameters
|
nikcleju@29
|
140 jobparams = []
|
nikcleju@22
|
141 for idelta,delta in zip(np.arange(deltas.size),deltas):
|
nikcleju@22
|
142 for irho,rho in zip(np.arange(rhos.size),rhos):
|
nikcleju@22
|
143
|
nikcleju@22
|
144 # Generate data and operator
|
nikcleju@29
|
145 Omega,x0,y,M,realnoise = generateData(d,sigma,delta,rho,numvects,SNRdb)
|
nikcleju@22
|
146
|
nikcleju@29
|
147 #Save the parameters, and run after
|
nikcleju@24
|
148 print "***** delta = ",delta," rho = ",rho
|
nikcleju@29
|
149 jobparams.append((algosN,algosL, Omega,y,lambdas,realnoise,M,x0))
|
nikcleju@29
|
150
|
nikcleju@29
|
151 # Run
|
nikcleju@29
|
152 jobresults = []
|
nikcleju@29
|
153 if doparallel:
|
nikcleju@29
|
154 pool = Pool(4)
|
nikcleju@29
|
155 jobresults = pool.map(run_once_tuple,jobparams)
|
nikcleju@29
|
156 else:
|
nikcleju@29
|
157 for jobparam in jobparams:
|
nikcleju@29
|
158 jobresults.append(run_once(algosN,algosL,Omega,y,lambdas,realnoise,M,x0))
|
nikcleju@29
|
159
|
nikcleju@29
|
160 # Read results
|
nikcleju@29
|
161 idx = 0
|
nikcleju@29
|
162 for idelta,delta in zip(np.arange(deltas.size),deltas):
|
nikcleju@29
|
163 for irho,rho in zip(np.arange(rhos.size),rhos):
|
nikcleju@29
|
164 mrelerrN,mrelerrL = jobresults[idx]
|
nikcleju@29
|
165 idx = idx+1
|
nikcleju@22
|
166 for algotuple in algosN:
|
nikcleju@22
|
167 meanmatrix[algotuple[1]][irho,idelta] = 1 - mrelerrN[algotuple[1]]
|
nikcleju@22
|
168 if meanmatrix[algotuple[1]][irho,idelta] < 0 or math.isnan(meanmatrix[algotuple[1]][irho,idelta]):
|
nikcleju@22
|
169 meanmatrix[algotuple[1]][irho,idelta] = 0
|
nikcleju@22
|
170 for algotuple in algosL:
|
nikcleju@22
|
171 for ilbd in np.arange(lambdas.size):
|
nikcleju@22
|
172 meanmatrix[algotuple[1]][ilbd,irho,idelta] = 1 - mrelerrL[algotuple[1]][ilbd]
|
nikcleju@22
|
173 if meanmatrix[algotuple[1]][ilbd,irho,idelta] < 0 or math.isnan(meanmatrix[algotuple[1]][ilbd,irho,idelta]):
|
nikcleju@22
|
174 meanmatrix[algotuple[1]][ilbd,irho,idelta] = 0
|
nikcleju@22
|
175
|
nikcleju@22
|
176 # # Prepare matrices to show
|
nikcleju@22
|
177 # showmats = dict()
|
nikcleju@22
|
178 # for i,algo in zip(np.arange(nalgosN),algosN):
|
nikcleju@22
|
179 # showmats[algo[1]] = np.zeros(rhos.size, deltas.size)
|
nikcleju@22
|
180 # for i,algo in zip(np.arange(nalgosL),algosL):
|
nikcleju@22
|
181 # showmats[algo[1]] = np.zeros(lambdas.size, rhos.size, deltas.size)
|
nikcleju@22
|
182
|
nikcleju@22
|
183 # Save
|
nikcleju@29
|
184 if dosavedata:
|
nikcleju@29
|
185 tosave = dict()
|
nikcleju@29
|
186 tosave['meanmatrix'] = meanmatrix
|
nikcleju@29
|
187 tosave['d'] = d
|
nikcleju@29
|
188 tosave['sigma'] = sigma
|
nikcleju@29
|
189 tosave['deltas'] = deltas
|
nikcleju@29
|
190 tosave['rhos'] = rhos
|
nikcleju@29
|
191 tosave['numvects'] = numvects
|
nikcleju@29
|
192 tosave['SNRdb'] = SNRdb
|
nikcleju@29
|
193 tosave['lambdas'] = lambdas
|
nikcleju@29
|
194 try:
|
nikcleju@29
|
195 scipy.io.savemat(savedataname, tosave)
|
nikcleju@29
|
196 except:
|
nikcleju@29
|
197 print "Save error"
|
nikcleju@22
|
198 # Show
|
nikcleju@29
|
199 if doshowplot or dosaveplot:
|
nikcleju@27
|
200 for algotuple in algosN:
|
nikcleju@29
|
201 algoname = algotuple[1]
|
nikcleju@27
|
202 plt.figure()
|
nikcleju@29
|
203 plt.imshow(meanmatrix[algoname], cmap=cm.gray, interpolation='nearest',origin='lower')
|
nikcleju@29
|
204 if dosaveplot:
|
nikcleju@29
|
205 for ext in saveplotexts:
|
nikcleju@29
|
206 plt.savefig(saveplotbase + algoname + '.' + ext)
|
nikcleju@27
|
207 for algotuple in algosL:
|
nikcleju@29
|
208 algoname = algotuple[1]
|
nikcleju@27
|
209 for ilbd in np.arange(lambdas.size):
|
nikcleju@27
|
210 plt.figure()
|
nikcleju@29
|
211 plt.imshow(meanmatrix[algoname][ilbd], cmap=cm.gray, interpolation='nearest',origin='lower')
|
nikcleju@29
|
212 if dosaveplot:
|
nikcleju@29
|
213 for ext in saveplotexts:
|
nikcleju@29
|
214 plt.savefig(saveplotbase + algoname + lambdas[ilbd] + '.' + ext)
|
nikcleju@29
|
215 if doshowplot:
|
nikcleju@29
|
216 plt.show()
|
nikcleju@29
|
217
|
nikcleju@22
|
218 print "Finished."
|
nikcleju@22
|
219
|
nikcleju@29
|
220 def run_once_tuple(t):
|
nikcleju@29
|
221 return run_once(*t)
|
nikcleju@10
|
222
|
nikcleju@29
|
223 def run_once(algosN,algosL,Omega,y,lambdas,realnoise,M,x0):
|
nikcleju@22
|
224
|
nikcleju@22
|
225 d = Omega.shape[1]
|
nikcleju@22
|
226
|
nikcleju@22
|
227 nalgosN = len(algosN)
|
nikcleju@22
|
228 nalgosL = len(algosL)
|
nikcleju@10
|
229
|
nikcleju@19
|
230 xrec = dict()
|
nikcleju@19
|
231 err = dict()
|
nikcleju@19
|
232 relerr = dict()
|
nikcleju@22
|
233
|
nikcleju@22
|
234 # Prepare storage variables for algorithms non-Lambda
|
nikcleju@22
|
235 for i,algo in zip(np.arange(nalgosN),algosN):
|
nikcleju@22
|
236 xrec[algo[1]] = np.zeros((d, y.shape[1]))
|
nikcleju@22
|
237 err[algo[1]] = np.zeros(y.shape[1])
|
nikcleju@22
|
238 relerr[algo[1]] = np.zeros(y.shape[1])
|
nikcleju@22
|
239 # Prepare storage variables for algorithms with Lambda
|
nikcleju@22
|
240 for i,algo in zip(np.arange(nalgosL),algosL):
|
nikcleju@22
|
241 xrec[algo[1]] = np.zeros((lambdas.size, d, y.shape[1]))
|
nikcleju@22
|
242 err[algo[1]] = np.zeros((lambdas.size, y.shape[1]))
|
nikcleju@22
|
243 relerr[algo[1]] = np.zeros((lambdas.size, y.shape[1]))
|
nikcleju@19
|
244
|
nikcleju@22
|
245 # Run algorithms non-Lambda
|
nikcleju@22
|
246 for iy in np.arange(y.shape[1]):
|
nikcleju@22
|
247 for algofunc,strname in algosN:
|
nikcleju@22
|
248 epsilon = 1.1 * np.linalg.norm(realnoise[:,iy])
|
nikcleju@22
|
249 xrec[strname][:,iy] = algofunc(y[:,iy],M,Omega,epsilon)
|
nikcleju@22
|
250 err[strname][iy] = np.linalg.norm(x0[:,iy] - xrec[strname][:,iy])
|
nikcleju@22
|
251 relerr[strname][iy] = err[strname][iy] / np.linalg.norm(x0[:,iy])
|
nikcleju@22
|
252 for algotuple in algosN:
|
nikcleju@22
|
253 print algotuple[1],' : avg relative error = ',np.mean(relerr[strname])
|
nikcleju@22
|
254
|
nikcleju@22
|
255 # Run algorithms with Lambda
|
nikcleju@19
|
256 for ilbd,lbd in zip(np.arange(lambdas.size),lambdas):
|
nikcleju@19
|
257 for iy in np.arange(y.shape[1]):
|
nikcleju@22
|
258 D = np.linalg.pinv(Omega)
|
nikcleju@22
|
259 U,S,Vt = np.linalg.svd(D)
|
nikcleju@22
|
260 for algofunc,strname in algosL:
|
nikcleju@19
|
261 epsilon = 1.1 * np.linalg.norm(realnoise[:,iy])
|
nikcleju@22
|
262 gamma = algofunc(y[:,iy],M,Omega,D,U,S,Vt,epsilon,lbd)
|
nikcleju@22
|
263 xrec[strname][ilbd,:,iy] = np.dot(D,gamma)
|
nikcleju@19
|
264 err[strname][ilbd,iy] = np.linalg.norm(x0[:,iy] - xrec[strname][ilbd,:,iy])
|
nikcleju@19
|
265 relerr[strname][ilbd,iy] = err[strname][ilbd,iy] / np.linalg.norm(x0[:,iy])
|
nikcleju@19
|
266 print 'Lambda = ',lbd,' :'
|
nikcleju@22
|
267 for algotuple in algosL:
|
nikcleju@22
|
268 print ' ',algotuple[1],' : avg relative error = ',np.mean(relerr[strname][ilbd,:])
|
nikcleju@10
|
269
|
nikcleju@22
|
270 # Prepare results
|
nikcleju@22
|
271 mrelerrN = dict()
|
nikcleju@22
|
272 for algotuple in algosN:
|
nikcleju@22
|
273 mrelerrN[algotuple[1]] = np.mean(relerr[algotuple[1]])
|
nikcleju@22
|
274 mrelerrL = dict()
|
nikcleju@22
|
275 for algotuple in algosL:
|
nikcleju@22
|
276 mrelerrL[algotuple[1]] = np.mean(relerr[algotuple[1]],1)
|
nikcleju@22
|
277
|
nikcleju@22
|
278 return mrelerrN,mrelerrL
|
nikcleju@29
|
279
|
nikcleju@29
|
280 def generateData(d,sigma,delta,rho,numvects,SNRdb):
|
nikcleju@29
|
281
|
nikcleju@29
|
282 # Process parameters
|
nikcleju@29
|
283 noiselevel = 1.0 / (10.0**(SNRdb/10.0));
|
nikcleju@29
|
284 p = round(sigma*d);
|
nikcleju@29
|
285 m = round(delta*d);
|
nikcleju@29
|
286 l = round(d - rho*m);
|
nikcleju@29
|
287
|
nikcleju@29
|
288 # Generate Omega and data based on parameters
|
nikcleju@29
|
289 Omega = pyCSalgos.GAP.GAP.Generate_Analysis_Operator(d, p);
|
nikcleju@29
|
290 # Optionally make Omega more coherent
|
nikcleju@29
|
291 U,S,Vt = np.linalg.svd(Omega);
|
nikcleju@29
|
292 Sdnew = S * (1+np.arange(S.size)) # Make D coherent, not Omega!
|
nikcleju@29
|
293 Snew = np.vstack((np.diag(Sdnew), np.zeros((Omega.shape[0] - Omega.shape[1], Omega.shape[1]))))
|
nikcleju@29
|
294 Omega = np.dot(U , np.dot(Snew,Vt))
|
nikcleju@29
|
295
|
nikcleju@29
|
296 # Generate data
|
nikcleju@29
|
297 x0,y,M,Lambda,realnoise = pyCSalgos.GAP.GAP.Generate_Data_Known_Omega(Omega, d,p,m,l,noiselevel, numvects,'l0');
|
nikcleju@29
|
298
|
nikcleju@29
|
299 return Omega,x0,y,M,realnoise
|
nikcleju@22
|
300
|
nikcleju@19
|
301 # Script main
|
nikcleju@19
|
302 if __name__ == "__main__":
|
nikcleju@27
|
303 #import cProfile
|
nikcleju@27
|
304 #cProfile.run('mainrun()', 'profile')
|
nikcleju@29
|
305 run()
|