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))
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
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))
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")
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]
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
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
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
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))
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))
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))
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)
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
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
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))
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))
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)
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))
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
def count_nan_inf(x): bool_arr = cp.isinf(x) | cp.isnan(x) return cp.count_nonzero(bool_arr)
def fix_inf_nan(data): """Fix inf and nan values in projections""" data[cp.isnan(data)] = 0 data[cp.isinf(data)] = 0 return data
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
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
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