Exemple #1
0
def test_example_passing():
    # test when passing a minibatch of examples instead of the full dataloader
    for get_task in [get_fullyconnect_task]:
        loader, lc, parameters, model, function, n_output = get_task()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             function=function,
                             n_output=n_output)

        sum_mats = None
        tot_examples = 0
        for d in iter(loader):
            this_mat = PMatDense(generator=generator, examples=d)
            n_examples = len(d[0])

            if sum_mats is None:
                sum_mats = n_examples * this_mat
            else:
                sum_mats = n_examples * this_mat + sum_mats

            tot_examples += n_examples

        PMat_dense = PMatDense(generator=generator, examples=loader)

        check_tensors(PMat_dense.get_dense_tensor(),
                      (1. / tot_examples * sum_mats).get_dense_tensor())
Exemple #2
0
def test_jacobian_pblockdiag_vs_pdense():
    for get_task in linear_tasks + nonlinear_tasks:
        loader, lc, parameters, model, function, n_output = get_task()
        model.train()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             loader=loader,
                             function=function,
                             n_output=n_output)
        PMat_blockdiag = PMatBlockDiag(generator)
        PMat_dense = PMatDense(generator)

        # Test get_dense_tensor
        matrix_blockdiag = PMat_blockdiag.get_dense_tensor()
        matrix_dense = PMat_dense.get_dense_tensor()
        for layer_id, layer in lc.layers.items():
            start = lc.p_pos[layer_id]
            # compare blocks
            check_tensors(matrix_dense[start:start+layer.numel(),
                                       start:start+layer.numel()],
                          matrix_blockdiag[start:start+layer.numel(),
                                           start:start+layer.numel()])
            # verify that the rest is 0
            assert torch.norm(matrix_blockdiag[start:start+layer.numel(),
                                               start+layer.numel():]) < 1e-5
            assert torch.norm(matrix_blockdiag[start+layer.numel():,
                                               start:start+layer.numel()]) \
                < 1e-5
Exemple #3
0
def test_jacobian_pimplicit_vs_pdense():
    for get_task in linear_tasks + nonlinear_tasks:
        loader, lc, parameters, model, function, n_output = get_task()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             function=function,
                             n_output=n_output)
        PMat_implicit = PMatImplicit(generator=generator, examples=loader)
        PMat_dense = PMatDense(generator=generator, examples=loader)
        dw = random_pvector(lc, device=device)

        # Test trace
        check_ratio(PMat_dense.trace(), PMat_implicit.trace())

        # Test mv
        if ('BatchNorm1dLayer'
                in [l.__class__.__name__
                    for l in lc.layers.values()] or 'BatchNorm2dLayer'
                in [l.__class__.__name__ for l in lc.layers.values()]):
            with pytest.raises(NotImplementedError):
                PMat_implicit.mv(dw)
        else:
            check_tensors(
                PMat_dense.mv(dw).get_flat_representation(),
                PMat_implicit.mv(dw).get_flat_representation())

        # Test vTMv
        if ('BatchNorm1dLayer'
                in [l.__class__.__name__
                    for l in lc.layers.values()] or 'BatchNorm2dLayer'
                in [l.__class__.__name__ for l in lc.layers.values()]):
            with pytest.raises(NotImplementedError):
                PMat_implicit.vTMv(dw)
        else:
            check_ratio(PMat_dense.vTMv(dw), PMat_implicit.vTMv(dw))
