annotate OMP/omp_test.py @ 1:2a2abf5092f8

Organized into test file and lib files Changed sklearn cholesky function to behave as the others: tol does not override number of atoms, but the two conditions work together
author nikcleju
date Thu, 20 Oct 2011 21:06:06 +0000
parents
children
rev   line source
nikcleju@1 1 """
nikcleju@1 2 #=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
nikcleju@1 3 # Bob L. Sturm <bst@create.aau.dk> 20111018
nikcleju@1 4 # Department of Architecture, Design and Media Technology
nikcleju@1 5 # Aalborg University Copenhagen
nikcleju@1 6 # Lautrupvang 15, 2750 Ballerup, Denmark
nikcleju@1 7 #=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
nikcleju@1 8 """
nikcleju@1 9
nikcleju@1 10 import unittest
nikcleju@1 11
nikcleju@1 12 import numpy as np
nikcleju@1 13 from sklearn.utils import check_random_state
nikcleju@1 14 import time
nikcleju@1 15
nikcleju@1 16 from omp_sk_bugfix import orthogonal_mp
nikcleju@1 17 from omp_QR import greed_omp_qr
nikcleju@1 18 from omp_QR import omp_qr
nikcleju@1 19
nikcleju@1 20 """
nikcleju@1 21 Run a problem suite involving sparse vectors in
nikcleju@1 22 ambientDimension dimensional space, with a resolution
nikcleju@1 23 in the phase plane of numGradations x numGradations,
nikcleju@1 24 and at each indeterminacy and sparsity pair run
nikcleju@1 25 numTrials independent trials.
nikcleju@1 26
nikcleju@1 27 Outputs a text file denoting successes at each phase point.
nikcleju@1 28 For more on phase transitions, see:
nikcleju@1 29 D. L. Donoho and J. Tanner, "Precise undersampling theorems,"
nikcleju@1 30 Proc. IEEE, vol. 98, no. 6, pp. 913-924, June 2010.
nikcleju@1 31 """
nikcleju@1 32
nikcleju@1 33 class CompareResults(unittest.TestCase):
nikcleju@1 34
nikcleju@1 35 def testCompareResults(self):
nikcleju@1 36 """OMP results should be almost the same with all implementations"""
nikcleju@1 37 ambientDimension = 400
nikcleju@1 38 numGradations = 30
nikcleju@1 39 numTrials = 1
nikcleju@1 40 runProblemSuite(ambientDimension,numGradations,numTrials, verbose=False)
nikcleju@1 41
nikcleju@1 42
nikcleju@1 43
nikcleju@1 44 def runProblemSuite(ambientDimension,numGradations,numTrials, verbose):
nikcleju@1 45
nikcleju@1 46 idx = np.arange(ambientDimension)
nikcleju@1 47 phaseDelta = np.linspace(0.05,1,numGradations)
nikcleju@1 48 phaseRho = np.linspace(0.05,1,numGradations)
nikcleju@1 49 success = np.zeros((numGradations, numGradations))
nikcleju@1 50
nikcleju@1 51 #Nic: init timers
nikcleju@1 52 t1all = 0
nikcleju@1 53 t2all = 0
nikcleju@1 54 t3all = 0
nikcleju@1 55
nikcleju@1 56 deltaCounter = 0
nikcleju@1 57 # delta is number of measurements/
nikcleju@1 58 for delta in phaseDelta[:17]:
nikcleju@1 59 rhoCounter = 0
nikcleju@1 60 for rho in phaseRho:
nikcleju@1 61 if verbose:
nikcleju@1 62 print(deltaCounter,rhoCounter)
nikcleju@1 63
nikcleju@1 64 numMeasurements = int(delta*ambientDimension)
nikcleju@1 65 sparsity = int(rho*numMeasurements)
nikcleju@1 66 # how do I set the following to be random each time?
nikcleju@1 67 generator = check_random_state(100)
nikcleju@1 68 # create unit norm dictionary
nikcleju@1 69 D = generator.randn(numMeasurements, ambientDimension)
nikcleju@1 70 D /= np.sqrt(np.sum((D ** 2), axis=0))
nikcleju@1 71 # compute Gramian (for efficiency)
nikcleju@1 72 DTD = np.dot(D.T,D)
nikcleju@1 73
nikcleju@1 74 successCounter = 0
nikcleju@1 75 trial = numTrials
nikcleju@1 76 while trial > 0:
nikcleju@1 77 # generate sparse signal with a minimum non-zero value
nikcleju@1 78 x = np.zeros((ambientDimension, 1))
nikcleju@1 79 idx2 = idx
nikcleju@1 80 generator.shuffle(idx2)
nikcleju@1 81 idx3 = idx2[:sparsity]
nikcleju@1 82 while np.min(np.abs(x[idx3,0])) < 1e-10 :
nikcleju@1 83 x[idx3,0] = generator.randn(sparsity)
nikcleju@1 84 # sense sparse signal
nikcleju@1 85 y = np.dot(D, x)
nikcleju@1 86
nikcleju@1 87 # Nic: Use sparsify OMP function (translated from Matlab)
nikcleju@1 88 ompopts = dict({'stopCrit':'M', 'stopTol':2*sparsity})
nikcleju@1 89 starttime = time.time() # start timer
nikcleju@1 90 x_r2, errs, times = greed_omp_qr(y.squeeze().copy(), D.copy(), D.shape[1], ompopts)
nikcleju@1 91 t2all = t2all + time.time() - starttime # stop timer
nikcleju@1 92 idx_r2 = np.nonzero(x_r2)[0]
nikcleju@1 93
nikcleju@1 94 # run to two times expected sparsity, or tolerance
nikcleju@1 95 # why? Often times, OMP can retrieve the correct solution
nikcleju@1 96 # when it is run for more than the expected sparsity
nikcleju@1 97 #x_r, idx_r = omp_qr(y,D,DTD,2*sparsity,1e-5)
nikcleju@1 98 # Nic: adjust tolerance to match with other function
nikcleju@1 99 starttime = time.time() # start timer
nikcleju@1 100 x_r, idx_r = omp_qr(y.copy(),D.copy(),DTD.copy(),2*sparsity,numMeasurements*1e-14/np.vdot(y,y))
nikcleju@1 101 t1all = t1all + time.time() - starttime # stop timer
nikcleju@1 102
nikcleju@1 103 # Nic: test sklearn omp
nikcleju@1 104 starttime = time.time() # start timer
nikcleju@1 105 x_r3 = orthogonal_mp(D.copy(), y.copy(), 2*sparsity, tol=numMeasurements*1e-14, precompute_gram=False, copy_X=True)
nikcleju@1 106 idx_r3 = np.nonzero(x_r3)[0]
nikcleju@1 107 t3all = t3all + time.time() - starttime # stop timer
nikcleju@1 108
nikcleju@1 109 # Nic: compare results
nikcleju@1 110 if verbose:
nikcleju@1 111 print 'diff1 = ',np.linalg.norm(x_r.squeeze() - x_r2.squeeze())
nikcleju@1 112 print 'diff2 = ',np.linalg.norm(x_r.squeeze() - x_r3.squeeze())
nikcleju@1 113 print 'diff3 = ',np.linalg.norm(x_r2.squeeze() - x_r3.squeeze())
nikcleju@1 114 print "Bob's total time = ", t1all
nikcleju@1 115 print "Nic's total time = ", t2all
nikcleju@1 116 print "Skl's total time = ", t3all
nikcleju@1 117 if np.linalg.norm(x_r.squeeze() - x_r2.squeeze()) > 1e-6 or \
nikcleju@1 118 np.linalg.norm(x_r.squeeze() - x_r3.squeeze()) > 1e-6 or \
nikcleju@1 119 np.linalg.norm(x_r2.squeeze() - x_r3.squeeze()) > 1e-6:
nikcleju@1 120 if verbose:
nikcleju@1 121 print "STOP: Different results"
nikcleju@1 122 print "Bob's residual: ||y - D x_r ||_2 = ",np.linalg.norm(y.squeeze() - np.dot(D,x_r).squeeze())
nikcleju@1 123 print "Nic's residual: ||y - D x_r ||_2 = ",np.linalg.norm(y.squeeze() - np.dot(D,x_r2).squeeze())
nikcleju@1 124 print "Skl's residual: ||y - D x_r ||_2 = ",np.linalg.norm(y.squeeze() - np.dot(D,x_r3).squeeze())
nikcleju@1 125 raise ValueError("Different results")
nikcleju@1 126
nikcleju@1 127 # debais to remove small entries
nikcleju@1 128 for nn in idx_r:
nikcleju@1 129 if abs(x_r[nn]) < 1e-10:
nikcleju@1 130 x_r[nn] = 0
nikcleju@1 131
nikcleju@1 132 # exact recovery condition using support
nikcleju@1 133 #if sorted(np.flatnonzero(x_r)) == sorted(np.flatnonzero(x)):
nikcleju@1 134 # successCounter += 1
nikcleju@1 135 # exact recovery condition using error in solution
nikcleju@1 136 error = x - x_r
nikcleju@1 137 """ the following is the exact recovery condition in: A. Maleki
nikcleju@1 138 and D. L. Donoho, "Optimally tuned iterative reconstruction
nikcleju@1 139 algorithms for compressed sensing," IEEE J. Selected Topics
nikcleju@1 140 in Signal Process., vol. 4, pp. 330-341, Apr. 2010. """
nikcleju@1 141 if np.vdot(error,error) < np.vdot(x,x)*1e-4:
nikcleju@1 142 successCounter += 1
nikcleju@1 143 trial -= 1
nikcleju@1 144
nikcleju@1 145 success[rhoCounter,deltaCounter] = successCounter
nikcleju@1 146 if successCounter == 0:
nikcleju@1 147 break
nikcleju@1 148
nikcleju@1 149 rhoCounter += 1
nikcleju@1 150 #np.savetxt('test.txt',success,fmt='#2.1d',delimiter=',')
nikcleju@1 151 deltaCounter += 1
nikcleju@1 152
nikcleju@1 153 if __name__ == "__main__":
nikcleju@1 154
nikcleju@1 155 unittest.main(verbosity=2)
nikcleju@1 156 #suite = unittest.TestLoader().loadTestsFromTestCase(CompareResults)
nikcleju@1 157 #unittest.TextTestRunner(verbosity=2).run(suite)