Ejemplo n.º 1
0
def rAMCA(Xini,A,amca=1):
    '''Computes the rAMCA algorithm. It estimates A, S and O jointly. It estimates the outliers
    based on their norm and delta-density, and estimates A and S with AMCA wich penalizes the corrupted samples.
    Input:
    Xini: Observations, represented in a domain in which both the sources and the outliers are sparse.
    A: initializing mixing matrix
    amca: boolean. If it is set to one, AMCA is performed, otherwise, GMCA is performed in the inner loop to estimate A and S. (Should be one)
    Output:
    S: estimated sparse sources
    A: estimated mixing matrix
    O: estimated sparse outliers
    '''

    #Initialize the variables and parameters

    X=copy(Xini)
    A=copy(A)
    O=np.zeros(np.shape(Xini))


    itMAX=aS['iteMaxrAMCA']
    IndexTot=0
    convA=10 #stop when A has converged


    densityMin=WminD[str(dS['n'])]#Maximal value of the delta-density for not being considered as corrupted
    gammaValue=np.sqrt(2)*scipy.special.gamma((dS['m']+1.)/2.)/scipy.special.gamma((dS['m'])/2.) #For the l_2,1 norm estimation of the outliers

    perc=5 #percentage of outliers newly considered at every iteration (can be smaller to avoid false estimation of outliers)
    tperc=perc/100.*dS['t']


    suppOest=np.zeros((dS['t'],)) #Support of the estimated outliers
    new=np.zeros((dS['t'],)) # Newly estimated outliers



    #First estimation of A and S
    S,A=AMCA(X-O,A,amca)

    #Start of the main loop
    while (IndexTot<itMAX  and (np.sum(new)>0 or convA>5)): #Stop if A has converged and no outlier has been estimated


       #########################################
        #Update the support of the outliers
       #########################################
        #Update the delta density of the estimated sources
        deltaDen=np.linalg.norm(S,axis=0,ord=1.)/np.max(np.abs(S)+1e-6,axis=0)
        #update the l2 norm of the columns
        normX=np.linalg.norm(X-A.dot(S)-O,axis=0)

        if np.sum(deltaDen>densityMin)>0:

            deltaDen[deltaDen<densityMin]=0 #The sparse samples are not considered
            normX[deltaDen==0]=0
            minSuppX=np.percentile(normX[normX>0],max((np.sum(normX>0)-tperc)/np.sum(normX>0)*100,0)) #Lower value of the norm of the admissible corrupted samples

            if (np.sum(new)==0 and convA<5): #If it has nearly converged, decreases the value of minSuppX to avoid local minima and bias
                minSuppX=mad(X-A.dot(S)-O)*gammaValue


            new=np.array(normX>minSuppX,int) #Support of the samples corresponding to the largest entries in the residue and whose delta-density is large enough

            new[new*suppOest>0]=0 # Take only the new oultiers#
            suppOest+=np.array(new,int) #Add the new outliers
            suppOest[suppOest>0]=1 # support of the outliers#

            #Sanity Check to avoid the false estimation of outliers. It is not necessary if the initial matrix A has a small condition number (less than 50), and if the parameter perc is small enough.
            #As the outliers are broadly distributed, its m eigenvalues should be centered around a same value.
            #If a source has been wrongly estimated as being outliers, then one of the eigenvalue will be much more larger than the other one (the energy of the sources has been added up to the one of the outliers)
            #If the difference between the largest eigenvalue and the mean of the other eigenvalues is equal to five time the standard deviation of the m-1 smallest eigenvalues, then,
            # the samples contributing to this eigenvalue are not considered as being outliers.
            if np.sum(new)>max(0.005*dS['t'],dS['m']) : #if new outliers have been deteced#
                            Onew=(X/(np.linalg.norm(X,axis=0)))[:,(suppOest>0)] #corresponding columns in X, normalized to avoid scaling issue in the PCA (if the sources amplitude is much smaller than the outliers amplitude, they may not be detected otherwise)
                            u,s,v=np.linalg.svd(Onew,full_matrices=True)#Compute the svd, can do better than that
                            if (s[0]-np.mean(s[1::]))/(np.var(s[1::])**0.5)>5: #if an eigenvalue is anormaly large, a source is detected
                                Onew_=copy(Onew)
                                Os=s[0]*(u[:,0].reshape((dS['m'],1)).dot(v[0,:].reshape((1,np.size(v[0,:]))))) #outliers contribution corresponding to this eigenvalue

                                Onew=Onew_ - Os # outliers contribution on the m-1 remaining dimensions
                                suppOest[np.where(suppOest>0)[0][np.linalg.norm(Onew,axis=0)< np.linalg.norm(Os,axis=0)]]=0 #release of the samples whose projection on the m-1 remaining dimensions has a smaller energy than on the axis corresponding to the largest eigenvalue

        else:
            new=0*new#no outlier


        #########################################
        #Update the amplitudes of the outliers
       #########################################
        R=X
        beta=mad(X-A.dot(S)-O)*gammaValue #threshold value of the l_2,1 norm
        O[:,suppOest>0]=((R)[:,suppOest>0])* (np.maximum(1-beta/(np.linalg.norm((R)[:,suppOest>0],axis=0)),0))


        #########################################
        #Update S and A with AMCA
       #########################################
        A_=copy(A)#A before estimation
        A=np.random.randn(dS['m'],dS['n']) #randomize the initialization point
        A/=np.linalg.norm(A,axis=0)

        S,A=AMCA(X-O,A,amca)#Estimation of S, A

        S,A=reOrder(A,S,A_,S) # reorder the factorization  (to compute the convergence metric)
        angle=np.arccos(np.abs(np.sum(A_*A,axis=0)))*180/np.pi
        convA=np.max(angle) #A has converged if the maximal angle is less than 5


        IndexTot+=1
    if pS['verboserAMCA']:
        print 'rAMCA terminates in ', IndexTot, ' iterations'

    return S,A,O