Exemple #4
0
def test_jacobian_pquasidiag_vs_pdense():
    for get_task in [get_conv_task, get_fullyconnect_task]:
        loader, lc, parameters, model, function, n_output = get_task()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             function=function,
                             n_output=n_output)
        PMat_qd = PMatQuasiDiag(generator=generator, examples=loader)
        PMat_dense = PMatDense(generator=generator, examples=loader)

        # Test get_dense_tensor
        matrix_qd = PMat_qd.get_dense_tensor()
        matrix_dense = PMat_dense.get_dense_tensor()

        for layer_id, layer in lc.layers.items():
            start = lc.p_pos[layer_id]
            # compare diags
            sw = layer.weight.numel()

            check_tensors(
                torch.diag(
                    torch.diag(matrix_dense[start:start + sw,
                                            start:start + sw])),
                matrix_qd[start:start + sw, start:start + sw])

            if layer.bias is not None:
                sb = layer.bias.numel()
                check_tensors(
                    torch.diag(
                        torch.diag(matrix_dense[start + sw:start + sw + sb,
                                                start + sw:start + sw + sb])),
                    matrix_qd[start + sw:start + sw + sb,
                              start + sw:start + sw + sb])

                s_in = sw // sb
                for i in range(sb):
                    # check the strips bias/weight
                    check_tensors(
                        matrix_dense[start + i * s_in:start + (i + 1) * s_in,
                                     start + sw + i],
                        matrix_qd[start + i * s_in:start + (i + 1) * s_in,
                                  start + sw + i])

                    # verify that the rest is 0
                    assert torch.norm(matrix_qd[start + i * s_in:start +
                                                (i + 1) * s_in, start +
                                                sw:start + sw + i]) < 1e-10
                    assert torch.norm(
                        matrix_qd[start + i * s_in:start +
                                  (i + 1) * s_in, start + sw + i + 1:]) < 1e-10

                # compare upper triangular block with lower triangular one
                check_tensors(
                    matrix_qd[start:start + sw + sb, start + sw:],
                    matrix_qd[start + sw:, start:start + sw + sb].t())
Exemple #5
0
def test_jacobian_plowrank_vs_pdense():
    for get_task in nonlinear_tasks:
        loader, lc, parameters, model, function, n_output = get_task()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             function=function,
                             n_output=n_output)
        PMat_lowrank = PMatLowRank(generator=generator, examples=loader)
        PMat_dense = PMatDense(generator=generator, examples=loader)

        # Test get_dense_tensor
        matrix_lowrank = PMat_lowrank.get_dense_tensor()
        matrix_dense = PMat_dense.get_dense_tensor()
        check_tensors(matrix_dense, matrix_lowrank)
Exemple #6
0
def test_jacobian_pdense_vs_pushforward():
    # NB: sometimes the test with centering=True do not pass,
    # which is probably due to the way we compute centering
    # for PMatDense: E[x^2] - (Ex)^2 is notoriously not numerically stable
    for get_task in linear_tasks + nonlinear_tasks:
        for centering in [True, False]:
            loader, lc, parameters, model, function, n_output = get_task()
            model.train()
            generator = Jacobian(layer_collection=lc,
                                 model=model,
                                 loader=loader,
                                 function=function,
                                 n_output=n_output,
                                 centering=centering)
            push_forward = PushForwardDense(generator)
            pull_back = PullBackDense(generator, data=push_forward.data)
            PMat_dense = PMatDense(generator)
            dw = random_pvector(lc, device=device)
            n = len(loader.sampler)

            # Test get_dense_tensor
            jacobian = push_forward.get_dense_tensor()
            sj = jacobian.size()
            PMat_computed = torch.mm(jacobian.view(-1, sj[2]).t(),
                                     jacobian.view(-1, sj[2])) / n
            check_tensors(PMat_computed,
                          PMat_dense.get_dense_tensor())

            # Test vTMv
            vTMv_PMat = PMat_dense.vTMv(dw)
            Jv_pushforward = push_forward.mv(dw)
            Jv_pushforward_flat = Jv_pushforward.get_flat_representation()
            vTMv_pushforward = torch.dot(Jv_pushforward_flat.view(-1),
                                         Jv_pushforward_flat.view(-1)) / n
            check_ratio(vTMv_pushforward, vTMv_PMat)

            # Test Mv
            Mv_PMat = PMat_dense.mv(dw)
            Mv_pf_pb = pull_back.mv(Jv_pushforward)
            check_tensors(Mv_pf_pb.get_flat_representation() / n,
                          Mv_PMat.get_flat_representation())
