Exemple #1
0
def ts_max(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)
    # 把空值填充为-inf
    x = cp.where(cp.isinf(x) | cp.isnan(x), -cp.inf, x)

    prefix = cp.full(window - 1, cp.nan)
    x_rolling_array = cp_rolling_window(x, window)
    result = cp.max(x_rolling_array, axis=1)
    # 结果中如果存在-inf,说明此window均为空,返回nan
    result = result.astype(float)
    result = cp.where(cp.isinf(result), cp.nan, result)
    return cp.concatenate((prefix, result))
Exemple #2
0
def gpu_resize(dPhi, dAmp, src_x, src_y, nx, ny):
    ratio_x = nx/src_x
    ratio_y = ny/src_y
    # print(ratio_x , ratio_y)
    dPhi[cupy.isnan(dPhi)] = 0
    dPhi[cupy.isinf(dPhi)] = 0
    dAmp[cupy.isnan(dAmp)] = 1
    dAmp[cupy.isinf(dAmp)] = 1
    dAmp[cupy.equal(dAmp,0.0)] = 0.01;
    dAmp = cupy.absolute(dAmp)
    dPhi = cupyx.scipy.ndimage.zoom(dPhi, (ratio_y,ratio_x))
    dAmp = cupyx.scipy.ndimage.zoom(dAmp, (ratio_y,ratio_x))
    dField = cupy.log(dAmp) + 1j*(dPhi)
    return dField
Exemple #3
0
def ts_argmin(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)
    # 将nan及-inf填充为inf
    x = cp.where(cp.isinf(x) | cp.isnan(x), cp.inf, x)

    prefix = cp.full(window - 1, cp.nan)
    x_rolling_array = cp_rolling_window(x, window)
    result = cp.argmin(x_rolling_array, axis=1)

    # 找到window中全为-inf的情况,填充为nan
    result = result.astype(float)
    result = cp.where(cp.isinf(x_rolling_array).all(axis=1), cp.nan, result)
    result += 1
    return cp.concatenate((prefix, result))
Exemple #4
0
def check_finite(array, force_all_finite=True):
    """Checks that the input is finite if necessary

    Parameters
    ----------
    array : object
        Input object to check / convert.
    force_all_finite : boolean or 'allow-nan', (default=True)
        Whether to raise an error on np.inf, np.nan, pd.NA in array. The
        possibilities are:
        - True: Force all values of array to be finite.
        - False: accepts np.inf, np.nan, pd.NA in array.
        - 'allow-nan': accepts only np.nan and pd.NA values in array. Values
          cannot be infinite.
           ``force_all_finite`` accepts the string ``'allow-nan'``.

    Returns
    -------
    None or raise error
    """
    if force_all_finite is True:
        if not cp.all(cp.isfinite(array)):
            raise ValueError("Non-finite value encountered in array")
    elif force_all_finite == 'allow-nan':
        if cp.any(cp.isinf(array)):
            raise ValueError("Non-finite value encountered in array")
Exemple #5
0
    def _rank(x):

        x = cp.where(cp.isinf(x) | cp.isnan(x), cp.inf, x)

        # 此方式,只一次排序,对于长数组更有优势
        temp = x.argsort()
        ranks = cp.empty_like(temp)
        ranks[temp] = cp.arange(len(x))
        ranks = ranks.astype(float)

        # 将nan和inf的位置恢复为nan,不参与rank

        ranks = cp.where(cp.isinf(x), cp.nan, ranks)
        #ranks[cp.isinf(x)] = cp.nan
        # 返回x的最后一个元素的排名
        return (ranks + 1)[-1]
Exemple #6
0
def indneutralize(y, X):
    # 采用最小二乘法拟合
    # 保证二者同维度
    if X.shape[0] != y.shape[0]:
        X = X.T
    # 如果仍然不相等,那就报错
    if X.shape[0] != y.shape[0]:
        raise ValueError("X和y不同维度")

    result = cp.zeros(len(y))

    # index = cp.arange(len(y))
    bool_y = cp.isnan(y) | cp.isinf(y)
    # X中的每一行矩阵加和!=1 的地方
    bool_X = ~(cp.abs(cp.sum(X, axis=1) - 1) < 0.000001)
    bool_na = bool_y | bool_X

    # used_index = index[~bool_na]
    used_y = y[~bool_na]
    used_X = X[~bool_na]

    b = cp.linalg.inv(used_X.T.dot(used_X)).dot(used_X.T).dot(used_y)

    pred_used_y = used_X.dot(b)

    result[~bool_na] = used_y - pred_used_y
    result[bool_na] = cp.nan

    return result