Ejemplo n.º 2
0
def rGMCA(Xini,Aini):
    '''
    Performs the rGMCA algorithm.It estimates jointly O,S and A. It further implements a weighting scheme which penalizes the
    entries corrupted by outliers.
    Input:
    Xini: the observations, represented in a domain in which the sources and outliers have a sparse reprentation.
    Output:
    S: the estimated sparse sources
    A: the estimatedmixing matrix
    O: the estimated sparse outliers
    '''

    #Initialization
    X=copy(Xini)
    A=copy(Aini)
    O=np.zeros((dS['m'],dS['t']))
    S=np.zeros((dS['n'],dS['t']))

    #########################################
        #Initialization
    #########################################
    #First outliers estimation
    Xabs=np.array(np.abs(X))
    sigmaN=np.median(Xabs)#can do better than that
    iniO=(np.percentile(Xabs[Xabs>sigmaN],50))#Threshold for the first estimation of the outliers

    O=softThres(X-A.dot(S),iniO)#First estimation of the outliers

    while np.linalg.cond(S)>1e4 or np.linalg.cond(A)>1e4 or np.linalg.norm(S)==0:#first estimation of the sources
        S=np.array(np.abs(np.linalg.pinv(A).dot(X-O)))
        ini=np.array(np.percentile(S,99,1)).reshape((dS['n'],1))#threshold for each source
        S=softThres(S,ini)


        while np.linalg.cond(S)>1e4 or np.linalg.cond(A)>1e4 or np.linalg.norm(S)==0:#estimation of the mixing matrix
            A=data.mixingMatrix(dS['m'],dS['n'])
            S=np.array(np.abs(np.linalg.pinv(A).dot(X-O)))
            tot=99
            ini=np.array(np.percentile(S,tot,1)).reshape((dS['n'],1))
            S=softThres(S,ini)

            A=(X-O).dot(np.linalg.pinv(S))
            A/=np.linalg.norm(A,axis=0)



    #The outliers will be thresholded by kO*mad(X-AS-O), where k decreases toward 3
    kOIni= max(iniO,10)/mad(X-A.dot(S)-O)*np.ones((dS['m'],1)) #initial kO

    #########################################
        #Joint estimation
    #########################################
    indexIte=0
    convA=10
    while (convA>1 and indexIte<aS['iteMaxrGMCA']) or indexIte<5:
        A_=A
        S_=S
        # Decrease k#
        kO=kOIni+(aS['kOMax']*np.ones((dS['m'],1))-kOIni)*np.float((indexIte))/(aS['iteMaxrGMCA']-1)

        W=1./(np.median(np.abs(S[np.abs(S)>0]))/10.+np.linalg.norm(O,axis=0,ord=1)) #Weight for the estimation of A

        S,A=AMCA(X-O,A,amca=0,WO=W)#Estimate A and S

        O=softThres(X-A.dot(S),kO*np.median(mad(X-A.dot(S)-O)))#update of O

        S,A=reOrder(A,S,A_,S_)#reorder the factorization to compute the convergence metric
        angle=np.arccos(np.abs(np.sum(A_*A,axis=0)))*180/np.pi
        convA= np.max(angle)
        indexIte+=1

    if pS['verboserGMCA']:
        print 'rGMCA terminates in ', indexIte, ' iterations'


    return S,A,O
