예제 #1
0
    def draw_das(D, ax):
        idx_img = info['show_reconstruction']
        sampler = D.sampler()
        S, _, _ = sampler.decode(D[idx_img])
        sky_model = D.ground_truth[idx_img]

        A = phased_array.steering_operator(D.XYZ, D.R, D.wl)
        alpha = 1 / (2 * pylinalg.eighMax(A))
        beta = 2 * D.lambda_[idx_img] * alpha * (1 - D.gamma) + 1

        exec_time = time.time()
        das = spectral.DAS(D.XYZ, S, D.wl, D.R) * 2 * alpha / beta
        exec_time = time.time() - exec_time

        if info['interpolation_order'] is not None:
            N = info['interpolation_order']
            approximate_kernel = True if (N > 15) else False
            interp = interpolate.Interpolator(N, approximate_kernel)
            N_s = N_px = D.R.shape[1]
            das = interp.__call__(weight=np.ones((N_s, )),
                                  support=D.R,
                                  f=das.reshape((1, N_px)),
                                  r=D.R)
            das = np.clip(das, a_min=0, a_max=None)

        das_plot = s2image.Image(data=das, grid=D.R)
        das_plot.draw(catalog=sky_model.xyz,
                      projection=info['projection'],
                      use_contours=False,
                      catalog_kwargs=dict(edgecolor='g', ),
                      ax=ax)
        ax.set_title(f'DAS, {exec_time:.02f} [s]')
예제 #2
0
    def draw_apgd_filter(D, ax):
        R_focus = np.mean(D.R, axis=1)
        R_focus /= linalg.norm(R_focus)
        idx_focus = np.argmax(R_focus @ D.R)

        A = phased_array.steering_operator(D.XYZ, D.R, D.wl)
        N_px = D.R.shape[1]
        alpha = 1 / (2 * pylinalg.eighMax(A))
        beta = 2 * np.median(D.lambda_) * alpha * (1 - D.gamma) + 1
        psf = pylinalg.psf_exp(D.XYZ, D.R, D.wl, center=R_focus)
        filter = (e(idx_focus, N_px) - 2 * alpha * psf) / beta

        if info['interpolation_order'] is not None:
            N = info['interpolation_order']
            approximate_kernel = True if (N > 15) else False
            interp = interpolate.Interpolator(N, approximate_kernel)
            N_s = N_px = D.R.shape[1]
            filter = interp.__call__(weight=np.ones((N_s, )),
                                     support=D.R,
                                     f=filter.reshape((1, N_px)),
                                     r=D.R)
            filter = np.clip(filter, a_min=0, a_max=None)

        filter_plot = s2image.Image(data=filter, grid=D.R)
        filter_plot.draw(projection=info['projection'],
                         use_contours=False,
                         catalog_kwargs=dict(edgecolor='g', ),
                         ax=ax)
        ax.set_title(r'$p_{\theta}^{APGD}\left(\widetilde{L}\right)$')
예제 #3
0
    def draw_apgd_psf(D, ax):
        R_focus = np.mean(D.R, axis=1)
        R_focus /= linalg.norm(R_focus)

        A = phased_array.steering_operator(D.XYZ, D.R, D.wl)
        alpha = 1 / (2 * pylinalg.eighMax(A))
        beta = 2 * np.median(D.lambda_) * alpha * (1 - D.gamma) + 1
        psf = (pylinalg.psf_exp(D.XYZ, D.R, D.wl, center=R_focus) *
               (2 * alpha / beta))

        if info['interpolation_order'] is not None:
            N = info['interpolation_order']
            approximate_kernel = True if (N > 15) else False
            interp = interpolate.Interpolator(N, approximate_kernel)
            N_s = N_px = D.R.shape[1]
            psf = interp.__call__(weight=np.ones((N_s, )),
                                  support=D.R,
                                  f=psf.reshape((1, N_px)),
                                  r=D.R)
            psf = np.clip(psf, a_min=0, a_max=None)

        psf_plot = s2image.Image(data=psf, grid=D.R)
        psf_plot.draw(projection=info['projection'],
                      use_contours=False,
                      catalog_kwargs=dict(edgecolor='g', ),
                      ax=ax)
        ax.set_title(r'$\Psi_{APGD}(r, r_{0})$')