Exemple #7
0
def _fhtq(a, u, inverse=False):
    '''Compute the biased fast Hankel transform.

    This is the basic FFTLog routine.
    '''

    # size of transform
    n = a.shape[-1]

    # check for singular transform or singular inverse transform
    if cupy.isinf(u[0]) and not inverse:
        warn('singular transform; consider changing the bias')
        # fix coefficient to obtain (potentially correct) transform anyway
        u = u.copy()
        u[0] = 0
    elif u[0] == 0 and inverse:
        warn('singular inverse transform; consider changing the bias')
        # fix coefficient to obtain (potentially correct) inverse anyway
        u = u.copy()
        u[0] = cupy.inf

    # biased fast Hankel transform via real FFT
    A = _fft.rfft(a, axis=-1)
    if not inverse:
        # forward transform
        A *= u
    else:
        # backward transform
        A /= u.conj()
    A = _fft.irfft(A, n, axis=-1)
    A = A[..., ::-1]

    return A
Exemple #8
0
def signedpower(x, a):
    #将inf和-inf处理为nan
    #x[cp.isinf(x)] = cp.nan
    # 经测试where替换更快一些

    x = cp.where(cp.isinf(x), cp.nan, x)
    return cp.sign(x) * cp.abs(x)**a
Exemple #9
0
def sinhm(arr):
    """Hyperbolic Sine calculation for a given nXn matrix
    Args:
        arr(cupy.ndarray) :
                            Square matrix with dimension nXn.
    Returns:
        (cupy.ndarray):
                        Hyperbolic sine of given square matrix as input.
    ..seealso:: :func: 'scipy.linalg.sinhm'
    """

    arr = cupy.array(arr)

    # Checking whether the input is a 2D matrix or not
    if (len(arr.shape) != 2):
        raise ValueError("Dimensions of matrix should be 2")

    # Checking whether the input matrix is square matrix or not
    if (arr.shape[0] != arr.shape[1]):
        raise ValueError("Input matrix should be a square matrix")

    # Checking whether the input matrix elements are nan or not
    if (cupy.isnan(cupy.cumsum(arr)[2 * arr.shape[0] - 1])):
        raise ValueError("Input matrix elements cannot be nan")

    # Checking whether the input matrix elements are infinity or not
    if (cupy.isinf(cupy.cumsum(arr)[2 * arr.shape[0] - 1])):
        raise ValueError("Input matrix elements cannot be infinity")

    return 0.5 * (cupy.exp(arr) - cupy.exp(-1 * arr))
Exemple #10
0
def rank(x):
    # https://stackoverflow.com/questions/5284646/rank-items-in-an-array-using-python-numpy-without-sorting-array-twice
    # 将x的空值,-inf,inf全都变为inf,排序时会被放在数组最末尾
    x = cp.where(cp.isinf(x) | cp.isnan(x), cp.inf, x)

    denominator = len(x) - count_inf(x)

    # 此方式,只一次排序,对于长数组更有优势
    temp = x.argsort()
    ranks = cp.empty_like(temp)
    ranks[temp] = cp.arange(len(x))
    ranks = ranks.astype(float)

    # 将nan和inf的位置恢复为nan,不参与rank
    ranks[cp.isinf(x)] = cp.nan

    return (ranks + 1) / denominator
def isinf(x: Array, /) -> Array:
    """
    Array API compatible wrapper for :py:func:`np.isinf <numpy.isinf>`.

    See its docstring for more information.
    """
    if x.dtype not in _numeric_dtypes:
        raise TypeError("Only numeric dtypes are allowed in isinf")
    return Array._new(np.isinf(x._array))
Exemple #12
0
def ts_sma(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)
    pre_fix = cp.full(window - 1, cp.nan)

    x = cp.where(cp.isinf(x), cp.nan, x)
    rolling_array = cp_rolling_window(x, window)

    result = cp.mean(rolling_array, axis=1)
    return cp.concatenate((pre_fix, result))
Exemple #13
0
def _check_nan_inf(x, dtype, neg=None):
    if dtype.char in 'FD':
        dtype = cupy.dtype(dtype.char.lower())
    if dtype.char not in 'efd':
        x = 0
    elif x is None and neg is not None:
        x = cupy.finfo(dtype).min if neg else cupy.finfo(dtype).max
    elif cupy.isnan(x):
        x = cupy.nan
    elif cupy.isinf(x):
        x = cupy.inf * (-1)**(x < 0)
    return cupy.asanyarray(x, dtype)