Ejemplo n.º 3
0
def pcpGMCA(M, Aori, Sori, Aini):
    '''Algorithm performing the combination PCP+GMCA
    The implementation of PCP follows the one proposed in the article 
    Robust Principal Component Analysis? of E. Candes et al.
    Several combinations PCP+GMCA for different values of the parameter Lambda are performed, 
    and the best estimates are returned.
    Input:
     M: observations
     Aori: initial mixing matrix
     Sori: initial sources
     Aini: initializating mixing matrix for GMCA
    Output: S the estimated sources and A, the estimated mixing matrix
    '''
    #Dimensions
    m = np.shape(M)[0]
    t = np.shape(M)[1]

    #Initialization of the variables
    L = M.copy()  #Low rank term (corresponding to AS)
    O = 0 * M  #outliers
    Y = np.zeros(np.shape(M))

    #Initialization of the parameters for the loop
    index = 0
    errorX = 20000

    #Loop with the varying parameter Lambda
    while index < 20:

        Lambda = (np.float(index) / 2. + 0.5) / np.sqrt(
            t)  #current value of lambda

        mu = (t * m / (4 * np.sum(np.abs(M)))
              )  #value of mu, given in the aticle (can do better than that)

        #Parameters for pcp
        ite = 0
        convO = 10
        tot = 1e16
        convTot = 1e16
        convL = 1

        try:
            #Perform pcp given the current value of lambda
            while (ite < aS['iteMaxPCP'] and (convL > 1e-3 or convO > 1e-3
                                              or convTot > 1e-6)) or ite < 15:

                #Update variables for convergence
                tot_ = tot  #value of the cost function
                O_ = O  #outliers
                L_ = L  #low-rank

                L, S = updateL(mu, M, O, Y)  # update of the low-rank term
                O = updateO(Lambda, mu, M, L, Y)  # update of the outliers
                Y = Y + mu * (M - L - O
                              )  #update Y, the Lagrange multiplier  matrix
                #

                #
                tot = np.sum(S) + Lambda * np.sum(
                    np.abs(O))  # update cost function
                convTot = np.abs(
                    (tot - tot_)) / tot  # convergence cost function
                convO = np.linalg.norm(O - O_) / np.linalg.norm(
                    O_)  #convergence outliers
                convL = np.linalg.norm(L - L_) / np.linalg.norm(
                    L_)  # convergence low-rank term
                ite += 1

            #perform GMCA for the returned low-rank term L
            S, A = AMCA(L, Aini.copy(), amca=0)
            S, A = reOrder(A, S, Aori, Sori)
            deltaGMCA = np.sum(
                np.abs(np.linalg.pinv(A).dot(Aori) - np.eye(dS['n']))) / (
                    dS['n']**2)  #compute the corresponding error

            if deltaGMCA < errorX:
                #If there is an improvement, keep this results
                errorX = deltaGMCA
                Sfin = S.copy()
                Afin = A.copy()
                Ofin = O.copy()
                if pS['verbosePCP']:
                    print 'PCP+GMCA, current best error:', errorX, 'at index', index, 'th index in ', ite, 'iterations'

            elif deltaGMCA > 1.5 * errorX:  #Otherwise
                index += 1
        except np.linalg.LinAlgError:
            pass
        index += 1

    return Sfin, Afin, Ofin