Exemple #7
0
def test_conv_impl_switch():
    loader, lc, parameters, model, function, n_output = get_conv_task()
    generator = Jacobian(layer_collection=lc,
                         model=model,
                         function=function,
                         n_output=n_output)

    with jacobian.use_unfold_impl_for_convs():
        PMat_dense_unfold = PMatDense(generator=generator, examples=loader)

    with jacobian.use_conv_impl_for_convs():
        PMat_dense_conv = PMatDense(generator=generator, examples=loader)

    check_tensors(PMat_dense_unfold.get_dense_tensor(),
                  PMat_dense_conv.get_dense_tensor())
def test_dense():
    for get_task in nonlinear_tasks:
        loader, lc, parameters, model1, function1, n_output = get_task()
        _, _, _, model2, function2, _ = get_task()

        generator1 = Jacobian(layer_collection=lc,
                              model=model1,
                              function=function1,
                              n_output=n_output)
        generator2 = Jacobian(layer_collection=lc,
                              model=model2,
                              function=function1,
                              n_output=n_output)
        M_dense1 = PMatDense(generator=generator1, examples=loader)
        M_dense2 = PMatDense(generator=generator2, examples=loader)

        prod = M_dense1.mm(M_dense2)

        M_dense1_tensor = M_dense1.get_dense_tensor()
        M_dense2_tensor = M_dense2.get_dense_tensor()

        prod_tensor = prod.get_dense_tensor()

        check_tensors(torch.mm(M_dense1_tensor, M_dense2_tensor), prod_tensor)
Exemple #9
0
def test_jacobian_pdiag_vs_pdense():
    for get_task in nonlinear_tasks:
        loader, lc, parameters, model, function, n_output = get_task()
        model.train()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             loader=loader,
                             function=function,
                             n_output=n_output)
        PMat_diag = PMatDiag(generator)
        PMat_dense = PMatDense(generator)
        dw = random_pvector(lc, device=device)

        # Test get_dense_tensor
        matrix_diag = PMat_diag.get_dense_tensor()
        matrix_dense = PMat_dense.get_dense_tensor()
        check_tensors(torch.diag(matrix_diag),
                      torch.diag(matrix_dense))
        assert torch.norm(matrix_diag -
                          torch.diag(torch.diag(matrix_diag))) < 1e-5

        # Test trace
        check_ratio(torch.trace(matrix_diag),
                    PMat_diag.trace())

        # Test frobenius
        check_ratio(torch.norm(matrix_diag),
                    PMat_diag.frobenius_norm())

        # Test mv
        mv_direct = torch.mv(matrix_diag, dw.get_flat_representation())
        mv_PMat_diag = PMat_diag.mv(dw)
        check_tensors(mv_direct,
                      mv_PMat_diag.get_flat_representation())

        # Test vTMv
        vTMv_direct = torch.dot(mv_direct, dw.get_flat_representation())
        vTMv_PMat_diag = PMat_diag.vTMv(dw)
        check_ratio(vTMv_direct, vTMv_PMat_diag)

        # Test inverse
        regul = 1e-3
        PMat_diag_inverse = PMat_diag.inverse(regul)
        prod = torch.mm(matrix_diag + regul * torch.eye(lc.numel(),
                                                        device=device),
                        PMat_diag_inverse.get_dense_tensor())
        check_tensors(torch.eye(lc.numel(), device=device),
                      prod)

        # Test solve
        regul = 1e-3
        Mv_regul = torch.mv(matrix_diag +
                            regul * torch.eye(PMat_diag.size(0),
                                              device=device),
                            dw.get_flat_representation())
        Mv_regul = PVector(layer_collection=lc,
                           vector_repr=Mv_regul)
        dw_using_inv = PMat_diag.solve(Mv_regul, regul=regul)
        check_tensors(dw.get_flat_representation(),
                      dw_using_inv.get_flat_representation(), eps=5e-3)

        # Test get_diag
        diag_direct = torch.diag(matrix_diag)
        diag_PMat_diag = PMat_diag.get_diag()
        check_tensors(diag_direct, diag_PMat_diag)

        # Test add, sub, rmul
        loader, lc, parameters, model, function, n_output = get_task()
        model.train()
        generator = Jacobian(layer_collection=lc,
                             model=model,
                             loader=loader,
                             function=function,
                             n_output=n_output)
        PMat_diag2 = PMatDiag(generator)

        check_tensors(PMat_diag.get_dense_tensor() +
                      PMat_diag2.get_dense_tensor(),
                      (PMat_diag + PMat_diag2).get_dense_tensor())
        check_tensors(PMat_diag.get_dense_tensor() -
                      PMat_diag2.get_dense_tensor(),
                      (PMat_diag - PMat_diag2).get_dense_tensor())
        check_tensors(1.23 * PMat_diag.get_dense_tensor(),
                      (1.23 * PMat_diag).get_dense_tensor())