Exemple #14
0
def PartitionData_cp(Xcp,
                     NodePositions,
                     MaxBlockSize,
                     SquaredXcp,
                     TrimmingRadius=float("inf")):
    """
    # Partition the data by proximity to graph nodes
    # (same step as in K-means EM procedure)
    #
    # Inputs:
    #   X is n-by-m matrix of datapoints with one data point per row. n is
    #       number of data points and m is dimension of data space.
    #   NodePositions is k-by-m matrix of embedded coordinates of graph nodes,
    #       where k is number of nodes and m is dimension of data space.
    #   MaxBlockSize integer number which defines maximal number of
    #       simultaneously calculated distances. Maximal size of created matrix
    #       is MaxBlockSize-by-k, where k is number of nodes.
    #   SquaredX is n-by-1 vector of data vectors length: SquaredX = sum(X.^2,2);
    #   TrimmingRadius (optional) is squared trimming radius.
    #
    # Outputs
    #   partition is n-by-1 vector. partition[i] is number of the node which is
    #       associated with data point X[i, ].
    #   dists is n-by-1 vector. dists[i] is squared distance between the node with
    #       number partition[i] and data point X[i, ].
    """
    NodePositionscp = cupy.asarray(NodePositions)
    n = Xcp.shape[0]
    partition = cupy.zeros((n, 1), dtype=int)
    dists = cupy.zeros((n, 1))
    # Calculate squared length of centroids
    cent = NodePositionscp.T
    centrLength = (cent**2).sum(axis=0)
    # Process partitioning without trimming
    for i in range(0, n, MaxBlockSize):
        # Define last element for calculation
        last = i + MaxBlockSize
        if last > n:
            last = n
        # Calculate distances
        d = SquaredXcp[i:last] + centrLength - 2 * cupy.dot(
            Xcp[i:last, ], cent)
        tmp = d.argmin(axis=1)
        partition[i:last] = tmp[:, cupy.newaxis]
        dists[i:last] = d[cupy.arange(d.shape[0]), tmp][:, cupy.newaxis]
    # Apply trimming
    if not cupy.isinf(TrimmingRadius):
        ind = dists > (TrimmingRadius**2)
        partition[ind] = -1
        dists[ind] = TrimmingRadius**2

    return cupy.asnumpy(partition), cupy.asnumpy(dists)
 def _truncnorm_ppf(self,q, N):
     out = cp.zeros(cp.shape(q))
     delta = self._truncnorm_get_delta(N)
     cond1 = delta > 0
     cond2 = (delta > 0) & (self.a > 0)
     cond21 = (delta > 0) & (self.a<=0)
     if cp.any(cond1) == True:
         sa = self.norm_sf(a[cond2])
         out[:,cond2] = -self.ndtri((1 - q[:,cond2]) * sa)
     if cp.any(cond21) == True:
         na = norm_cdf(self.a[cond21])
         out[:,cond21] = self._ndtri(q[:,cond21]  + na * (1.0 - q[:,cond21]))
     cond3 = ~cond1 & cp.isinf(self.b)
     cond4 = ~cond1 & cp.isinf(self.a)
     if cp.any(cond3) == True:
         out[:,cond3] = -self._norm_ilogcdf(cp.log1p(-q[:,cond3]) + self.norm_logsf(self.a[cond3]))
     if cp.any(cond4) == True:
         out[:,cond4] = self._norm_ilogcdf(cp.log(q) + self.norm_logcdf(self.b))
     cond5 = out < self.a
     if cp.any(cond5) == True:
         out[cond5] = ((cond5) * self.a)[cond5]
     return out
Exemple #16
0
def scale(x, a=1):
    bool_x = cp.isnan(x) | cp.isinf(x)

    # 变为原来的 a / sum 倍

    denominator = cp.sum(cp.abs(x[~bool_x]))
    #如果和为0的处理
    if denominator < 0.000001:
        return cp.full(len(x), cp.nan)
    x[bool_x] = cp.nan

    result = (a / denominator) * x
    return result
Exemple #17
0
def decay_linear(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)
    prefix = cp.full(window - 1, cp.nan)

    x = cp.where(cp.isinf(x), cp.nan, x)

    x_rolling_array = cp_rolling_window(x, window)
    # 等差数列求和公式
    denominator = (window + 1) * window / 2
    # window各元素权重
    weight = (cp.arange(window) + 1) * 1.0 / denominator
    result = cp.zeros(x_rolling_array.shape[0])
    for i in range(x_rolling_array.shape[0]):
        result[i] = x_rolling_array[i].dot(weight)
    return cp.concatenate((prefix, result))
Exemple #18
0
def ts_sum(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)

    # 增加了一步,对含有nan值的放缩处理,比如[1, cp.nan, 3]的和本来为4, 这里乘以3/2变为6,
    # scale_nan_inf = window / ts_count_not_nan_inf(x, window)
    # 不直接修改x,通过copy的方式完成,目的是保留x原来的取值,否则参数x也会直接更改。
    # 空值,inf填充为0

    x = cp.where(cp.isinf(x), cp.nan, x)
    pre_fix = cp.full(window - 1, cp.nan)

    rolling_array = cp_rolling_window(x, window)
    result = cp.sum(rolling_array, axis=1)
    # 对求和结果进行放缩
    # result = result * scale_nan_inf
    return cp.concatenate((pre_fix, result))
Exemple #19
0
def calcPCV1(x):
    x = cp.array(cp.where(x > pcv_thre))
    if 0 in x.shape:
        return np.array([[0, 0]]).T, np.array([[0, 0], [0, 0]])
    #center = np.array([[256,256]]).T
    center = cp.mean(x, axis=1)[:, cp.newaxis]
    xCe = x - center
    Cov = cp.cov(xCe, bias=1)
    if True in cp.isnan(Cov):
        print("nan")
        pdb.set_trace()
    elif True in cp.isinf(Cov):
        print("inf")
        pdb.set_trace()
    V, D = cp.linalg.eig(Cov)
    vec = D[:, [cp.argmax(V)]]
    line = cp.concatenate([vec * -256, vec * 256], axis=1) + center
    return cp.asnumpy(center), cp.asnumpy(line)