Ejemplo n.º 4
0
def trRGMCA(X,Aini,Afix=0):
    '''
    tr-rGMCA algorithm: performs the estimations of A, S and O, based on the
    observations X, the number of sources n (dictionary dS['n']), and the difference of morphology
    between the outliers and the sources.
    This difference of morphology is taken into account with the transformations: Stransf, Otransf (and Sback, Oback).
    Inputs: 
    - X the observations (m by t matrix)
    - Aini the initialized mixing matrix (m by n)
    - boolean Afix: if true, then the oracle is performed (no estimation of A). Otherwise, A is jointly estimated.
    Outputs: S (the estimated sources, n by t), A (estimated mixing matrix, m by n) and O (estimated outliers, m by t matrix).
    '''
    O=np.zeros((dS['m'],dS['t'])) # Estimated outliers
    S=np.zeros((dS['n'],dS['t'])) # Estimated sources
    A=Aini.copy() # Estimated mixing matrix
    Sini=np.linalg.pinv(A).dot(X) #First estimated sources- only used to reorder the sources
    Siniws=Stransf(Sini)# Expansion coefficients of Sini
    
    #Expansion Coefficients of the components in the dictionary in which S is sparse
    Ows=Stransf(O)  
    Sws=Stransf(S)
    Xws=Stransf(X)
    
    #Expansion Coefficients of the components in the dictionary in which O is sparse
    Owo=Otransf(O)
    Swo=Otransf(S)
    Xwo=Otransf(X)
    
    
    #########################################################
       #      Warm-up Phase or Oracle with A known       #
    #########################################################

    
    indexTotW=aS['Rew'] #Number of reweighting loops

    I=0 # Index of the outer loop (A-S// O-S)
    convA=10 # Criterion for the stability of A
    if Afix==0: #If A is estimated, set the maximal number of outer loops to 25.
        loopTot=25
    else:
        loopTot=1# If A is fixed, only O and S are estimated (and the number of outer loops is set to 1)
    while (I<loopTot and (convA>2)) or (I<3 and Afix==0): #Stop the algorithm if the number of outer loops is too large (should not be the case), A is stable, and at least 3 outer loops have been done.
      I+=1
      #Copy of A for convergence
      Aold=A.copy()
      
      #Weights for the reweightings
      WO=np.ones(np.shape(Owo))
      WS=np.ones(np.shape(Sws))
      
     
     
      iteMax=1000 # The maximal number of iterations for the loop estimating S and O
      indexW=0#Set the index of the reweighting procedure to 0 
     
      ########################  Estimation of A #################################
         
      if Afix==0: #If A is estimated
          
          Sws,A=AMCA((Xws-Ows),A,0) #run GMCA on Xws - Ows, for estimating A and S

          (Sws,A)=reOrder(A,Sws,Aini,Siniws)#permutations
          convA=np.max(np.arccos(np.abs(np.sum(Aold*A,axis=0))/(np.linalg.norm(Aold,axis=0)*np.linalg.norm(A,axis=0)))*180/np.pi) #Maximal angle deviation from one estimation of A to another. (Should be smaller than 2 degrees to stop the algorithm).
          
          #Compute the corresponding outliers
          S=Sback(Sws)
          Swo=Otransf(S)
          madO=madAxis(Otransf(X-A.dot(S)-O))
          normO=np.linalg.norm(Xwo-A.dot(Swo),axis=0)
          thr_O=np.sqrt(2)*aS['kOMax']*madO*sp.special.gamma(dS['m']/2.+0.5)/sp.special.gamma(dS['m']/2.)
          if np.max(normO)>thr_O:
                  Owo=(Xwo-A.dot(Swo))*(np.maximum(1.-thr_O*WO/normO,0))
          else:
              O*=0
              Owo*=0

          O=Oback(Owo)
          Ows=Stransf(O)
          
      L=np.linalg.norm(A.T.dot(A), 2)#Maximal eigenvalue of A.T.A
      
    
      ########################  EstimationS of O and S #################################

      if  I==1: #If this is the first loop, do not reweight 
         indexTotW=1
      else:
         indexTot=aS['Rew']
      if Afix==1: #If A is fixed, set the number of reweighting loops to 5
         indexTotW=5
      else:
          indexTotW=1
          
      convW=1 #criterion for the convergence of the joint O-S estimation with reweighting (based on the stability of S)
   
      ########### Reweighting ############
      while indexW<indexTotW and (convW>1e-2 or indexW<2 ):  # Stop the reweighting if S is stable of the number of reweighting steps is reached
          S_W=S.copy() # To check the stability of S
          
          if  indexW==0:   #Do not reweight the output of GMCA

              WS=np.ones((np.shape(Sws)))
              WO=np.ones((np.shape(Owo)))
          else: #Weights based on the current thresholds and components
              
              WS=np.maximum(madS*aS['kSMax'],0)/(madS*aS['kSMax']+np.abs(Sws))
              WO=np.maximum(thr_O,0)/(thr_O+np.linalg.norm(Owo,axis=0))

          index=0
          convO=1
          convS=1
          ####### Estimations O and S ########
          while index< iteMax and ((convO+convS)>1e-5  ): # Stop the algorithm when O and S are stable (should not reach iteMax)
                if index>iteMax-2 and (convA<=1e-4 or Afix==1):
                    print 'Convergence not reached O-S'
                if (convO+convS)>1e-4:  #Fix the parameters for convergence once the components are stable enough
                        madS=madAxis(A.T.dot(Stransf(X-A.dot(S)-O)), axis=1) #projected noise level on the sources
                        madO=madAxis(Otransf(X-A.dot(S)-O)) # noise level for the outliers
                  
                  
                  
                #Copies of the components for convergence check
                O_=Owo.copy()
                S_=S.copy()
                
                
                ###Estimation of S, with LASSO and FISTA implementation###
                # Thresholds of the sources: madS*WS*aS['kSMax']
                convS_sub=1
                indexS=0
                t_=1
                y=S.copy()
                while convS_sub>1e-6 and indexS<5000 :
                        S_old=S.copy()
                        S=Sback(softThres(Stransf(y+1./L*A.T.dot(X-A.dot(y)-O)),madS*aS['kSMax']*1./L*WS,1))
                        t=(1.+np.sqrt(1+4*(t_)**2))/2.
                        y=S+(t_-1.)/(t)*(S-S_old)
                        t_=t
                        convS_sub=np.linalg.norm(S_old-S)/np.linalg.norm(S)
                        indexS+=1
                       
                            
                        
                Swo=Otransf(S)
                Sws=Stransf(S)
                
                         
                
                ### Estimation of O ###
                normO=np.linalg.norm(Xwo-A.dot(Swo),axis=0)
                thr_O=np.sqrt(2)*aS['kOMax']*madO*sp.special.gamma(dS['m']/2.+0.5)/sp.special.gamma(dS['m']/2.)
                if np.max(normO)>thr_O:
                       Owo=(Xwo-A.dot(Swo))*(np.maximum(1.-thr_O*WO/normO,0))
                else:
                    Owo*=0

                O=Oback(Owo)
                Ows=Stransf(O)
               
                ### Convergence criteria O-S###
                convO=np.linalg.norm(Owo-O_)/np.linalg.norm(Owo+1e-16)
                convS=np.linalg.norm(S-S_)/np.linalg.norm(S+1e-16)
                
                index+=1
            
          indexW+=1
          ######Convergence reweigthing######
          convW=np.linalg.norm(S-S_W)/np.linalg.norm(S)


          ###End warm-up###

    #########################################################
                    #      Refinement       #
    #########################################################    

    if Afix==0:
        
        S,A,O=palm_trRGMCA(X, O, S,A )
        
        
    return S,A,O    