예제 #4
0
def get_field(D, P, idx_img, img_type):
    """
    Parameters
    ----------
    D : list(:py:class:`~deepwave.nn.DataSet`)
        (9,) multi-frequency datasets.
    P : list(:py:class:`~deepwave.nn.crnn.Parameter`)
        (9,) multi-frequency trained parameters.
    idx_img : int
        Image index
    img_type : str
        One of ['APGD', 'RNN', 'DAS']

    Returns
    -------
    I : :py:class:`~numpy.ndarray`
        (9, N_px) frequency intensities of specified image.
    """
    I = []
    for idx_freq in range(9):
        Df, Pf = D[idx_freq], P[idx_freq]

        N_antenna = Df.XYZ.shape[1]
        N_px = Df.R.shape[1]
        K = int(Pf['K'])
        parameter = crnn.Parameter(N_antenna, N_px, K)
        sampler = Df.sampler()

        A = phased_array.steering_operator(Df.XYZ, Df.R, Df.wl)
        if img_type == 'APGD':
            _, I_apgd, _ = sampler.decode(Df[idx_img])
            I.append(I_apgd)
        elif img_type == 'RNN':
            Ln, _ = graph.laplacian_exp(Df.R, normalized=True)
            afunc = lambda _: func.retanh(Pf['tanh_lin_limit'], _)
            p_opt = Pf['p_opt'][np.argmin(Pf['v_loss'])]
            S, _, I_prev = sampler.decode(Df[idx_img])
            N_layer = Pf['N_layer']
            rnn_eval = crnn.Evaluator(N_layer, parameter, p_opt, Ln, afunc)
            I_rnn = rnn_eval(S, I_prev)
            I.append(I_rnn)
        elif img_type == 'DAS':
            S, _, _ = sampler.decode(Df[idx_img])
            alpha = 1 / (2 * pylinalg.eighMax(A))
            beta = 2 * Df.lambda_[idx_img] * alpha * (1 - Df.gamma) + 1

            I_das = spectral.DAS(Df.XYZ, S, Df.wl, Df.R) * 2 * alpha / beta
            I.append(I_das)
        else:
            raise ValueError(f'Parameter[img_type] invalid.')

    I = np.stack(I, axis=0)
    return I