Exemple #20
0
def ts_product(x, window):
    if window > len(x):
        return cp.full(len(x), cp.nan)
    # # 增加对溢出的处理
    # max_element = cp.max(cp.abs(x))
    # if max_element**window == cp.inf:
    #     return cp.nan

    # 对于有空值的地方,开方再取幂
    # exp_nan_inf = window / ts_count_not_nan_inf(x, window)

    # 空值,填充为1
    x = cp.where(cp.isinf(x), cp.nan, x)

    pre_fix = cp.full(window - 1, cp.nan)

    x_rolling_array = cp_rolling_window(x, window)
    result = cp.prod(x_rolling_array, axis=1)

    # 指数放缩, 有一个奇怪的现象就是1^nan = 1
    # result = cp.sign(result) * (cp.abs(result)**exp_nan_inf)
    # 当window内均为nan时,处理为nan
    # result[cp.isnan(exp_nan_inf)] = cp.nan
    return cp.concatenate((pre_fix, result))
Exemple #21
0
    def _zdivide(x, y):
        """Patched version of :func:`sporco.linalg.zdivide`."""

        div = x / y
        div[cp.logical_or(cp.isnan(div), cp.isinf(div))] = 0
        return div
Exemple #22
0
def count_nan_inf(x):
    bool_arr = cp.isinf(x) | cp.isnan(x)
    return cp.count_nonzero(bool_arr)
Exemple #23
0
def fix_inf_nan(data):
    """Fix inf and nan values in projections"""
    data[cp.isnan(data)] = 0
    data[cp.isinf(data)] = 0
    return data
Exemple #24
0
    def _zdivide(x, y):
        """Patched version of :func:`sporco.linalg.zdivide`."""

        div = x / y
        div[cp.logical_or(cp.isnan(div), cp.isinf(div))] = 0
        return div
