Пример #1
0
def mean_dimension(t, mask=None, marginals=None):
    """
    Computes the mean dimension of a given tensor with given marginal distributions. This quantity measures how well the
    represented function can be expressed as a sum of low-parametric functions. For example, mean dimension 1 (the
    lowest possible value) means that it is a purely additive function: :math:`f(x_1, ..., x_N) = f_1(x_1) + ... + f_N(x_N)`.

    Assumption: the input variables :math:`x_n` are independently distributed.

    References:

    - R. E. Caflisch, W. J. Morokoff, and A. B. Owen: `"Valuation of Mortgage Backed Securities Using Brownian Bridges to Reduce Effective Dimension" (1997) <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.3160>`_

    -  R. Ballester-Ripoll, E. G. Paredes, and R. Pajarola: `"Tensor Algorithms for Advanced Sensitivity Metrics" (2017) <https://epubs.siam.org/doi/10.1137/17M1160252>`_

    :param t: an N-dimensional :class:`Tensor`
    :param marginals: a list of N vectors (will be normalized if not summing to 1). If None (default), uniform distributions are assumed for all variables

    :return: a scalar >= 1
    """

    if mask is None:
        return tn.sobol(t, tn.weight(t.dim()), marginals=marginals)
    else:
        return tn.sobol(
            t, tn.mask(tn.weight(t.dim()), mask),
            marginals=marginals) / tn.sobol(t, mask, marginals=marginals)
Пример #2
0
def dimension_distribution(t, mask=None, order=None, marginals=None):
    """
    Computes the dimension distribution of an ND tensor.

    :param t: ND input :class:`Tensor`
    :param mask: an optional mask :class:`Tensor` to restrict to
    :param order: int, compute only this many order contributions. By default, all N are returned
    :param marginals: PMFs for input variables. By default, uniform distributions

    :return: a PyTorch vector containing N elements
    """

    if order is None:
        order = t.dim()
    if mask is None:
        return tn.sobol(t, tn.weight_one_hot(t.dim(), order+1), marginals=marginals).torch()[1:]
    else:
        mask2 = tn.mask(tn.weight_one_hot(t.dim(), order+1), mask)
        return tn.sobol(t, mask2, marginals=marginals).torch()[1:] / tn.sobol(t, mask, marginals=marginals)