Ejemplo n.º 5
0
def BetaD_ICA(xori, Aori):
    '''
    Minization of the beta-divergence via BFGS. This implementation comes from the Matlab implementation proposed by N. Gadhok (http://home.cc.umanitoba.ca/~kinsner/projects/software/index.html) 
    The modifications of the original code are identified as so. In particular, this version performs the minimization of the beta-divergence for different values of the beta-divergence, and returns
    the mixing matrix with the minimal error.
    Input:
    xori: observations
    Aori: initial mixing matrix, to be retrieved.
    Output:
    S: estimated sources
    A: estimated mixing matrix
    '''

    #Setup parameters
    stopping_criterion = 1e-5  #convergence criteria
    maxiteration_BFGS = aS['iteMaxBeta']  #maximal number of iterations
    maxiteration_linesearch = 20  #maximal number of iterations for the line search

    #variables
    p_i = 2 * np.ones((dS['n'], 1))  #should be set to 2 for sparse data
    x = xori.copy()  #copy of the observations (assumed to have zero mean)
    xm = x.copy()  #copy of the observations (assumed to have zero mean)

    ###
    #If the number of mesures is strictly larger than the number of sources: a PCA is performed
    #for the reduction of dimensions
    ###

    if dS['m'] > dS['n']:
        U, d, V = np.linalg.svd((x).T)
        d2 = np.zeros((dS['n'], dS['t'])).T
        for index in range(0, dS['n']):
            d2[index, index] = d[index]
        x = (U[:, :].dot(d2)).T  #projected observations

    Wred = x.dot(np.linalg.pinv((xm)))  #projection matrix, identity if n=m

    uori = np.mean(x, 1).reshape(
        (dS['n'], 1))  #mean of x (should be close to 0)
    Wori = np.linalg.inv(Wred.dot(
        Aori))  #initialization of W, which should be close to the inverse of A

    W1 = Wori.copy()  #initiliazation of demixing matrix used in the algo.
    u1 = uori.copy()  #initiliazation of mean used in the algo.

    Wfinal = Wori  #initialization of the returned results
    ufinal = uori  #initialization of the returned results

    resultat = 1e5  #initialization of the "best" error
    index = 0  #index of the loop
    (m, t) = np.shape(x)
    # dimension of the matrix
    G = np.eye(m**2 + m)  #initialization of the inverse of Hessian;

    #Each following loop performs a minimization given a different value of beta.
    while index < 400:

        B = 0.005 + index * 0.002  #current value of beta

        #Initialization of the variables and parameters
        W = W1.copy()
        u = u1.copy()

        v = formv(W, u)
        # v is a column vector corresponding of the concatenation of W and u
        v1 = np.zeros((m**2 + m, 1))
        # v1 will be used an update of v

        i = 1
        #index for the minimization
        fxO = 0  # value of the cost function at the previous iteration
        fx = 10  #value of the cost function
        fxn = 10  # vlaue of the cost function for the line search
        flag = 1  #Set to zero when the line search has failed
        prev = 1  #Previous decrease of the cost function

        ###
        #Minimization of the beta-divergence with the corresponding value of beta
        ###

        while ((prev > stopping_criterion or
                (np.abs(fx - fxO) /
                 (np.abs(fxO) + 1e-16) > stopping_criterion)) and
               (i < maxiteration_BFGS)) or i < 10:
            #Main loop, which stop if convergence has been reached (decrease in the cost function smaller than stopping-criterion, twice)
            prev = np.abs(fx - fxO) / np.abs(fxO)  #cost function decrease
            fxO = fx  #previous value of the cost function
            if i > 1 and flag:
                #update of the variables (only if the line search was successful (implementation difference with the original implementation))
                v = v1
                #Update of v
                [W, u] = deformv(v)
                #Update of W and u

            p = -G.dot(BetaD_Deriv(x, W, u, B, p_i))
            #New direction given by p

            ###
            #Begin of the line search
            ###
            alpha = 1
            #line search coeffcient
            sigma = 1.e-4
            #minimal decrease

            alphamin = 1.e-4
            #minimal coefficient for alpha
            pgx = p.T.dot(BetaD_Deriv(x, W, u, B, p_i))
            #decrease of the function given the direction
            v1 = v + alpha * p
            #first update of v

            [W2, u2] = deformv(v1)
            #corresponding W and u

            fxn = BetaD_Lbeta(x, W2, u2, B, p_i)
            #cost function for the first update
            fx = BetaD_Lbeta(x, W, u, B, p_i)
            #actual cost function

            i_linesearch = 1
            #index for the line-search

            while (fxn > fx + sigma * alpha * pgx) and (alpha > alphamin) and (
                    i_linesearch < maxiteration_linesearch):
                mu = -0.5 * pgx * alpha / (fxn - fx - alpha * pgx)
                if mu < .01:
                    mu = .5
                    #don't trust quadratic interpolation from far away

                alpha = mu * alpha
                v1 = v + alpha * p
                [W2, u2] = deformv(v1)
                fxn = BetaD_Lbeta(x, W2, u2, B, p_i)
                i_linesearch += 1

            if (fxn > fx + sigma * alpha * pgx) or np.sum(
                    np.isnan(W2) == True) > 0 or np.sum(
                        np.isnan(
                            BetaD_Deriv(x, W, u, B, p_i) -
                            BetaD_Deriv(x, W2, u2, B, p_i)) == True) > 0:
                # Line search failed. Thus, the BFGS approx of the Hessian has become corrupt, or we are near the minimum (flat valley) and the step size is too big. So restart.
                G = np.eye(m**2 + m)
                p = -G.dot((BetaD_Deriv(x, W, u, B, p_i)))
                alpha = 1
                flag = 0
                prev += 1

            #End Line search.Update accordingly the variables

            else:
                flag = 1
                v1 = v + alpha * p

                [W, u] = deformv(v1)
                [W1, u1] = deformv(v)
                s = alpha * p
                y = BetaD_Deriv(x, W, u, B, p_i) - BetaD_Deriv(
                    x, W1, u1, B, p_i)
                I = np.eye(m**2 + m)
                G = (I - (s.dot(y.T)) / ((y.T).dot(s))).dot(
                    G.dot((I - (y.dot(s.T)) /
                           ((y.T).dot(s))))) + (s.dot(s.T)) / ((y).T.dot(s))
                #update inverse of the Hessian
            i += 1

        [Wfinal, ufinal] = deformv(v1)
        #Final variables

        ###
        #Compute the corresponding sources and mixing matrix, and then the associated errors
        ###
        A = np.linalg.inv(Wfinal)  #Inverse of W
        A = np.linalg.pinv(Wred).dot(A)  # if dimension reduction was needed
        for indexC in range(0, dS['n']):
            A[:, indexC] = A[:, indexC] / np.linalg.norm(
                A[:, indexC])  #normalization of the columns
        S = np.sign(np.linalg.pinv(A).dot(xori)) * np.maximum(
            np.abs(np.linalg.pinv(A).dot(xori)) - aS['kSMax'] * dS['ampliN'],
            0)  #corresponding sources

        S, A = reOrder(A, S, Aori, S)  # reorder the factorization
        D = np.sum(
            np.abs(np.linalg.pinv(A).dot(Aori) - np.eye(np.shape(Aori)[1])) /
            (dS['n']**2))  #Delta A error

        if D <= resultat:
            resultat = D
            Afin = A.copy()  #keep the corresponding mixing matrix
            Sfin = S.copy()  #keep the corresponding sources
            index += 1
            if pS['verboseBeta']:
                print 'Beta-div.: current best result: ', D, 'at beta= 0.005+ 0.002*', index, 'in ', i, ' iterations'

        elif D < resultat * 1.5:
            index += 1
        else:
            #exit
            if pS['verboseBeta']:
                print 'exit at ', index, 'th index'
            index += 400

    return Sfin, Afin