Exemple #25
0
def peak_local_max(
    image,
    min_distance=1,
    threshold_abs=None,
    threshold_rel=None,
    exclude_border=True,
    indices=True,
    num_peaks=cp.inf,
    footprint=None,
    labels=None,
    num_peaks_per_label=cp.inf,
):
    """Find peaks in an image as coordinate list or boolean mask.

    Peaks are the local maxima in a region of `2 * min_distance + 1`
    (i.e. peaks are separated by at least `min_distance`).

    If there are multiple local maxima with identical pixel intensities
    inside the region defined with `min_distance`,
    the coordinates of all such pixels are returned.

    If both `threshold_abs` and `threshold_rel` are provided, the maximum
    of the two is chosen as the minimum intensity threshold of peaks.

    Parameters
    ----------
    image : ndarray
        Input image.
    min_distance : int, optional
        Minimum number of pixels separating peaks in a region of `2 *
        min_distance + 1` (i.e. peaks are separated by at least
        `min_distance`).
        To find the maximum number of peaks, use `min_distance=1`.
    threshold_abs : float, optional
        Minimum intensity of peaks. By default, the absolute threshold is
        the minimum intensity of the image.
    threshold_rel : float, optional
        Minimum intensity of peaks, calculated as `max(image) * threshold_rel`.
    exclude_border : int, tuple of ints, or bool, optional
        If positive integer, `exclude_border` excludes peaks from within
        `exclude_border`-pixels of the border of the image.
        If tuple of non-negative ints, the length of the tuple must match the
        input array's dimensionality.  Each element of the tuple will exclude
        peaks from within `exclude_border`-pixels of the border of the image
        along that dimension.
        If True, takes the `min_distance` parameter as value.
        If zero or False, peaks are identified regardless of their distance
        from the border.
    indices : bool, optional
        If True, the output will be an array representing peak
        coordinates. The coordinates are sorted according to peaks
        values (Larger first). If False, the output will be a boolean
        array shaped as `image.shape` with peaks present at True
        elements.
    num_peaks : int, optional
        Maximum number of peaks. When the number of peaks exceeds `num_peaks`,
        return `num_peaks` peaks based on highest peak intensity.
    footprint : ndarray of bools, optional
        If provided, `footprint == 1` represents the local region within which
        to search for peaks at every point in `image`.  Overrides
        `min_distance`.
    labels : ndarray of ints, optional
        If provided, each unique region `labels == value` represents a unique
        region to search for peaks. Zero is reserved for background.
    num_peaks_per_label : int, optional
        Maximum number of peaks for each label.

    Returns
    -------
    output : ndarray or ndarray of bools

        * If `indices = True`  : (row, column, ...) coordinates of peaks.
        * If `indices = False` : Boolean array shaped like `image`, with peaks
          represented by True values.

    Notes
    -----
    The peak local maximum function returns the coordinates of local peaks
    (maxima) in an image. A maximum filter is used for finding local maxima.
    This operation dilates the original image. After comparison of the dilated
    and original image, this function returns the coordinates or a mask of the
    peaks where the dilated image equals the original image.

    See also
    --------
    skimage.feature.corner_peaks

    Examples
    --------
    >>> import cupy as cp
    >>> img1 = cp.zeros((7, 7))
    >>> img1[3, 4] = 1
    >>> img1[3, 2] = 1.5
    >>> img1
    array([[0. , 0. , 0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 1.5, 0. , 1. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. , 0. , 0. ]])

    >>> peak_local_max(img1, min_distance=1)
    array([[3, 2],
           [3, 4]])

    >>> peak_local_max(img1, min_distance=2)
    array([[3, 2]])

    >>> img2 = cp.zeros((20, 20, 20))
    >>> img2[10, 10, 10] = 1
    >>> peak_local_max(img2, exclude_border=0)
    array([[10, 10, 10]])

    """
    out = cp.zeros_like(image, dtype=cp.bool)

    threshold_abs = threshold_abs if threshold_abs is not None else image.min()

    if isinstance(exclude_border, bool):
        exclude_border = (min_distance if exclude_border else 0, ) * image.ndim
    elif isinstance(exclude_border, int):
        if exclude_border < 0:
            raise ValueError("`exclude_border` cannot be a negative value")
        exclude_border = (exclude_border, ) * image.ndim
    elif isinstance(exclude_border, tuple):
        if len(exclude_border) != image.ndim:
            raise ValueError(
                "`exclude_border` should have the same length as the "
                "dimensionality of the image.")
        for exclude in exclude_border:
            if not isinstance(exclude, int):
                raise ValueError(
                    "`exclude_border`, when expressed as a tuple, must only "
                    "contain ints.")
            if exclude < 0:
                raise ValueError(
                    "`exclude_border` cannot contain a negative value")
    else:
        raise TypeError(
            "`exclude_border` must be bool, int, or tuple with the same "
            "length as the dimensionality of the image.")

    # no peak for a trivial image
    # if cp.all(image == image.flat[0]):
    if cp.all(image == image.ravel()[0]):
        if indices is True:
            return cp.empty((0, image.ndim), cp.int)
        else:
            return out

    # In the case of labels, call ndi on each label
    if labels is not None:
        label_values = cp.unique(labels)
        # Reorder label values to have consecutive integers (no gaps)
        if cp.any(cp.diff(label_values) != 1):
            mask = labels >= 1
            labels[mask] = 1 + rank_order(labels[mask])[0].astype(labels.dtype)
        labels = labels.astype(cp.int32)

        # create a mask for the non-exclude region
        inner_mask = _exclude_border(cp.ones_like(labels, dtype=bool),
                                     exclude_border)

        # For each label, extract a smaller image enclosing the object of
        # interest, identify num_peaks_per_label peaks and mark them in
        # variable out.
        warnings.warn(
            "host/device transfers necessary: ndimage.find_objects unimplemented on the GPU"
        )
        objects = cpu_find_objects(cp.asnumpy(labels))
        for label_idx, obj in enumerate(objects):
            img_object = image[obj] * (labels[obj] == label_idx + 1)
            mask = _get_peak_mask(
                img_object,
                min_distance,
                footprint,
                threshold_abs,
                threshold_rel,
            )
            if exclude_border:
                # remove peaks fall in the exclude region
                mask &= inner_mask[obj]
            coordinates = _get_high_intensity_peaks(img_object, mask,
                                                    num_peaks_per_label)
            nd_indices = tuple(coordinates.T)
            mask.fill(False)
            mask[nd_indices] = True
            out[obj] += mask

        if not indices and cp.isinf(num_peaks):
            return out

        coordinates = _get_high_intensity_peaks(image, out, num_peaks)
        if indices:
            return coordinates
        else:
            out.fill(False)
            nd_indices = tuple(coordinates.T)
            out[nd_indices] = True
            return out

    # Non maximum filter
    mask = _get_peak_mask(image, min_distance, footprint, threshold_abs,
                          threshold_rel)

    mask = _exclude_border(mask, exclude_border)

    # Select highest intensities (num_peaks)
    coordinates = _get_high_intensity_peaks(image, mask, num_peaks)

    if indices is True:
        return coordinates
    else:
        nd_indices = tuple(coordinates.T)
        out[nd_indices] = True
        return out
