(model, target_weights, initial_guess, n_iter=100, mask=None, lr=1e-1, verbose=True, device=None,
                       dtype=None)
return x, hist
Find input tensor such that the model produces an allocation close to the target one.

    Parameters
    ----------
    model : torch.Module
        Network that predicts weight allocation given feature tensor.

    target_weights : torch.Tensor
        Vector of targeted asset weights of shape `(n_assets,)`.

    initial_guess : torch.Tensor
        Initial feature tensor serving as the starting point for the optimization. The shape is
        `(n_channels, lookback, n_assets)` - the sample dimension is not included.

    n_iter : int
        Number of iterations of the gradients descent (or other) algorithm.

    mask : None or torch.Tensor
        If specified, then boolean ``torch.Tensor`` of the same shape as `initial_guess` than
        one can elementwise choose what parts of the inputs to optimize (True) and which
        keep the same as the initial guess (False).

    lr : float
        Learning rate for the optimizer.

    verbose : bool
        If True, then verbosity activated.

    dtype : None or torch.dtype
        Dtype to be used. If specified, casts all used tensors.

    device : None or torch.device
        Device to be used. If specified, casts all used tensors.

    Returns
    -------
    result : torch.Tensor
        Feature tensor of the same shape as `initial_guess` that is mapped by the network (hopefully)
        close to `target_weights`.

    hist : list
        List of losses per iteration.
Find input tensor such that the model produces an allocation close to the target one.
Find input tensor such that the model produces an allocation close to the target one .
def gradient_wrt_input(model, target_weights, initial_guess, n_iter=100, mask=None, lr=1e-1, verbose=True, device=None,
                       dtype=None):
    """Find input tensor such that the model produces an allocation close to the target one.

    Parameters
    ----------
    model : torch.Module
        Network that predicts weight allocation given feature tensor.

    target_weights : torch.Tensor
        Vector of targeted asset weights of shape `(n_assets,)`.

    initial_guess : torch.Tensor
        Initial feature tensor serving as the starting point for the optimization. The shape is
        `(n_channels, lookback, n_assets)` - the sample dimension is not included.

    n_iter : int
        Number of iterations of the gradients descent (or other) algorithm.

    mask : None or torch.Tensor
        If specified, then boolean ``torch.Tensor`` of the same shape as `initial_guess` than
        one can elementwise choose what parts of the inputs to optimize (True) and which
        keep the same as the initial guess (False).

    lr : float
        Learning rate for the optimizer.

    verbose : bool
        If True, then verbosity activated.

    dtype : None or torch.dtype
        Dtype to be used. If specified, casts all used tensors.

    device : None or torch.device
        Device to be used. If specified, casts all used tensors.

    Returns
    -------
    result : torch.Tensor
        Feature tensor of the same shape as `initial_guess` that is mapped by the network (hopefully)
        close to `target_weights`.

    hist : list
        List of losses per iteration.
    """
    device = device or torch.device('cpu')
    dtype = dtype or torch.float32

    x = initial_guess.clone().to(device=device, dtype=dtype)
    x.requires_grad = True

    if mask is None:
        mask = torch.ones_like(x)

    elif torch.is_tensor(mask):
        if mask.shape != x.shape:
            raise ValueError('Inconsistent shape of the mask.')
    else:
        raise TypeError('Incorrect type of the mask, either None or torch.Tensor.')

    # casting
    mask = mask.to(dtype=torch.bool, device=device)
    model.to(device=device, dtype=dtype)
    target_weights = target_weights.to(device=device, dtype=dtype)

    optimizer = torch.optim.Adam([x], lr=lr)
    model.train()

    hist = []
    for i in range(n_iter):
        if i % 50 == 0 and verbose:
            msg = '{}-th iteration, loss: {:.4f}'.format(i, hist[-1]) if i != 0 else 'Starting optimization'
            print(msg)

        loss_per_asset = (model((x * mask)[None, ...])[0] - target_weights) ** 2
        loss = loss_per_asset.mean()
        hist.append(loss.item())

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    if verbose:
        print('Optimization done, final loss: {:.4f}'.format(hist[-1]))

    return x, hist
def gradient_wrt_input ( model , target_weights , initial_guess , n_iter = 100 , mask = None , lr = 1e-1 , verbose = True , device = None , dtype = None ) : device = device or torch . device ( 'cpu' ) dtype = dtype or torch . float32 x = initial_guess . clone ( ) . to ( device = device , dtype = dtype ) x . requires_grad = True if mask is None : mask = torch . ones_like ( x ) elif torch . is_tensor ( mask ) : if mask . shape != x . shape : raise ValueError ( 'Inconsistent shape of the mask.' ) else : raise TypeError ( 'Incorrect type of the mask, either None or torch.Tensor.' ) # casting mask = mask . to ( dtype = torch . bool , device = device ) model . to ( device = device , dtype = dtype ) target_weights = target_weights . to ( device = device , dtype = dtype ) optimizer = torch . optim . Adam ( [ x ] , lr = lr ) model . train ( ) hist = [ ] for i in range ( n_iter ) : if i % 50 == 0 and verbose : msg = '{}-th iteration, loss: {:.4f}' . format ( i , hist [ - 1 ] ) if i != 0 else 'Starting optimization' print ( msg ) loss_per_asset = ( model ( ( x * mask ) [ None , ... ] ) [ 0 ] - target_weights ) ** 2 loss = loss_per_asset . mean ( ) hist . append ( loss . item ( ) ) optimizer . zero_grad ( ) loss . backward ( ) optimizer . step ( ) if verbose : print ( 'Optimization done, final loss: {:.4f}' . format ( hist [ - 1 ] ) ) return x , hist