Ejemplo n.º 6
0
def OP_GMCA(M, Aori, Sori, Aini):
    '''Implementation of outliers pursuit combined with GMCA. The implementation of outliers pursuit, 
     performed for different parameters values, followed the one proposed in 'Robust PCA via Outlier Pursuit', H.Xu et al, IEEE TIT 2012.
     The notations taken are also the ones proposed in the aforementioned  paper.
     Inputs:
     - M: the observations, of size m by t. The outliers should be sparsely represented in this domain (use Otransf, see XMCA, if needed)
     - Aori: the reference mixing matrix, size m by n
     - Sori: the reference sources (in the direct domain) (are sparely represented in DCT, via Stransf, in XMCA)
     - Aini: the mixing matrix for the initialization of GMCA
     -Outputs:
     -Send: the estimated sources, size n by t
     -Aend: estimated mixing matrix, size m by n
     -Oend: estimated outliers, size m by t.
     '''

    m = np.shape(M)[0]  #dimension m

    muOri = 0.99 * np.linalg.norm(M, 'fro')
    errorX = 1e5
    flagExit = 0
    delta = 1e-5
    nu = 0.9
    index = 1
    muBar = delta * muOri
    prevRank = 0

    while flagExit == 0 and index < 50:  #Test for different parameter values

        Lambda = 1. / (np.sqrt(dS['t'])) * index / 5.  #Threshold value

        mu = muOri

        t = 1.
        t_ = 1.
        k = 0
        kMax = 15000
        convM = 1
        L = np.zeros(np.shape(M))
        L_ = np.zeros(np.shape(M))
        C = np.zeros(np.shape(M))
        C_ = np.zeros(np.shape(M))
        try:

            while (k < kMax
                   and convM > 1e-5) or k < 30:  #While have not converge

                Yl = L + (t_ - 1.) / t * (L - L_)
                Yc = C + (t_ - 1.) / t * (C - C_)

                Gl = Yl - 0.5 * (Yl + Yc - M)
                Gc = Yc - 0.5 * (Yl + Yc - M)

                L_ = L.copy()
                U, s2, UT = np.linalg.svd(np.dot(Gl, Gl.T),
                                          full_matrices=False)
                s = np.sqrt(s2)  # eigenvalues of (M-O+Y*1./mu)
                S = np.zeros((m, m))
                S[:m, :m] = np.diag(s)
                Sinv = S.copy()
                Sinv[S > 0] = 1. / S[S > 0]
                V = np.dot(Sinv.T, np.dot(UT, Gl))
                S = softThres(S, mu / 2.)  # Threshold of the eigenvalues
                L = np.dot(U, np.dot(S, V))

                C_ = C.copy()
                C = Gc * np.maximum(
                    0, 1. - Lambda * mu / 2. / np.linalg.norm(Gc, axis=0))
                t_ = t
                t = (1. + np.sqrt(4 * t_**2 + 1)) / 2.
                mu = max(nu * mu, muBar)
                k += 1
                convM = np.linalg.norm(L - L_, 'fro') / (
                    np.linalg.norm(L_, 'fro') + 1e-16) + np.linalg.norm(
                        C - C_, 'fro') / (np.linalg.norm(C_, 'fro') + 1e-16)

            L = XMCA.Stransf(L)  #DCT/ domain in which the sources are sparse

            if np.linalg.matrix_rank(L) >= dS[
                    'n'] and prevRank > 0:  #If the low rank term, L, has a rank larger or equal to n.
                u, s, v = np.linalg.svd(np.dot(L, L.T))
                Aini = u[:, 0:dS['n']]
                St, A = XMCA.AMCA(L, Aini, 0)  #GMCA
                S = XMCA.Sback(St)
                S, A = reOrder(A, S, Aori, Sori)
                deltaGMCA = np.sum(
                    np.abs(np.linalg.pinv(A).dot(Aori) - np.eye(dS['n']))) / (
                        dS['n']**2)  #compute the corresponding error
                if deltaGMCA < errorX:
                    #If there is an improvement, keep this results
                    errorX = deltaGMCA
                    Send = S.copy()
                    Aend = A.copy()
                    Oend = C.copy()

                elif deltaGMCA > 1.5 * errorX:  # if the error is significantly larger than the best one, stop the algorithm
                    index += 100

                index += 1

            elif np.linalg.matrix_rank(
                    L
            ) == 0:  # If the parameters are not correctly chosen, make a big step
                index += 5
            elif prevRank > 0:  # if we are not too far from the optimum
                index += 1
            elif np.linalg.matrix_rank(L) >= dS[
                    'n'] and prevRank == 0:  #if we have made a too large step
                index = max(1, index - 2)
            else:
                index += 1
            prevRank = np.linalg.matrix_rank(L)

        except np.linalg.LinAlgError:
            index += 1

    return Send, Aend, Oend