Exemple #26
0
def sinkhorn_knopp(a,
                   b,
                   M,
                   reg,
                   numItermax=1000,
                   stopThr=1e-9,
                   verbose=False,
                   log=False,
                   to_numpy=True,
                   **kwargs):
    r"""
    Solve the entropic regularization optimal transport on GPU

    If the input matrix are in numpy format, they will be uploaded to the
    GPU first which can incur significant time overhead.

    The function solves the following optimization problem:

    .. math::
        \gamma = arg\min_\gamma <\gamma,M>_F + reg\cdot\Omega(\gamma)

        s.t. \gamma 1 = a

             \gamma^T 1= b

             \gamma\geq 0
    where :

    - M is the (ns,nt) metric cost matrix
    - :math:`\Omega` is the entropic regularization term :math:`\Omega(\gamma)=\sum_{i,j} \gamma_{i,j}\log(\gamma_{i,j})`
    - a and b are source and target weights (sum to 1)

    The algorithm used for solving the problem is the Sinkhorn-Knopp matrix scaling algorithm as proposed in [2]_


    Parameters
    ----------
    a : np.ndarray (ns,)
        samples weights in the source domain
    b : np.ndarray (nt,) or np.ndarray (nt,nbb)
        samples in the target domain, compute sinkhorn with multiple targets
        and fixed M if b is a matrix (return OT loss + dual variables in log)
    M : np.ndarray (ns,nt)
        loss matrix
    reg : float
        Regularization term >0
    numItermax : int, optional
        Max number of iterations
    stopThr : float, optional
        Stop threshol on error (>0)
    verbose : bool, optional
        Print information along iterations
    log : bool, optional
        record log if True
    to_numpy : boolean, optional (default True)
        If true convert back the GPU array result to numpy format.


    Returns
    -------
    gamma : (ns x nt) ndarray
        Optimal transportation matrix for the given parameters
    log : dict
        log dictionary return only if log==True in parameters


    References
    ----------

    .. [2] M. Cuturi, Sinkhorn Distances : Lightspeed Computation of Optimal Transport, Advances in Neural Information Processing Systems (NIPS) 26, 2013


    See Also
    --------
    ot.lp.emd : Unregularized OT
    ot.optim.cg : General regularized OT

    """

    a = cp.asarray(a)
    b = cp.asarray(b)
    M = cp.asarray(M)

    if len(a) == 0:
        a = np.ones((M.shape[0], )) / M.shape[0]
    if len(b) == 0:
        b = np.ones((M.shape[1], )) / M.shape[1]

    # init data
    Nini = len(a)
    Nfin = len(b)

    if len(b.shape) > 1:
        nbb = b.shape[1]
    else:
        nbb = 0

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

    # we assume that no distances are null except those of the diagonal of
    # distances
    if nbb:
        u = np.ones((Nini, nbb)) / Nini
        v = np.ones((Nfin, nbb)) / Nfin
    else:
        u = np.ones(Nini) / Nini
        v = np.ones(Nfin) / Nfin

    # print(reg)

    # Next 3 lines equivalent to K= np.exp(-M/reg), but faster to compute
    K = np.empty(M.shape, dtype=M.dtype)
    np.divide(M, -reg, out=K)
    np.exp(K, out=K)

    # print(np.min(K))
    tmp2 = np.empty(b.shape, dtype=M.dtype)

    Kp = (1 / a).reshape(-1, 1) * K
    cpt = 0
    err = 1
    while (err > stopThr and cpt < numItermax):
        uprev = u
        vprev = v

        KtransposeU = np.dot(K.T, u)
        v = np.divide(b, KtransposeU)
        u = 1. / np.dot(Kp, v)

        if (np.any(KtransposeU == 0) or np.any(np.isnan(u))
                or np.any(np.isnan(v)) or np.any(np.isinf(u))
                or np.any(np.isinf(v))):
            # we have reached the machine precision
            # come back to previous solution and quit loop
            print('Warning: numerical errors at iteration', cpt)
            u = uprev
            v = vprev
            break
        if cpt % 10 == 0:
            # we can speed up the process by checking for the error only all
            # the 10th iterations
            if nbb:
                err = np.sum((u - uprev)**2) / np.sum((u)**2) + \
                    np.sum((v - vprev)**2) / np.sum((v)**2)
            else:
                # compute right marginal tmp2= (diag(u)Kdiag(v))^T1
                tmp2 = np.sum(u[:, None] * K * v[None, :], 0)
                #tmp2=np.einsum('i,ij,j->j', u, K, v)
                err = np.linalg.norm(tmp2 - b)**2  # violation of marginal
            if log:
                log['err'].append(err)

            if verbose:
                if cpt % 200 == 0:
                    print('{:5s}|{:12s}'.format('It.', 'Err') + '\n' +
                          '-' * 19)
                print('{:5d}|{:8e}|'.format(cpt, err))
        cpt = cpt + 1
    if log:
        log['u'] = u
        log['v'] = v

    if nbb:  # return only loss
        #res = np.einsum('ik,ij,jk,ij->k', u, K, v, M) (explodes cupy memory)
        res = np.empty(nbb)
        for i in range(nbb):
            res[i] = np.sum(u[:, None, i] * (K * M) * v[None, :, i])
        if to_numpy:
            res = utils.to_np(res)
        if log:
            return res, log
        else:
            return res

    else:  # return OT matrix
        res = u.reshape((-1, 1)) * K * v.reshape((1, -1))
        if to_numpy:
            res = utils.to_np(res)
        if log:
            return res, log
        else:
            return res