Пример #3
0
def data_reading(N, nfix, t, listvariable=None):
    start4 = time.time()
    dc = dircov.DirectionalCovariance(t)
    ind = al.AllIndices(t)

    n = nfix if nfix < N else N
    if listvariable is None:
        listvariable = list(range(1, N + 1))

    inputorder = len(listvariable)
    # ========= compute all the sobol indices in one loop =============
    sobolAll = []
    relativeAll = []
    sobolsetInOrder = {}
    relativeInOrder = {}

    for i in range(n):
        setOrder = i + 1
        sobolsetInOrder[setOrder] = {}
        relativeInOrder[setOrder] = {}
        setnow = list(itertools.combinations(listvariable, setOrder))
        len_setnow = len(setnow)  # like C(2,5) = 10

        sobolset = {
            'dc': [],
            'sobol': [],
            'closed': [],
            'total': [],
            'super': []
        }

        for j in range(len_setnow):
            # split setnow and get every single element in setnow, then apply the logic
            # variables_index = setnow[j] like (1,2,3)
            vindex = setnow[j]
            vv = list(map(lambda x: x - 1, list(vindex)))
            dc_p = dc.index(vv)
            # union_set = tn.any(N, which=list(map(lambda x: x - 1, list(vindex))))  # map function(function, input)
            # inter_set = tn.all(N, which=list(map(lambda x: x - 1, list(vindex))))

            # sobol_p = tn.sobol(t, mask=tn.only(inter_set)).tolist()
            # sobol_c = tn.sobol(t, mask=tn.only(union_set)).tolist()
            # sobol_t = tn.sobol(t, union_set).tolist()
            # sobol_s = tn.sobol(t, inter_set).tolist()

            sobol_p = ind.variance_component(vv)
            sobol_c = ind.closed_index(vv)
            sobol_t = ind.total_index(vv)
            sobol_s = ind.superset_index(vv)

            sobol_p = round(sobol_p, digit)
            sobol_c = round(sobol_c, digit)
            sobol_t = round(sobol_t, digit)
            sobol_s = round(sobol_s, digit)

            # sobols[i] = [sobol_p, sobol_c, sobol_t, sobol_s]
            sobolset['dc'].append(dc_p)
            sobolset['sobol'].append(sobol_p)
            sobolset['closed'].append(sobol_c)
            sobolset['total'].append(sobol_t)
            sobolset['super'].append(sobol_s)

            # tn.sobol(t, x & (y | z)) / tn.sobol(t, y | z); or tn.sobol(t, (x | y) & z) / tn.sobol(t, z)
            # get relative importance values
        setfull = list(itertools.combinations(listvariable, setOrder))
        len_setfull = len(setfull)  # C(2,7) = 21
        relativeOrders = []
        for j in range(len_setfull):
            # vindex: [1,6]
            vindex = setfull[j]
            # [2,3,4,5], delete removes the elements with certain index
            temp = listvariable
            for m in range(len(vindex)):
                vrest = np.delete(temp, list(temp).index(vindex[m]))  # [3,4]
                temp = vrest
            inter_set = tn.any(N,
                               which=list(map(lambda x: x - 1, list(vindex))))
            relative_index = []
            for k in range(len(vrest)):  # 0,1,2,3
                # nmset = vindex  # [1,6]
                rela = []
                dnmset = list(itertools.combinations(vrest, k + 1))
                for m in range(len(dnmset)):
                    dnm_union = tn.any(N,
                                       which=list(
                                           map(lambda x: x - 1,
                                               list(dnmset[m]))))

                    nm_sobol = tn.sobol(t, (inter_set & dnm_union))
                    dnm_sobol = tn.sobol(t, dnm_union)

                    rela_temp = (nm_sobol / dnm_sobol).tolist()
                    rela_temp = round(rela_temp, digit)

                    rela.append(rela_temp)
                relative_index.append(rela)
            relativeOrders.append(relative_index)

        sobolsetInOrder[setOrder].update(sobolset)
        relativeInOrder[setOrder] = relativeOrders
    sobolAll.append(sobolsetInOrder)
    relativeAll.append(relativeInOrder)

    sobolJson = {
        'order': N,
        'od': n,
        'chosenorder': inputorder,
        'nodes': sobolAll,
        'relatives': relativeAll
    }
    print('computing this index took only {:g}s'.format(time.time() - start4))

    # with open('./data/data3.json', 'w', encoding='utf-8') as f:
    #     json.dump(sobolJson, f, ensure_ascii=False, indent=2)

    return json.dumps(sobolJson)
Пример #4
0
    #     return self._get_index(variables, self.dircov)


if __name__ == '__main__':  # For example and testing purposes
    torch.manual_seed(0)
    I = 32
    N = 4
    R = 5
    t = tn.rand([I] * N, ranks_tt=R)
    ind = AllIndices(t)

    s = tn.symbols(N)

    print('Variance component example:')
    print(ind.variance_component([0, 1]))
    print(tn.sobol(t, mask=tn.only(s[0] & s[1])).item())
    print()

    print('Superset index example:')
    print(ind.superset_index([0, 1]))
    print(tn.sobol(t, mask=s[0] & s[1]).item())
    print()

    print('Closed index example:')
    print(ind.closed_index([0, 1]))
    print(tn.sobol(t, mask=tn.only(s[0] | s[1])).item())
    print()

    print('Variance component example:')
    print(ind.total_index([0, 1]))
    print(tn.sobol(t, mask=s[0] | s[1]).item())