예제 #5
0
def train_network(args):
    """
    Parameters
    ----------
    args : :py:class:`~argparse.Namespace`

    Returns
    -------
    opt : dict
        p_opt : :py:class:`~numpy.ndarray`
            (N_epoch + 1, N_cell) optimized parameter per epoch.
            `p_opt[0] = p_apgd`
        iter_loss : :py:class:`~numpy.ndarray`
            (N_epoch, N_batch) loss function value per (epoch, batch) on
            training set.
        t_loss : :py:class:`~numpy.ndarray`
            (N_epoch + 1,) loss function value per epoch on training set.
        v_loss : :py:class:`~numpy.ndarray`
            (N_epoch + 1,) loss function value per epoch on validation set.
        t : :py:class:`~numpy.ndarray`
            (N_epoch,) execution time [s] per epoch.
            Includes time to compute training/validation loss.
        idx_t : :py:class:`~numpy.ndarray`
            (N_k1,) sample indices used for training set.
        idx_v : :py:class:`~numpy.ndarray`
            (N_k2,) sample indices used for validation set.
        K : int
            Order of polynomial filter.
        D_lambda : float
        tau_lambda : float
        N_layer : int
        psf_threshold : float
        tanh_lin_limit : float
        lr : float
        mu : float
        batch_size : int
    """
    if args.seed is not None:
        np.random.seed(args.seed)

    D = nn.DataSet.from_file(str(args.dataset))
    A = phased_array.steering_operator(D.XYZ, D.R, D.wl)
    N_antenna, N_px = A.shape
    sampler = nn.Sampler(N_antenna, N_px)

    # Set optimization initial point.
    p_apgd, K = crnn.APGD_Parameter(D.XYZ, D.R, D.wl,
                                    lambda_=np.median(D.lambda_),
                                    gamma=D.gamma,
                                    L=2 * pylinalg.eighMax(A),
                                    eps=args.psf_threshold)
    parameter = crnn.Parameter(N_antenna, N_px, K)
    p0 = p_apgd.copy()
    if args.random_initializer:
        p_mu, p_D, p_tau = parameter.decode(p0)
        if not args.fix_mu:
            mu_step = np.abs(p_mu[~np.isclose(p_mu, 0)]).min()
            p_mu[:] = mu_step * np.random.randn(K + 1)
        if not args.fix_tau:
            tau_step = np.abs(p_tau[~np.isclose(p_tau, 0)]).min()
            p_tau[:] = tau_step * np.random.randn(N_px)
        if not args.fix_D:
            D_step = np.abs(p_D[~np.isclose(p_D, 0)]).min() / 2  # because complex-valued.
            p_D[:] = D_step * (     np.random.randn(N_antenna, N_px) +
                               1j * np.random.randn(N_antenna, N_px))

    R_laplacian, _ = graph.laplacian_exp(D.R, normalized=True)

    afunc = (lambda x: func.retanh(args.tanh_lin_limit, x),
             lambda x: func.d_retanh(args.tanh_lin_limit, x))
    trainable_parameter = (('mu', not args.fix_mu),
                           ('D', not args.fix_D),
                           ('tau', not args.fix_tau))
    sample_loss = crnn.SampleLossFunction(args.N_layer, parameter, sampler, R_laplacian,
                                          args.loss, afunc, trainable_parameter)
    ridge_loss = crnn.D_RidgeLossFunction(args.D_lambda, parameter)
    laplacian_loss = crnn.LaplacianLossFunction(R_laplacian, args.tau_lambda, parameter)
    sgd_solver = optim.StochasticGradientDescent(func=[sample_loss, ridge_loss, laplacian_loss],
                                                 batch_size=args.batch_size,
                                                 N_epoch=args.N_epoch,
                                                 alpha=args.lr,
                                                 mu=args.mu,
                                                 verbosity='HIGH')

    log_fname = (pathlib.Path(args.parameter.parent) /
                 (args.parameter.stem + ".log"))
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s | %(message)s',
                        filename=log_fname,
                        filemode='w')
    # Setup logging to stdout.
    console = logging.StreamHandler(sys.stdout)
    console.setLevel(logging.DEBUG)
    console_formatter = logging.Formatter('%(asctime)s | %(message)s')
    console.setFormatter(console_formatter)
    logging.getLogger(__name__).addHandler(console)
    logging.info(str(args))

    ### Dataset Preprocessing: drop all-0 samples + permutation
    _, I, _ = sampler.decode(D[:])
    sample_mask = ~np.isclose(I.sum(axis=1), 0)
    if args.tv_index is None:  # Random split
        idx_valid = np.flatnonzero(sample_mask)
        idx_sample = np.random.permutation(idx_valid)

        N_sample = len(idx_valid)
        idx_ts = idx_sample[int(N_sample * args.tv_ratio):]
        idx_vs = idx_sample[:int(N_sample * args.tv_ratio)]
    else:  # Deterministic split
        idx_tv = np.load(args.tv_index)
        if not (('idx_train' in idx_tv) and ('idx_test' in idx_tv)):
            raise ValueError('Parameter[tv_index] does not have keys "idx_train" and "idx_test".')
        idx_ts = idx_tv['idx_train']
        if not (argcheck.has_integers(idx_ts) and
                np.all((0 <= idx_ts) & (idx_ts < len(D)))):
            raise ValueError('Specified "idx_ts" values must be integer and in {0, ..., len(D) - 1}.')
        idx_vs = idx_tv['idx_test']
        if not (argcheck.has_integers(idx_vs) and
                np.all((0 <= idx_vs) & (idx_vs < len(D)))):
            raise ValueError('Specified "idx_vs" values must be integer and in {0, ..., len(D) - 1}.')

        idx_invalid = np.flatnonzero(~sample_mask)
        idx_ts = np.setdiff1d(idx_ts, idx_invalid)
        idx_vs = np.setdiff1d(idx_vs, idx_invalid)

    D_ts = nn.DataSet(D[idx_ts], D.XYZ, D.R, D.wl,
                      ground_truth=[D.ground_truth[idx] for idx in idx_ts],
                      lambda_=np.array([np.median(D.lambda_[idx_ts])] * len(idx_ts)),
                      gamma=D.gamma,
                      N_iter=D.N_iter[idx_ts],
                      tts=D.tts[idx_ts])
    D_vs = nn.DataSet(D[idx_vs], D.XYZ, D.R, D.wl,
                      ground_truth=[D.ground_truth[idx] for idx in idx_vs],
                      lambda_=np.array([np.median(D.lambda_[idx_vs])] * len(idx_vs)),
                      gamma=D.gamma,
                      N_iter=D.N_iter[idx_vs],
                      tts=D.tts[idx_vs])
    out = sgd_solver.fit(D_ts, D_vs, p0, file_name=args.parameter)

    # Augment output with extra information.
    out = dict(**out,
               D_lambda=args.D_lambda,
               tau_lambda=args.tau_lambda,
               N_layer=args.N_layer,
               psf_threshold=args.psf_threshold,
               tanh_lin_limit=args.tanh_lin_limit,
               lr=args.lr,
               mu=args.mu,
               batch_size=args.batch_size,
               K=K,
               idx_t=idx_ts,
               idx_v=idx_vs,
               loss=args.loss)
    return out