Exemple #27
0
def corner_peaks(
    image,
    min_distance=1,
    threshold_abs=None,
    threshold_rel=None,
    exclude_border=True,
    indices=True,
    num_peaks=np.inf,
    footprint=None,
    labels=None,
    *,
    num_peaks_per_label=np.inf,
    p_norm=np.inf,
):
    """Find peaks in corner measure response image.

    This differs from `skimage.feature.peak_local_max` in that it suppresses
    multiple connected peaks with the same accumulator value.

    Parameters
    ----------
    image : ndarray
        Input image.
    min_distance : int, optional
        The minimal allowed distance separating peaks.
    * : *
        See :py:meth:`skimage.feature.peak_local_max`.
    p_norm : float
        Which Minkowski p-norm to use. Should be in the range [1, inf].
        A finite large p may cause a ValueError if overflow can occur.
        ``inf`` corresponds to the Chebyshev distance and 2 to the
        Euclidean distance.

    Returns
    -------
    output : ndarray or ndarray of bools

        * If `indices = True`  : (row, column, ...) coordinates of peaks.
        * If `indices = False` : Boolean array shaped like `image`, with peaks
          represented by True values.

    See also
    --------
    skimage.feature.peak_local_max

    Notes
    -----
    .. versionchanged:: 0.18
        The default value of `threshold_rel` has changed to None, which
        corresponds to letting `skimage.feature.peak_local_max` decide on the
        default. This is equivalent to `threshold_rel=0`.

    The `num_peaks` limit is applied before suppression of connected peaks.
    To limit the number of peaks after suppression, set `num_peaks=np.inf` and
    post-process the output of this function.

    Examples
    --------
    >>> from cucim.skimage.feature import peak_local_max
    >>> response = cp.zeros((5, 5))
    >>> response[2:4, 2:4] = 1
    >>> response
    array([[0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0.],
           [0., 0., 1., 1., 0.],
           [0., 0., 1., 1., 0.],
           [0., 0., 0., 0., 0.]])
    >>> peak_local_max(response)
    array([[2, 2],
           [2, 3],
           [3, 2],
           [3, 3]])
    >>> corner_peaks(response)
    array([[2, 2]])

    """
    if cp.isinf(num_peaks):
        num_peaks = None

    # Get the coordinates of the detected peaks
    coords = peak_local_max(
        image,
        min_distance=min_distance,
        threshold_abs=threshold_abs,
        threshold_rel=threshold_rel,
        exclude_border=exclude_border,
        num_peaks=np.inf,
        footprint=footprint,
        labels=labels,
        num_peaks_per_label=num_peaks_per_label,
    )

    if len(coords):
        # TODO: modify to do KDTree on the GPU (cuSpatial?)
        coords = cp.asnumpy(coords)

        # Use KDtree to find the peaks that are too close to each other
        tree = spatial.cKDTree(coords)

        rejected_peaks_indices = set()
        for idx, point in enumerate(coords):
            if idx not in rejected_peaks_indices:
                candidates = tree.query_ball_point(point,
                                                   r=min_distance,
                                                   p=p_norm)
                candidates.remove(idx)
                rejected_peaks_indices.update(candidates)

        # Remove the peaks that are too close to each other
        coords = np.delete(coords, tuple(rejected_peaks_indices),
                           axis=0)[:num_peaks]
        coords = cp.asarray(coords)

    if indices:
        return coords

    peaks = cp.zeros_like(image, dtype=bool)
    peaks[tuple(coords.T)] = True

    return peaks
