Exemplo n.º 1
0
def network_karcher_mean_armijo(CList, pList, maxIter=50):
    # performing backtracking line search
    CBase = CList[0]
    pBase = pList[0]
    Delta = 1000
    counter = 0
    loss_init = frechet_loss(CBase, CList, pBase, pList)
    Frechet_Loss = [loss_init]
    #Delta = loss_init
    print('Iter', 'Frechet_Loss')
    print(counter, loss_init)
    #while counter < maxIter: # This is a pretty arbitrary stopping condition
    while Delta > 1e-10 * loss_init and counter < maxIter:  # This is a pretty arbitrary stopping condition
        C0, pBase, gradient = frechet_gradient(CList, pList, CBase, pBase)
        # perform backtracking line search with following parameters:
        # currently at C0, descent direction = gradient,
        # actual gradient = -gradient, loss function = frechet_loss

        f_val = frechet_loss(C0, CList, pBase, pList)

        def frechet_loss_at(Y):
            return frechet_loss(Y, CList, pBase, pList)

        # Optionally normalize descent direction. Our gradient is minus the
        # true gradient
        pk = np.divide(gradient, np.linalg.norm(gradient))
        # Can replace gradient below by pk
        alpha, fc, f_val = line_search_armijo(frechet_loss_at, C0, gradient,
                                              -gradient, f_val)
        CBase = exp_map(C0, alpha *
                        gradient)  #step size satisfying Armijo condition
        Frechet_Loss.append(f_val)

        Delta = abs(Frechet_Loss[-1] - Frechet_Loss[-2])
        counter = counter + 1
        print(counter, f_val)
    print('Initial Loss: ' + str(Frechet_Loss[0]))
    print('Loss for Minimizer: ' + str(Frechet_Loss[-1]))
    return CBase, pBase, Frechet_Loss
def network_karcher_mean_armijo_sched_compress(CBase, pBase, CList,pList,budget,exploreIter = 20, maxIter = 50):
    # Take exploreIter full gradient steps at first,
    # then do backtracking line search up to maxIter
    Delta = 1000
    counter = 0
    loss_init = frechet_loss(CBase,CList,pBase,pList)
    Frechet_Loss = [loss_init]
    #Delta = loss_init
    print('Iter','Frechet_Loss')
    print(counter, loss_init)

    tmpC = [CBase]
    tmpP = [pBase]
    # Do full gradient steps
    while counter < exploreIter:
        CBase, pBase, gradient = frechet_gradient_compressed(CList,pList,CBase,pBase,budget)
        print('current size ', CBase.shape)
        CBase = exp_map(CBase,gradient)
        tmpC.append(CBase)
        tmpP.append(pBase)
        f_val = frechet_loss(CBase, CList, pBase, pList)
        Frechet_Loss.append(f_val)
        counter = counter + 1
        print(counter, f_val, ' full gradient step')

    # Set CBase to be the best seed point
    idx = Frechet_Loss.index(min(Frechet_Loss))
    CBase = tmpC[idx]
    pBase = tmpP[idx]
    print('setting seed at ', idx)
    f_val = frechet_loss(CBase, CList, pBase, pList)
    print('seed loss is', f_val)

    #while counter < maxIter: # This is a pretty arbitrary stopping condition
    while Delta > 1e-10*loss_init and counter < maxIter: # This is a pretty arbitrary stopping condition
        C0, pBase, gradient = frechet_gradient_compressed(CList,pList,CBase,pBase,budget)
        # perform backtracking line search with following parameters:
        # currently at CBase, descent direction = gradient, 
        # actual gradient = -gradient, loss function = frechet_loss
        def frechet_loss_at(Y):
            return frechet_loss(Y,CList,pBase,pList)
        
        # Optionally normalize descent direction. Our gradient is minus the
        # true gradient
        # gradSz = np.linalg.norm(gradient)
        #if gradSz > 0:
         #   pk = np.divide(gradient,np.linalg.norm(gradient)) 
        try:
            alpha, fc, f_val = line_search_armijo(frechet_loss_at, C0, gradient, -gradient, f_val)
        except:
            print('exception at iteration ', counter)
            f_val = frechet_loss_at(C0)
            print('error at current center is ', f_val)
            return C0, pBase, Frechet_Loss

        CBase = exp_map(CBase, alpha*gradient) #step size satisfying Armijo condition    
        Frechet_Loss.append(f_val)
        
        Delta = abs(Frechet_Loss[-1]-Frechet_Loss[-2])
        counter = counter + 1
        print(counter, f_val, 'step scale',alpha)
    print('Initial Loss: '+str(Frechet_Loss[0]))
    print('Loss for Minimizer: '+str(Frechet_Loss[-1]))
    return CBase, pBase, Frechet_Loss