예제 #6
0
def process(args):
    file = pathlib.Path(args.dataset).expanduser().absolute()
    if not (file.exists() and (file.suffix == '.npz')):
        raise ValueError('Dataset is non-conformant.')
    D = nn.DataSet.from_file(str(file))
    N_sample = len(D)

    if not (0 <= args.img_idx < N_sample):
        raise ValueError('Parameter[img_idx] is out-of-bounds.')

    S, I_apgd, I_prev = D.sampler().decode(D[args.img_idx])
    I_das = spectral.DAS(D.XYZ, S, D.wl, D.R)

    # Rescale DAS to lie on same range as APGD
    A = phased_array.steering_operator(D.XYZ, D.R, D.wl)
    alpha = 1 / (2 * pylinalg.eighMax(A))
    beta = 2 * D.lambda_[args.img_idx] * alpha * (1 - D.gamma) + 1
    I_das *= (2 * alpha) / beta

    if args.interpolation_order is not None:
        N = args.interpolation_order
        approximate_kernel = True if (N > 15) else False
        interp = interpolate.Interpolator(N, approximate_kernel)
        N_s = N_px = D.R.shape[1]

        I_prev = interp.__call__(weight=np.ones((N_s, )),
                                 support=D.R,
                                 f=I_prev.reshape((1, N_px)),
                                 r=D.R)
        I_prev = np.clip(I_prev, a_min=0, a_max=None)

        I_apgd = interp.__call__(weight=np.ones((N_s, )),
                                 support=D.R,
                                 f=I_apgd.reshape((1, N_px)),
                                 r=D.R)
        I_apgd = np.clip(I_apgd, a_min=0, a_max=None)

        I_das = interp.__call__(weight=np.ones((N_s, )),
                                support=D.R,
                                f=I_das.reshape((1, N_px)),
                                r=D.R)
        I_das = np.clip(I_das, a_min=0, a_max=None)

    fig = plt.figure()
    ax_prev = fig.add_subplot(131)
    ax_apgd = fig.add_subplot(132)
    ax_das = fig.add_subplot(133)

    s2image.Image(I_prev, D.R).draw(catalog=D.ground_truth[args.img_idx].xyz,
                                    projection=args.projection,
                                    catalog_kwargs=dict(edgecolor='g', ),
                                    ax=ax_prev)
    ax_prev.set_title(r'$APGD_{init}$')

    s2image.Image(I_apgd, D.R).draw(catalog=D.ground_truth[args.img_idx].xyz,
                                    projection=args.projection,
                                    catalog_kwargs=dict(edgecolor='g', ),
                                    ax=ax_apgd)
    ax_apgd.set_title('APGD')

    s2image.Image(I_das, D.R).draw(catalog=D.ground_truth[args.img_idx].xyz,
                                   projection=args.projection,
                                   catalog_kwargs=dict(edgecolor='g', ),
                                   ax=ax_das)
    ax_das.set_title('DAS')

    fig.show()