def barycenter_unbalanced_sinkhorn2D_gpu(A,
                                         Cx,
                                         Cy,
                                         reg,
                                         reg_m,
                                         weights=None,
                                         numItermax=1000,
                                         stopThr=1e-6,
                                         verbose=False,
                                         log=False,
                                         logspace=False,
                                         reg_K=1e-16):
    """
    ----------
    A : np.ndarray (dimx,dimy, n_hists)
        `n_hists` training distributions a_i of dimension dimxdim
    Cx : np.ndarray (dimx, dimx)
        x part of separable cost matrix for OT.
    Cy : np.ndarray (dimy, dimy)
        y part of separable cost matrix for OT.
    reg : float
        Entropy regularization term > 0
    reg_m: float
        Marginal relaxation term > 0
    weights : np.ndarray (n_hists,) optional
        Weight of each distribution (barycentric coodinates)
        If None, uniform weights are used.
    numItermax : int, optional
        Max number of iterations
    stopThr : float, optional
        Stop threshol on error (> 0)
    verbose : bool, optional
        Print information along iterations
    log : bool, optional
        record log if True
    logspace : bool, optional
        compuation done in logspace if True
    Returns
    -------
    q : (dim,) ndarray
        Unbalanced Wasserstein barycenter
    log : dict
        log dictionary return only if log==True in parameters
    References
    ----------
    .. [3] Benamou, J. D., Carlier, G., Cuturi, M., Nenna, L., & Peyré, G.
        (2015). Iterative Bregman projections for regularized transportation
        problems. SIAM Journal on Scientific Computing, 37(2), A1111-A1138.
    .. [10] Chizat, L., Peyré, G., Schmitzer, B., & Vialard, F. X. (2016).
        Scaling algorithms for unbalanced transport problems. arXiv preprin
        arXiv:1607.05816.
    """

    dimx, dimy, n_hists = A.shape
    if weights is None:
        weights = cp.ones(n_hists) / n_hists
    else:
        assert (len(weights) == A.shape[2])
    weights = cp.asarray(weights / weights.sum())
    if log:
        log = {'err': []}

    fi = reg_m / (reg_m + reg)
    if logspace:
        v = cp.zeros((dimx, dimy, 1)) * cp.log(1 / dimx / dimy)
        u = cp.zeros((dimx, dimy)) * cp.log(1 / dimx / dimy)
        q = cp.zeros((dimx, dimy)) * cp.log(1 / dimx / dimy)
        err = 1.
        for i in range(numItermax):
            uprev = u.copy()
            vprev = v.copy()
            qprev = q.copy()

            lKv = prod_separable_logspace(Cx, Cy, reg, v)
            u = fi * (cp.log(A) - cp.maximum(lKv, cp.log(reg_K)))
            lKtu = prod_separable_logspace(Cx.T, Cy.T, reg, u)
            mlktu = (1 - fi) * cp.max(lKtu, axis=2)
            q = (1 / (1 - fi)) * ((cp.log(
                cp.average(cp.exp((1 - fi) * lKtu - mlktu[:, :, None]),
                           axis=2,
                           weights=weights))) + mlktu)
            Q = q[:, :, None]
            v = fi * (Q - cp.maximum(lKtu, cp.log(reg_K)))

            if (cp.any(lKtu == -cp.inf) or cp.any(cp.isnan(u))
                    or cp.any(cp.isnan(v))):
                # we have reached the machine precision
                # come back to previous solution and quit loop
                print('Numerical errors at iteration %s' % i)
                u = uprev
                v = vprev
                # q = qprev
                break
                # compute change in barycenter
            if (i % 10 == 0) or i == 0:
                err = abs(cp.exp(qprev) * (1 - cp.exp(q - qprev))).max()
                err /= max(abs(cp.exp(q)).max(), abs(cp.exp(qprev)).max(), 1.)
                if log:
                    log['err'].append(err)
                # if barycenter did not change + at least 10 iterations - stop
                if err < stopThr and i > 10:
                    break

                if verbose:
                    if i % 100 == 0:
                        print('{:5s}|{:12s}'.format('It.', 'Err') + '\n' +
                              '-' * 19)
                    print('{:5d}|{:8e}|'.format(i, err.get()))

        if log:
            log['niter'] = i
            log['logu'] = ((u + 1e-300))
            log['logv'] = ((v + 1e-300))
            return cp.exp(q), log
        else:
            return cp.exp(q)
    else:
        v = cp.ones((dimx, dimy, 1)) / dimx / dimy
        u = cp.ones((dimx, dimy)) / dimx / dimy
        q = cp.ones((dimx, dimy)) / dimx / dimy
        err = 1.
        Kx = cp.exp(-Cx / reg)
        Ky = cp.exp(-Cy / reg)
        for i in range(numItermax):
            uprev = u.copy()
            vprev = v.copy()
            qprev = q.copy()

            Kv = cp.tensordot(cp.tensordot(Kx, v, axes=([1], [0])),
                              Ky,
                              axes=([1], [0])).swapaxes(1, 2)
            u = cp.power(cp.divide(A, (Kv + reg_K)), fi)
            Ktu = cp.tensordot(cp.tensordot(cp.transpose(Kx),
                                            u,
                                            axes=([1], [0])),
                               cp.transpose(Ky),
                               axes=([1], [0])).swapaxes(1, 2)
            q = cp.power(cp.dot(cp.power(Ktu, (1 - fi)), weights),
                         (1 / (1 - fi)))
            v = cp.power(cp.divide(q[:, :, None], (Ktu + reg_K)), fi)

            if (cp.any(Ktu == 0) or cp.any(cp.isnan(u)) or cp.any(cp.isnan(v))
                    or cp.any(cp.isinf(u)) or cp.any(cp.isinf(v))):
                # we have reached the machine precision
                # come back to previous solution and quit loop
                print('Numerical errors at iteration %s' % i)
                u = uprev
                v = vprev
                q = qprev
                break
                # compute change in barycenter
            if (i % 10 == 0) or i == 0:
                err = cp.abs(q - qprev).max()
                err /= max(cp.abs(q).max(), cp.abs(qprev).max(), 1.)
                if log:
                    log['err'].append(err)
                # if barycenter did not change + at least 10 iterations - stop
                if err < stopThr and i > 10:
                    break

                if verbose:
                    if i % 100 == 0:
                        print('{:5s}|{:12s}'.format('It.', 'Err') + '\n' +
                              '-' * 19)
                    print('{:5d}|{:8e}|'.format(i, err.get()))
        if log:
            log['niter'] = i
            log['logu'] = (cp.log(u + 1e-300))
            log['logv'] = (cp.log(v + 1e-300))
            return q, log
        else:
            return q