Exemple #10
0
def test_jacobian_pdense():
    for get_task in nonlinear_tasks:
        for centering in [True, False]:
            loader, lc, parameters, model, function, n_output = get_task()
            model.train()
            generator = Jacobian(layer_collection=lc,
                                 model=model,
                                 loader=loader,
                                 function=function,
                                 n_output=n_output,
                                 centering=centering)
            PMat_dense = PMatDense(generator)
            dw = random_pvector(lc, device=device)

            # Test get_diag
            check_tensors(torch.diag(PMat_dense.get_dense_tensor()),
                          PMat_dense.get_diag())

            # Test frobenius
            frob_PMat = PMat_dense.frobenius_norm()
            frob_direct = (PMat_dense.get_dense_tensor()**2).sum()**.5
            check_ratio(frob_direct, frob_PMat)

            # Test trace
            trace_PMat = PMat_dense.trace()
            trace_direct = torch.trace(PMat_dense.get_dense_tensor())
            check_ratio(trace_PMat, trace_direct)

            # Test solve
            # NB: regul is high since the matrix is not full rank
            regul = 1e-3
            Mv_regul = torch.mv(PMat_dense.get_dense_tensor() +
                                regul * torch.eye(PMat_dense.size(0),
                                                  device=device),
                                dw.get_flat_representation())
            Mv_regul = PVector(layer_collection=lc,
                               vector_repr=Mv_regul)
            dw_using_inv = PMat_dense.solve(Mv_regul, regul=regul)
            check_tensors(dw.get_flat_representation(),
                          dw_using_inv.get_flat_representation(), eps=5e-3)

            # Test inv
            PMat_inv = PMat_dense.inverse(regul=regul)
            check_tensors(dw.get_flat_representation(),
                          PMat_inv.mv(PMat_dense.mv(dw) + regul * dw)
                          .get_flat_representation(), eps=5e-3)

            # Test add, sub, rmul
            loader, lc, parameters, model, function, n_output = get_task()
            model.train()
            generator = Jacobian(layer_collection=lc,
                                 model=model,
                                 loader=loader,
                                 function=function,
                                 n_output=n_output,
                                 centering=centering)
            PMat_dense2 = PMatDense(generator)

            check_tensors(PMat_dense.get_dense_tensor() +
                          PMat_dense2.get_dense_tensor(),
                          (PMat_dense + PMat_dense2).get_dense_tensor())
            check_tensors(PMat_dense.get_dense_tensor() -
                          PMat_dense2.get_dense_tensor(),
                          (PMat_dense - PMat_dense2).get_dense_tensor())
            check_tensors(1.23 * PMat_dense.get_dense_tensor(),
                          (1.23 * PMat_dense).get_dense_tensor())