def gwa_cg(a, b, M, reg, f, df, G0=None, numItermax=200,
       stopThr=1e-9, verbose=False, log=False):
# Please refer to cg function in pot package for documentation

    loop = 1

    if log:
        log = {'loss': []}

    if G0 is None:
        G = np.outer(a, b)
    else:
        G = G0

    def cost(G):
        return np.sum(M * G) + reg * f(G)

    f_val = cost(G)
    if log:
        log['loss'].append(f_val)

    it = 0

    if verbose:
        print('{:5s}|{:12s}|{:8s}'.format(
            'It.', 'Loss', 'Delta loss') + '\n' + '-' * 32)
        print('{:5d}|{:8e}|{:8e}'.format(it, f_val, 0))

    while loop:

        it += 1
        old_fval = f_val

        # problem linearization
        Mi = M + reg * df(G)
        # set M positive
        Mi += Mi.min()

        # solve linear program
        Gc = ot.emd(a, b, Mi)

        deltaG = Gc - G

        # line search
        alpha, fc, f_val = line_search_armijo(cost, G, deltaG, Mi, f_val)
        
        # added May 19, 2020 to avoid multiplication between NoneType and Float
        if alpha is not None:
            G = G + alpha * deltaG

        # test convergence
        if it >= numItermax:
            loop = 0
        
        # extra stopping condition in gwa_cg
        # to avoid dividing by zero
        if f_val == 0:
            loop = 0

        delta_fval = (f_val - old_fval) / abs(f_val)
        if abs(delta_fval) < stopThr:
            loop = 0

        if log:
            log['loss'].append(f_val)

        if verbose:
            if it % 20 == 0:
                print('{:5s}|{:12s}|{:8s}'.format(
                    'It.', 'Loss', 'Delta loss') + '\n' + '-' * 32)
            print('{:5d}|{:8e}|{:8e}'.format(it, f_val, delta_fval))

    if log:
        return G, log
    else:
        return G
Exemplo n.º 4
0
    def generalized_conditional_gradient(self, source, target, source_labels):
        '''
        Algoritmo GCG: gradiente condicional generalizado. Calcula la matriz
        de transporte gamma.

        Argumentos
        --------------------------------
        source: numpy.ndarray shape(m, k).
            datos del dominio fuente.
        target: numpy.ndarray shape(n, k).
            datos del dominio objetivo.
        source_labels: numpy.ndarray shape(m, )
            etiquetas del dominio fuente.

        Retorno
        -----------------------------------
        G: numpy.ndarray shape(m, n)
            Matriz gamma de transporte.
        '''
        loop = True
        a, b = self.compute_probs(source), self.compute_probs(target)
        G = np.outer(a, b)
        M = self.cost_transport_matrix(source, target)
        cost, cost_gradient, f, df = self.computation_graph(
                source, target, source_labels
        )
        f_val = cost(G)
        it = 0
        while loop:
            it += 1
            old_fval = f_val

            # problem linearization
            Mi = M + self.eta * df(G)

            # solve linear program with Sinkhorn
            Gc = sinkhorn(
                    a, b, Mi, self.labda, numItermax=self.num_iters_sinkhorn
            )
            deltaG = Gc - G
            # line search
            # Que yo sepa la evaluación de la función se hace con G, no con
            # Gc
            dcost = cost_gradient(G)
            alpha, fc, f_val = line_search_armijo(
                    cost, G, deltaG, dcost, f_val
            )
            if alpha is None:  # No se si esto es lo correcto
                return G
            G = G + alpha * deltaG

            # test convergence
            if it >= self.num_iters_sinkhorn:
                loop = False

            # delta_fval = (f_val - old_fval) / abs(f_val)
            delta_fval = (f_val - old_fval)
            # print('fval:', f_val, 'delta_fval:', delta_fval)
            if abs(delta_fval) < self.convergence_threshold:
                loop = False
        return G