def Sources(t ,w1, ptot,ptot1=.2, dynamic=2, n=2, J=3, Opt=1 , w2=1): ''' Creation of the sources, exactly sparse in DCT. Output: a n*t matrix, sparse in DCT. ''' if Opt==1: Sw=np.zeros((n, t, J+1)) for l in range(J): S=np.zeros((n,t)) X,X0,A0,S,N,sigma_noise,kern=bssJ.Make_Experiment_Coherent(t_samp=t,ptot=ptot,w=w1,dynamic=dynamic) Sw[:,:, l]=dp(S) X,X0,A0,S,N,sigma_noise,kern=bssJ.Make_Experiment_Coherent(t_samp=t,ptot=ptot1,w=w2,dynamic=dynamic) Sw[:,:,-1]=dp(S) Su=ps.backward1d(Sw) else: Sw=np.zeros((n, t, J+1)) for l in range(J): S=np.zeros((n,t)) X,X0,A0,S,N,sigma_noise,kern=bssJ.Make_Experiment_Coherent(t_samp=t,ptot=ptot,w=w1,dynamic=dynamic) Sw[:,:, l]=dp(S) Su=ps.backward1d(Sw) return Su
def amcaps(X, dS , dPatch, aMCA, Init): n=dS['n'] t=dS['t'] J=dPatch['J'] Sps=np.zeros((n, t, J+1)) Xw = ps.forward1d(X,J=J) n_Xw = np.shape(Xw) Xmca = Xw[:,:,0:J].reshape(n_Xw[0],n_Xw[1]*J) dSp=dp(dS) dSp['t']=t*J (A,temp)=AMCA(Xmca, dSp, aMCA=aMCA,Init=Init) Sps[:,:,:-1]=temp.reshape(n, t, J) Ra = np.dot(A.T,A) Ua,Sa,Va = np.linalg.svd(Ra) iRa = np.dot(Va.T,np.dot(np.diag(1./Sa),Ua.T)) piA = np.dot(iRa,A.T) Sps[:,:,-1] = np.dot(piA,Xw[:,:,-1]) Sf=ps.backward1d(Sps) return (A,Sf)
def GMCA_star_V2(Xin, J_2D, rank): '''X dee taillee (m, N, N)''' m = np.shape(Xin)[0] N = np.shape(Xin)[1] mw = ps.forward(Xin.reshape((m, N, N)), J=J_2D) X = mw[:, :, :, :J_2D].reshape(m, J_2D * N**2) dS = {} dS['n'] = rank dS['m'] = m dS['t'] = N**2 dS['kSMax'] = 3 dS['iteMaxXMCA'] = 400 A, S = amca.AMCA(X, dS, 0, 1) SFinW = np.zeros((rank, N**2, J_2D + 1)) SFinW[:, :, 0:J_2D] = S.reshape(rank, N**2, J_2D) SFinW[:, :, J_2D] = np.dot(np.linalg.pinv(A), mw[:, :, :, J_2D].reshape(m, N**2)) Sb = ps.backward1d(SFinW) # Sc = np.reshape(Sb, (rank, N, N)) return (A, Sc)
def GMCA_patch(kend, mw, Xx, Xy, rank): import AMCA_Direct as amca J_2D = np.shape(mw)[-1] - 1 nb_obs = np.shape(mw)[0] N = Xx[1] - Xx[0] Xp = mw[:, Xx[0]:Xx[1], Xy[0]:Xy[1], :] X1 = Xp[:, :, :, :J_2D].reshape(nb_obs, (J_2D) * N**2) dS = {} dS['n'] = rank dS['m'] = nb_obs dS['t'] = N**2 dS['kSMax'] = kend dS['iteMaxXMCA'] = 400 A, S = amca.AMCA(X1, dS, 0, 1) SFinW = np.zeros((rank, N**2, J_2D + 1)) SFinW[:, :, 0:J_2D] = S.reshape(rank, N**2, J_2D) SFinW[:, :, J_2D] = np.dot(np.linalg.pinv(A), Xp[:, :, :, J_2D].reshape(nb_obs, N**2)) Sb = ps.backward1d(SFinW) Sc = np.reshape(Sb, (rank, N, N)) return (A, Sc)
def Threshold_1D(X,W=None,J=2,lam=0.1,optCoarse=1): """ Code that performs signal thresholding in the 1D isotropic undecimated wavelets Inputs: X : Input data (m x n_samp) W : weights (m x n_coef) J : number of scales lam : threshold optCoarse : if 0, set the coarse scale coefficients to 0 Output: X_thrd : Output data (m x n_samp) """ CardS=None nS = np.shape(X) n = nS[0] t = np.int(nS[1]) Wt_c = pys.forward1d(X,J = J) S = Wt_c[:,:,0:J].reshape(n,J*t) for r in range(n): if W == None: if CardS is not None: Kval = np.int(CardS[r]) I = np.argsort(abs(S[r,:]))[::-1] th = abs(S[r,I[Kval]]) else: th = lam S[r,:] = (S[r,:] - th*np.sign(S[r,:]))*(abs(S[r,:]) - th > 0) else: S[r,:] = (S[r,:] - lam*W[r,:]*np.sign(S[r,:]))*(abs(S[r,:]) - lam*W[r,:] > 0) Wt_c[:,:,0:J] = S.reshape(n,t,J) if optCoarse == 0: Wt_c[:,:,J] = np.zeros(np.shape(Wt_c[:,:,J])) rec = pys.backward1d(Wt_c) return rec
def seuillage_star(Sini, diffi, K, res, t, eps=1e-3): Si = dp(Sini) diff = dp(diffi) S_ = ps.forward1d(Si.reshape(1, t), J=res) grad_ = ps.forward1d(diff.reshape(1, t), J=res) ww = np.zeros((t)) for j in range(res): thr = K * mad(grad_[0, :, j]) valmax = np.max(abs(S_[0, :, j])) ww = eps / (eps + abs(S_[0, :, j]) / valmax) S_[0, :, j] = softThres(S_[0, :, j], thr * ww) S_ret = ps.backward1d(S_.reshape(1, t, res + 1))[0, :] return (S_ret)
def bGMCA_MainBlock_NMF_ondt_naif(X=0, n=0, A=0, S=0, kend=3, nmax=100, L0=0, verb=0, blocksize=2, tol=1e-12, optBlock=0, J=2): '''Usage: S,A,exception = bGMCA_MainBlock_NMF_ondt_naif(X=0,n=0,A=0,S=0,kend=3,nmax=100,L0=0,verb=0,blocksize=2,tol=1e-12,optBlock=0,J=0) Inputs: X : m x t array (input data, each row corresponds to a single observation) n : scalar (number of sources to be estimated) A : m x n array (initialization of the mixing matrix - can be performed by the bGMCA function) S : n x t array (initialization of the sources - can be performed by the bGMCA function) kend : scalar (final value of the k-mad thresholding) nmax : scalar (number of iterations) L0 : boolean (0: use of the L1 norm, 1: use of the L0 norm) verb : boolean (if set to 1, in verbose mode) blocksize : int (size of the blocks) tol : float (stopping criterion) optBlock: int in {0,1,2,3} (way the block is constructed: 0 : Random creation of the block, 1 : Correlation, 2 : Loop over all the sources + take the sources that are the most correlated with the current one, 3 : We create the batchs sequentially) J : int (number of wavelet scales. If J = 0, no wavelet transform) Outputs: S : n x t array (estimated sources) A : m x n array (estimated mixing matrix) exception : boolean (equals to 1 is a SVD did not converge during the iterations) Description: Computes the sources and the mixing matrix with bGMCA using blocks. Enforces non-negativity in the direct domain and sparsity in the wavelet domain. Does not perform the initialization of A and S Example: S,A,exception = bGMCA_MainBlock_NMF_ondt_naif(X,n=50,A,S,kend=3,nmax=10000,L0=0,verb=1,blocksize=5,tol=1e-12,optBlock=0,J=2)''' Xdir = cp.deepcopy(X) t = np.shape(Xdir)[1] Xw = pys.forward1d(X, J=J) n_Xw = np.shape(Xw) X = Xw[:, :, 0:J].reshape(n_Xw[0], n_Xw[1] * J) #--- Initialization optPos = 1 powCor = 0.5 n_S = np.shape(S) exception = 0 perc = 1. / nmax thrdTab = np.zeros((nmax + 1, n_S[0])) tabCard = -np.ones((n, 1)) if optPos in [1, 2, 3]: for ii in range( 0, n_S[0] ): # Initialization to ensure that the given matrices A and S are non negative Sl = S[ii, :] Al = A[:, ii] if optPos in [1, 2]: indMax = np.argmax(abs(Sl)) if Sl[indMax] < 0: Sl = -Sl Al = -Al Sl[Sl < 0] = 0 if optPos == 1: Al[Al < 0] = 0 Al = Al / np.linalg.norm(Al) elif optPos == 3: indMax = np.argmax(abs(Al)) if Al[indMax] < 0: Sl = -Sl Al = -Al Al[Al < 0] = 0 Al = Al / (1e-24 + np.linalg.norm(Al)) S[ii, :] = Sl A[:, ii] = Al # Stopping/iteration variables Go_On = 1 it = 1 if verb: print("Starting main loop ...") print(" ") print(" - Final k: ", kend) print(" - Maximum number of iterations: ", nmax) print(" - Batch size: ", blocksize) print(" - Using support-based threshold estimation") if L0: print(" - Using L0 norm rather than L1") print(" ") print(" ... processing ...") start_time = time.time() # Defines the residual Resi = cp.deepcopy(X) #--- #--- Main loop #--- while Go_On: it += 1 if it == nmax: Go_On = 0 #--- Estimate the sources (only when the corresponding column is non-zeros) sigA = np.sqrt(np.sum(A * A, axis=0)) indS = np.where(sigA > 1e-24)[0] if optBlock == 0: # Random if blocksize < n_S[0]: IndBatch = randperm( len(indS)) #---- mini-batch amongst available sources else: IndBatch = range(len(indS)) if blocksize < len(indS): indS = indS[IndBatch[0:blocksize]] elif optBlock == 1: # Correlation if blocksize < n_S[0]: currSrcInd = it % len(indS) currSrcInd = indS[currSrcInd] currSrc = np.power(S[currSrcInd, :].T, powCor) matCor = np.dot(np.power(S, powCor), currSrc) matCor[currSrcInd] = -1 IndBatch = np.argsort(matCor) IndBatch = np.append(IndBatch, currSrcInd) IndBatch = IndBatch[::-1] else: IndBatch = range(len(indS)) if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [currSrcInd] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] elif optBlock == 2: # Loop over all the sources + take the sources that are the most correlated with the current one if blocksize < n_S[0]: currSrcInd = it % len(indS) currSrcInd = indS[currSrcInd] angTab = np.dot(A[:, currSrcInd].T, A) angTab[ currSrcInd] = -2 #0 : correspond a l'angle le plus grand, 90 degres IndBatch = np.argsort(angTab) IndBatch = np.append(IndBatch, currSrcInd) IndBatch = IndBatch[::-1] else: IndBatch = range(len(indS)) if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [currSrcInd] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] elif optBlock == 4: # We create the batchs sequentially indStt = blocksize * (it - 1) % np.shape(S)[0] indEnd = blocksize * it % np.shape(S)[0] if indStt < indEnd: IndBatch = range(int(indStt), int(indEnd)) else: ind1 = range(indStt, np.shape(S)[0]) if (indEnd > 0): ind2 = range(0, indEnd) IndBatch = np.concatenate((ind1, ind2)) else: IndBatch = ind1 if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [indStt] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] Resi = Resi + np.dot(A[:, indS], S[indS, :]) # Putting back the sources if np.size(indS) > 0: if len(indS) > 1: # Least_square estimate Ra = np.dot(A[:, indS].T, A[:, indS]) excThisIt = 0 try: Ua, Sa, Va = np.linalg.svd(Ra) except np.linalg.linalg.LinAlgError: print(indS) print(np.sum(np.isnan(Ra))) print(np.sum(np.isinf(Ra))) print('SVD DID NOT CONVERGE') exception += 1 excThisIt = 1 if excThisIt == 0: cd_Ra = np.min(Sa) / np.max(Sa) else: cd_Ra = np.linalg.norm(Ra, ord=-2) / np.linalg.norm(Ra, ord=2) if (cd_Ra > 1e-12) and not ( excThisIt): # if the condition number is large enough iRa = np.dot(Va.T, np.dot(np.diag(1. / Sa), Ua.T)) piA = np.dot(iRa, A[:, indS].T) piA = np.real(piA) S[indS, :] = np.dot(piA, Resi) if (cd_Ra < 1e-12 or excThisIt == 1): # otherwise a few gradient descent steps print('GRADIENT STEP') if excThisIt == 0: La = np.max(Sa) else: La = np.linalg.norm(Ra, ord=2) print('SVD DID NOT CONVERGE') for it_A in range(0, 10): S[indS, :] = S[indS, :] + 1 / La * np.dot( A[:, indS].T, X - np.dot(A[:, indS], S[indS, :])) else: # only a single element in the selection / the update is straightforward S[indS[0], :] = np.dot( 1. / np.linalg.norm(A[:, indS[0]]) * A[:, indS[0]], Resi) # Non-negativity if optPos in [ 1, 2 ]: # If the non-negativity is enforced on the sources StempMat = np.zeros((len(indS), t, J + 1)) StempMat[:, :, 0:J] = S[indS, :].reshape(len(indS), t, J) StempMat[:, :, J] = np.dot(np.linalg.pinv(A), Xw[:, :, J])[indS, :] # coarse scale StempDir = pys.backward1d( StempMat) # Go back to the direct domain StempDir[ StempDir < 0] = 0 # Projection on the positive orthant StempMat = pys.forward1d( StempDir, J=J) # Go again the the wavelet domain S[indS, :] = StempMat[:, :, 0:J].reshape(len(indS), J * t) Stemp = S[indS, :] # Thresholding for r in range(len(indS)): St = Stemp[r, :] #Computation of the effective support indNZ = np.where(abs(St) > kend * mad(St))[0] thrd = mad(St[indNZ]) # Computation of the threshold Kval = np.min([ np.floor(np.max([0.01, perc * it]) * len(indNZ)), n_S[1] - 1. ]) # Includes an increasing percentage of available entries I = abs(St[indNZ]).argsort()[::-1] Kval = np.int(np.min([np.max([Kval, n]), len(I) - 1.])) tabCard[indS[r]] = Kval IndIX = np.int(indNZ[I[Kval]]) thrd = abs(St[IndIX]) thrdTab[it, indS[r]] = thrd St[(abs(St) < thrd)] = 0 indNZ = np.where(abs(St) > thrd)[0] if L0 == 0: St[indNZ] = St[indNZ] - thrd * np.sign(St[indNZ]) S[indS, :] = Stemp # --- Updating the mixing matrix if len(indS) > 1: Atemp = unmix_cgsolve(S[indS, :].T, Resi.T, maxiter=n) #---- Using CG A[:, indS] = Atemp.T if optPos in [1, 3]: # Enforcing non-negativity on A for ii in range(len(indS)): Al = A[:, indS[ii]] Al[Al < 0] = 0 A[:, indS[ii]] = Al A[:, indS] = np.dot( A[:, indS], np.diag(1. / (1e-24 + np.sqrt(np.sum(A[:, indS]**2, axis=0)))) ) #--- Renormalization else: # Case where the update is explicit Atemp = np.dot(Resi, S[indS, :].T) A[:, indS] = Atemp / (1e-24 + np.linalg.norm(Atemp)) Resi = Resi - np.dot(A[:, indS], S[indS, :]) #--- Removing the sources if (np.mod(it, 500) == 1) & (verb == 1): print("It #", it) if len(indS) == 1: print("Deflation") elif len(indS) == n: print("GMCA") else: print("minibatch - ratio : ", len(indS) / n) if verb: elapsed_time = time.time() - start_time print("Stopped after ", it, " iterations, in ", elapsed_time, " seconds") SFinW = np.zeros((n, t, J + 1)) SFinW[:, :, 0:J] = S.reshape(n, t, J) SFinW[:, :, J] = np.dot(np.linalg.pinv(A), Xw[:, :, J]) S = pys.backward1d(SFinW) return S, A, exception
def PALM_NMF_MainBlock(X=0, n=0, A=0, S=0, kend=3, nmax=100, L0=0, blocksize=2, tol=1e-12, optPos=0, J=0): '''Usage: S,A = PALM_NMF_MainBlock(X=0,n=0,A=0,S=0,kend=3,nmax=100,L0=0,blocksize=2,tol=1e-12,optPos = 0,J=0) Inputs: X : m x t array (input data, each row corresponds to a single observation) n : scalar (number of sources to be estimated) A : m x n array (initialization of the mixing matrix - can be performed by the bGMCA function) S : n x t array (initialization of the sources - can be performed by the bGMCA function) kend : scalar (final value of the k-mad thresholding) nmax : scalar (number of iterations) L0 : boolean (0: use of the L1 norm, 1: use of the L0 norm) blocksize : int (size of the blocks) tol : float (stopping criterion) optPos : int in {0,1,2,3} option for the non-negativity: 0 no constraint, 1 : non-negativity on A and S, 2: non-negativity on S, 3: non-negativity on A J : int (number of wavelet scales. If J = 0, no wavelet transform) Outputs: S : n x t array (estimated sources) A : m x n array (estimated mixing matrix) Description: Computes the sources and the mixing matrix with a PALM algorithm using blocks. Allows to enforce the non-negativity in the direct domain but not to use sparsity in the wavelet domain at the same time. Does not perform the initialization of A and S Example: S,A = PALM_NMF_MainBlock(X,n=50,A,S,kend=3,nmax=100000,L0=0,blocksize=10,tol=1e-12,optPos = 0,J=0)''' # Stopping/iteration variables #optPos : 1 : tout, 2 : S, 3 : A if J > 0: # Wavelet transform t = np.shape(X)[1] Xw = pys.forward1d(X, J=J) n_Xw = np.shape(Xw) X = Xw[:, :, 0:J].reshape(n_Xw[0], n_Xw[1] * J) # Initializations Go_On = 1 it = 1 Aold = deepcopy(A) deltaTabAngle = np.zeros(nmax + 1) n_X = np.shape(X) thrdTab = -np.ones((n, n_X[1])) # Initialization to ensure that the given matrices A and S are non negative n_S = np.shape(S) for ii in range(0, n_S[0]): Sl = S[ii, :] Al = A[:, ii] if optPos in [1, 2]: indMax = np.argmax(abs(Sl)) if Sl[indMax] < 0: Sl = -Sl Al = -Al Sl[Sl < 0] = 0 if optPos == 1: Al[Al < 0] = 0 if np.linalg.norm(Al) > 1: Al = Al / np.linalg.norm(Al) elif optPos == 3: indMax = np.argmax(abs(Al)) if Al[indMax] < 0: Sl = -Sl Al = -Al Al[Al < 0] = 0 if np.linalg.norm(Al) > 1: Al = Al / np.linalg.norm(Al) S[ii, :] = Sl A[:, ii] = Al #--- #--- Main loop #--- while Go_On: it += 1 if it == nmax: # If stopping criterion met Go_On = 0 # We create the blocks deterministically indStt = blocksize * (it - 1) % np.shape(S)[0] indEnd = blocksize * it % np.shape(S)[0] if indStt < indEnd: indS = range(int(indStt), int(indEnd)) else: ind1 = range(indStt, np.shape(S)[0]) if (indEnd > 0): ind2 = range(0, indEnd) indS = np.concatenate((ind1, ind2)) else: indS = ind1 if np.size(indS) > 0: # Computation of a gradient step for S Stemp = S[indS, :].copy() Atemp = A[:, indS].copy() specNormAtemp = np.linalg.norm(np.dot(Atemp.T, Atemp), ord=2) deltaF = np.dot(Atemp.T, np.dot(A, S) - X) Stemp = Stemp - 1 / specNormAtemp * deltaF # Thresholding for r in range(0, np.shape(Stemp)[0]): gradSt = Stemp[r, :] if thrdTab[ indS[r], 0] < 0: # We fix the threshold at the first iteration and keep the same for the following ones. thrd = mad( gradSt ) # We have a single value for the threshold per line thrd = kend * thrd thrd = thrd * np.ones((1, len(gradSt)))[0, :] thrdTab[indS[r], :] = thrd thrd = thrdTab[indS[r], :] / specNormAtemp if optPos in [ 1, 2 ]: # if the non-negativity is enforced on the sources gradSt[gradSt < thrd] = 0 indNZ = np.where(gradSt > thrd)[0] if L0 == 0: gradSt[indNZ] = gradSt[indNZ] - thrd[indNZ] * np.sign( gradSt[indNZ] ) # We only have the positive part => we don't need to use the sign else: gradSt[(abs(gradSt) < thrd)] = 0 indNZ = np.where(abs(gradSt) > thrd)[0] if L0 == 0: gradSt[indNZ] = gradSt[indNZ] - thrd[indNZ] * np.sign( gradSt[indNZ]) Stemp[r, :] = gradSt.copy() A[:, indS] = Atemp.copy() S[indS, :] = Stemp.copy() # Computation of the gradient step for A Stemp = S[indS, :].copy() Atemp = A[:, indS].copy() specNormStemp = np.linalg.norm(np.dot(Stemp, Stemp.T), ord=2) Atemp = Atemp - 1 / specNormStemp * np.dot( (np.dot(A, S) - X), Stemp.T) if optPos in [ 1, 3 ]: # If non-negativity is enforced on the mixing matrix for r in range( 0, Atemp.shape[1] ): # Le fait de multiplier par D ne change rien, vu que ses coeffs sont positifs. Ac = Atemp[:, r] indMax = np.argmax(abs(Ac)) if Ac[indMax] < 0: print('Warning, max < 0') Ac[Ac < 0] = 0 Atemp[:, r] = Ac # Projection of the column of gradA on the L1 ball for r in range(0, Atemp.shape[1]): if (np.linalg.norm(Atemp[:, r]) > 1): Atemp[:, r] = Atemp[:, r] / np.linalg.norm( Atemp[:, r]) # Normalisation validee A[:, indS] = Atemp.copy() S[indS, :] = Stemp.copy() # Computation of the stopping criterion DeltaAngle = np.sum(A * Aold, axis=0) deltaTabAngle[it] = np.min( DeltaAngle ) # min car cos decroissant: on veut que le plus grand angle soit faible, donc le plus petit cos grand if np.mod(it, 500) == 0: print(it) Delta = np.linalg.norm(A - Aold) / (1e-24 + np.linalg.norm(Aold)) print('Delta angle: %s' % (np.arccos(deltaTabAngle[it]))) print('Delta: %s' % (Delta)) if it > 10000 and deltaTabAngle[it] > np.cos(9 * 1e-8): Go_On = 0 Aold = deepcopy(A) if J > 0: # Giong back into the direct domain SFinW = np.zeros((n, t, J + 1)) SFinW[:, :, 0:J] = S.reshape(n, t, J) SFinW[:, :, J] = np.dot(np.linalg.pinv(A), Xw[:, :, J]) S = pys.backward1d(SFinW) return S, A
def bGMCA_MainBlock(X=0, n=0, A=0, S=0, kend=3, nmax=100, L0=1, verb=0, blocksize=2, tol=1e-12, optBlock=0, J=0, optPos=0): '''Usage: S,A,exception,Sw = bGMCA_MainBlock(X=0,n=0,A=0,S=0,kend=3,nmax=100,L0=1,verb=0,blocksize=2,tol=1e-12,optBlock=0,J=0,optPos = 0) Inputs: X : m x t array (input data, each row corresponds to a single observation) n : scalar (number of sources to be estimated) A : m x n array (initialization of the mixing matrix) S : n x t array (initialization of the sources) kend : scalar (final value of the k-mad thresholding) nmax : scalar (number of iterations) L0 : boolean (0: use of the L1 norm, 1: use of the L0 norm) verb : boolean (if set to 1, in verbose mode) blocksize : int (size of the blocks) tol : float (stopping criterion) optBlock: int in {0,1,2,3} (way the block is constructed: 0 : Random creation of the block, 1 : Correlation, 2 : Loop over all the sources + take the sources that are the most correlated with the current one, 3 : We create the blocks sequentially) J : int (number of wavelet scales. If J = 0, no wavelet transform) optPos : int in {0,1,2,3} option for the non-negativity: 0 no constraint, 1 : non-negativity on A and S, 2: non-negativity on S, 3: non-negativity on A Outputs: S : n x t array (estimated sources) A : m x n array (estimated mixing matrix) exception : boolean (equals to 1 is a SVD did not converge during the iterations) Sw : n x (t x j) array (wavelet transform of the sources) Description: Computes the sources and the mixing matrix with bGMCA using blocks. Does not perform the initialization of A and S Example: S,A,exception,Sw = bGMCA_MainBlock(Xw,50,A,S,kend = 3,nmax=10000,L0=0,verb=1,blocksize=10,optBlock=0,J=2,optPos=0)''' if J > 0: # Use of wavelets Xdir = cp.deepcopy(X) t = np.shape(Xdir)[1] Xw = pys.forward1d(X, J=J) n_Xw = np.shape(Xw) X = Xw[:, :, 0:J].reshape(n_Xw[0], n_Xw[1] * J) #--- Initialization powCor = 0.5 n_S = np.shape(S) exception = 0 comptPasGrad = 0 perc = 1. / nmax Aold = deepcopy(A) deltaTabAngle = np.zeros(nmax + 1) if optPos in [1, 2, 3]: for ii in range( 0, n_S[0] ): # Initialization to ensure that the given matrices A and S are non negative Sl = S[ii, :] Al = A[:, ii] if optPos in [1, 2]: indMax = np.argmax(abs(Sl)) if Sl[indMax] < 0: Sl = -Sl Al = -Al Sl[Sl < 0] = 0 if optPos == 1: Al[Al < 0] = 0 Al = Al / np.linalg.norm(Al) elif optPos == 3: indMax = np.argmax(abs(Al)) if Al[indMax] < 0: Sl = -Sl Al = -Al Al[Al < 0] = 0 Al = Al / (1e-24 + np.linalg.norm(Al)) S[ii, :] = Sl A[:, ii] = Al # Stopping/iteration variables Go_On = 1 it = 1 if verb: print("Starting main loop ...") print(" ") print(" - Final k: ", kend) print(" - Maximum number of iterations: ", nmax) print(" - Batch size: ", blocksize) print(" - Using support-based threshold estimation") if L0: print(" - Using L0 norm rather than L1") print(" ") print(" ... processing ...") start_time = time.time() # Defines the residual Resi = cp.deepcopy(X) #--- #--- Main loop #--- while Go_On: it += 1 if it == nmax: Go_On = 0 #--- Estimate the sources (only when the corresponding column is non-zeros) sigA = np.sqrt(np.sum(A * A, axis=0)) indS = np.where(sigA > 1e-24)[0] if optBlock == 0: # Random creation of the block if blocksize < n_S[0]: IndBatch = randperm( len(indS)) #---- mini-batch amongst available sources else: IndBatch = range(len(indS)) if blocksize < len(indS): indS = indS[IndBatch[0:blocksize]] elif optBlock == 1: # Correlation if blocksize < n_S[0]: currSrcInd = it % len(indS) currSrcInd = indS[currSrcInd] currSrc = np.power(S[currSrcInd, :].T, powCor) matCor = np.dot(np.power(S, powCor), currSrc) matCor[currSrcInd] = -1 IndBatch = np.argsort(matCor) IndBatch = np.append(IndBatch, currSrcInd) IndBatch = IndBatch[::-1] else: IndBatch = range(len(indS)) if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [currSrcInd] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] elif optBlock == 2: # Loop over all the sources + take the sources that are the most correlated with the current one if blocksize < n_S[0]: currSrcInd = it % len(indS) currSrcInd = indS[currSrcInd] angTab = np.dot(A[:, currSrcInd].T, A) angTab[ currSrcInd] = -2 #0 : correspond a l'angle le plus grand, 90 degres IndBatch = np.argsort(angTab) IndBatch = np.append(IndBatch, currSrcInd) IndBatch = IndBatch[::-1] else: IndBatch = range(len(indS)) if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [currSrcInd] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] elif optBlock == 3: # We create the batchs deterministically indStt = blocksize * (it - 1) % np.shape(S)[0] indEnd = blocksize * it % np.shape(S)[0] if indStt < indEnd: IndBatch = range(int(indStt), int(indEnd)) else: ind1 = range(indStt, np.shape(S)[0]) if (indEnd > 0): ind2 = range(0, indEnd) IndBatch = np.concatenate((ind1, ind2)) else: IndBatch = ind1 if blocksize < len(indS): if len(indS) == n_S[0]: indS = indS[IndBatch[0:blocksize]] else: print('Attention, cas special') indSTemp = [indStt] ii = 0 while len(indSTemp) < blocksize: ii = ii + 1 if IndBatch[ii] in indS: indSTemp = indSTemp + [IndBatch[ii]] Resi = Resi + np.dot(A[:, indS], S[indS, :]) # Putting back the sources if np.size(indS) > 0: if len(indS) > 1: # Least_square estimate Ra = np.dot(A[:, indS].T, A[:, indS]) excThisIt = 0 try: Ua, Sa, Va = np.linalg.svd(Ra) except np.linalg.linalg.LinAlgError: print(indS) print(np.sum(np.isnan(Ra))) print(np.sum(np.isinf(Ra))) print('ATTENTION PAS DE CONVERGENCE DE LA SVD') exception += 1 excThisIt = 1 if excThisIt == 0: cd_Ra = np.min(Sa) / np.max(Sa) else: cd_Ra = np.linalg.norm(Sa, ord=-2) / np.linalg.norm(Sa, ord=2) if (cd_Ra > 1e-12) and not ( excThisIt): # if the condition number is large enough iRa = np.dot(Va.T, np.dot(np.diag(1. / Sa), Ua.T)) piA = np.dot(iRa, A[:, indS].T) S[indS, :] = np.dot(piA, Resi) if (cd_Ra < 1e-12 or excThisIt == 1): # otherwise a few gradient descent steps comptPasGrad += 1 print('GRADIENT STEP INSTEAD OF PSEUDO-INVERSE NUMBER %s' % comptPasGrad) if excThisIt == 0: La = np.max(Sa) else: La = np.linalg.norm(Ra, ord=2) print('WARNING SVD DID NOT CONVERGE AT THIS ITERATION') for it_A in range(0, 10): S[indS, :] = S[indS, :] + 1 / La * np.dot( A[:, indS].T, X - np.dot(A[:, indS], S[indS, :])) else: # only a single element in the selection / the update is straightforward S[indS[0], :] = np.dot( 1. / np.linalg.norm(A[:, indS[0]]) * A[:, indS[0]], Resi) # Thresholding Stemp = S[indS, :] for r in range(len(indS)): # Thresholding St = Stemp[r, :] indNZ = np.where(abs(St) > kend * mad(St))[0] thrd = mad(St[indNZ]) Kval = np.min([ np.floor(np.max([0.01, perc * it]) * len(indNZ)), n_S[1] - 1. ]) # Includes an increasing percentage of available entries I = abs(St[indNZ]).argsort()[::-1] Kval = np.int(np.min([np.max([Kval, n]), len(I) - 1.])) IndIX = np.int(indNZ[I[Kval]]) thrd = abs(St[IndIX]) if optPos in [1, 2]: St[St < thrd] = 0 indNZ = np.where(St > thrd)[0] if L0 == 0: St[indNZ] = St[indNZ] - thrd * np.sign(St[indNZ]) else: St[(abs(St) < thrd)] = 0 indNZ = np.where(abs(St) > thrd)[0] if L0 == 0: St[indNZ] = St[indNZ] - thrd * np.sign(St[indNZ]) S[indS, :] = Stemp # --- Updating the mixing matrix if len(indS) > 1: Atemp = unmix_cgsolve(S[indS, :].T, Resi.T, maxiter=n) #---- Using CG A[:, indS] = Atemp.T A[:, indS] = np.dot( A[:, indS], np.diag(1. / (1e-24 + np.sqrt(np.sum(A[:, indS]**2, axis=0)))) ) #--- Renormalization else: Atemp = np.dot(Resi, S[indS, :].T) A[:, indS] = Atemp / (1e-24 + np.linalg.norm(Atemp)) if optPos in [1, 3]: for ii in range(len(indS)): Al = A[:, indS[ii]] Al[Al < 0] = 0 A[:, indS[ii]] = Al Resi = Resi - np.dot(A[:, indS], S[indS, :]) #--- Removing the sources Delta = np.linalg.norm(A - Aold) / (1e-24 + np.linalg.norm(Aold)) if (np.mod(it, 500) == 1) & (verb == 1): print("It #", it, " - Delta = ", Delta) if len(indS) == 1: print("Deflation") elif len(indS) == n: print("GMCA") else: print("minibatch - ratio : ", len(indS) / n) if verb: DeltaAngle = np.sum(A * Aold, axis=0) deltaTabAngle[it] = np.min( DeltaAngle ) # min car cos decroissant: on veut que le plus grand angle soit faible, donc le plus petit cos grand if np.mod(it, 500) == 1: print('Delta angle: %s' % (np.arccos(deltaTabAngle[it]))) Aold = deepcopy(A) if verb: elapsed_time = time.time() - start_time print("Stopped after ", it, " iterations, in ", elapsed_time, " seconds") if J > 0: Sw = cp.deepcopy(S) SFinW = np.zeros((n, t, J + 1)) SFinW[:, :, 0:J] = S.reshape(n, t, J) SFinW[:, :, J] = np.dot(np.linalg.pinv(A), Xw[:, :, J]) S = pys.backward1d(SFinW) if J > 0: return S, A, exception, Sw else: return S, A, exception
def GFB_WSparse_Positivity_1D(X,W=None,CardS = None,J=2,lam = 1,niter=250,tol=1e-6,Analysis=False,verb=0,XisOndt=0,coarseScale=0,A=0): """ Solves : Argmin_(x>=0) lam *||W o (S Phi^T) ||_1 using 1D wavelets Inputs: X : Input data (m x n_samp) W : weights (m x n_coef) niter : number of iterations J : number of scales tol : limit on the stopping criterion lam : threshold Analysis : if set, rather uses a synthesis prior verb : enables verbose mode XisOndt: set to 1 if X is already in the wavelet domain coarseScale : contains the coarse scale of X if X is already in the wavelet domain Output: X_thrd : Output data (m x n_samp) if XisOndt = 1, additional outputs: coarseScale : coarse scale of X """ if XisOndt==1: n_X = np.shape(X) m = n_X[0] t = np.shape(coarseScale)[1] Wt_c = np.zeros((m,t,J+1)) Wt_c[:,:,0:J] = X.reshape(m,t,J) Wt_c[:,:,J] = np.dot(np.linalg.pinv(A),coarseScale) #coarseScale X = pys.backward1d(Wt_c) u = dp(X) v = dp(X) Xout = dp(X) Xold= dp(Xout) w_u = 0.8 w_v = 0.2 gamma = 0.9 mu = 1.5 it = 0 Go_On = 1 tk = 1 while Go_On: it+=1 dG = Xout - X # Update positivity Xt = 2.*Xout - u - gamma*dG Xt = Xt*(Xt > 0) - Xout u = u + mu*Xt # Update sparsity Xt = 2.*Xout - v - gamma*dG if Analysis: Xt = Analysis_prox(Xt,W = W,J=J,lam=lam) - Xout else: Xt = Threshold_1D(Xt,W=W,J=J,lam=lam,CardS=CardS) - Xout v = v + mu*Xt # Update Sout tkp = 0.5*(1+np.sqrt(1. + 4.*(tk**2))) Xt = w_u*u + w_v*v Xout = Xt + (tk - 1.)/tkp*(Xt - Xold) diffX = np.sum(abs(Xold - Xout))/(1e-24 + np.sum(abs(Xold))) Xold = dp(Xout) if verb: print("It. #",it," - relative variation : " ,diffX) if diffX < tol: Go_On=0 if it > niter: Go_On=0 if XisOndt==1: Xout = pys.forward1d(Xout,J = J) coarseScale = Xout[:,:,J] Xout = Wt_c[:,:,0:J].reshape(m,J*t) return Xout,coarseScale else: return Xout