예제 #7
0
def solve(S,
          A,
          lambda_=None,
          gamma=0.5,
          L=None,
          d=50,
          x0=None,
          eps=1e-3,
          N_iter_max=200,
          verbosity='LOW',
          momentum=True):
    """
    APGD solution to the Acoustic Camera problem. (Algorithm 3.1)

    Parameters
    ----------
    S : :py:class:`~numpy.ndarray`
        (M, M) visibility matrix
    A : :py:class:`~numpy.ndarray`
        (M, N) system steering matrix.
    lambda_ : float
        Regularization parameter.

        If `None`, then it is chosen according to Remark 3.4.
    gamma : float
        Linear trade-off between lasso and ridge regularizers.
    L : float
        Lipschitz constant of the gradient of the smooth function being
        optimized.

        If `None`, then it is estimated using
        :py:func:`~deepwave.tools.math.linalg.eighMax`.
    d : float
        Weight parameter as defined in [1].
    x0 : :py:class:`~numpy.ndarray`
        (N,) initial intensity field estimate.

        Defaults to 0 if not explicitly initialized.
    eps : float
        Relative tolerance stopping threshold.
    N_iter_max : int
        Maximum number of iterations.
    verbosity : str
        One of 'NONE', 'LOW', 'HIGH', 'ALL'.
    momentum : bool
        If :py:class:`False`, disable Nesterov acceleration.

    Returns
    -------
    I_opt : dict
        sol : :py:class:`~numpy.ndarray`
            (N,) optimal intensity field.
        solver : str
            The used solver.
        crit : {‘ATOL’, ‘DTOL’, ‘RTOL’, ‘XTOL’, ‘MAXIT’}
            The used stopping criterion.
        niter : int
            The number of iterations.
        time : float
            The execution time in seconds.
        objective : :py:class:`~numpy.ndarray`
            The successive evaluations of the objective function at each
            iteration.
        backtrace : :py:class:`~numpy.ndarray`
            (N_iter + 1, N) successive values of the objective parameter at
            each iteration.
            backtrace[0] holds the initial solution.
        L : float
            Lipschitz constant of the gradient of the smooth function being optimized.
        lambda_ : float
            Regularization parameter
        gamma : float
            Linear trade-off between lasso and ridge regularizers.

    Notes
    -----
    [1] On the Convergence of the Iterates of the "Fast Iterative
        [Shrinkage/Thresholding Algorithm" [Chambolle, Dossal]
    """
    M, N = A.shape
    if not ((S.shape[0] == S.shape[1]) and (S.shape[0] == M)):
        raise ValueError('Parameters[S, A] are inconsistent.')
    if not np.allclose(S, S.conj().T):
        raise ValueError('Parameter[S] must be Hermitian.')

    if not (0 <= gamma <= 1):
        raise ValueError('Parameter[gamma] is must lie in [0, 1].')

    if L is None:
        L = 2 * pylinalg.eighMax(A)
    elif L <= 0:
        raise ValueError('Parameter[L] must be positive.')

    if d < 2:
        raise ValueError(r'Parameter[d] must be \ge 2.')

    if x0 is None:
        x0 = np.zeros((N, ), dtype=np.float64)
    elif np.any(x0 < 0):
        raise ValueError('Parameter[x0] must be non-negative.')

    if not (0 < eps < 1):
        raise ValueError('Parameter[eps] must lie in (0, 1).')

    if N_iter_max < 1:
        raise ValueError('Parameter[N_iter_max] must be positive.')

    if verbosity not in ('NONE', 'LOW', 'HIGH', 'ALL'):
        raise ValueError('Unknown verbosity specification.')

    if lambda_ is None:
        if gamma > 0:  # Procedure of Remark 3.4
            # When gamma == 0, we fall into the ridge-regularizer case, so no
            # need to do the following.
            func = [l2_loss(S, A), elastic_net_loss(lambda_=0, gamma=gamma)]
            solver = opt.solvers.forward_backward(
                accel=ground_truth_accel(d, L, momentum=False))
            I_opt = _solve(functions=func,
                           x0=np.zeros((N, )),
                           solver=solver,
                           rtol=eps,
                           maxit=1,
                           verbosity=verbosity)
            alpha = 1 / L
            lambda_ = np.max(I_opt['sol']) / (10 * alpha * gamma)
        else:
            lambda_ = 1  # Anything will do.
    elif lambda_ < 0:
        raise ValueError('Parameter[lambda_] must be non-negative.')

    func = [l2_loss(S, A), elastic_net_loss(lambda_, gamma)]
    solver = opt.solvers.forward_backward(
        accel=ground_truth_accel(d, L, momentum))
    I_opt = _solve(functions=func,
                   x0=x0.copy(),
                   solver=solver,
                   rtol=eps,
                   maxit=N_iter_max,
                   verbosity=verbosity)
    I_opt['gamma'] = gamma
    I_opt['lambda_'] = lambda_
    I_opt['L'] = L
    return I_opt