def _get_outer_edges(a, range): """ Determine the outer bin edges to use, from either the data or the range argument """ if range is not None: first_edge, last_edge = range if first_edge > last_edge: raise ValueError("max must be larger than min in range parameter.") if not (numpy.isfinite(first_edge) and numpy.isfinite(last_edge)): raise ValueError("supplied range of [{}, {}] is not finite".format( first_edge, last_edge)) elif a.size == 0: first_edge = 0.0 last_edge = 1.0 else: first_edge = float(a.min()) last_edge = float(a.max()) if not (cupy.isfinite(first_edge) and cupy.isfinite(last_edge)): raise ValueError( "autodetected range of [{}, {}] is not finite".format( first_edge, last_edge)) # expand empty range to avoid divide by zero if first_edge == last_edge: first_edge = first_edge - 0.5 last_edge = last_edge + 0.5 return first_edge, last_edge
def step(self, state, momentum, rng, **args): q = state.copy() p = self.draw_momentum(rng) q_new = deepcopy(q) p_new = deepcopy(p) positions, momentums = [cp.asnumpy(q)], [cp.asnumpy(p)] epsilon = self.step_size path_length = cp.ceil(2 * cp.random.rand() * self.path_length / epsilon) grad_q = self.model.grad(q, **args) # leapfrog step for _ in cp.arange(path_length - 1): for var in self.start.keys(): p_new[var] -= (0.5 * epsilon) * grad_q[var] q_new[var] += epsilon * p_new[var] grad_q = self.model.grad(q_new, **args) p_new[var] -= epsilon * grad_q[var] #positions.append(deepcopy(q_new)) #momentums.append(deepcopy(p_new)) # negate momentum for var in self.start.keys(): p_new[var] = -p_new[var] acceptprob = self.accept(q, q_new, p, p_new, **args) if cp.isfinite(acceptprob) and (cp.random.rand() < acceptprob): q = q_new.copy() p = p_new.copy() return q, p, positions, momentums, acceptprob
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 isfinite(x: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.isfinite <numpy.isfinite>`. See its docstring for more information. """ if x.dtype not in _numeric_dtypes: raise TypeError("Only numeric dtypes are allowed in isfinite") return Array._new(np.isfinite(x._array))
def _lu_factor(a, overwrite_a=False, check_finite=True): a = cupy.asarray(a) _util._assert_2d(a) dtype = a.dtype if dtype.char == 'f': getrf = cusolver.sgetrf getrf_bufferSize = cusolver.sgetrf_bufferSize elif dtype.char == 'd': getrf = cusolver.dgetrf getrf_bufferSize = cusolver.dgetrf_bufferSize elif dtype.char == 'F': getrf = cusolver.cgetrf getrf_bufferSize = cusolver.cgetrf_bufferSize elif dtype.char == 'D': getrf = cusolver.zgetrf getrf_bufferSize = cusolver.zgetrf_bufferSize else: msg = 'Only float32, float64, complex64 and complex128 are supported.' raise NotImplementedError(msg) a = a.astype(dtype, order='F', copy=(not overwrite_a)) if check_finite: if a.dtype.kind == 'f' and not cupy.isfinite(a).all(): raise ValueError('array must not contain infs or NaNs') cusolver_handle = device.get_cusolver_handle() dev_info = cupy.empty(1, dtype=numpy.int32) m, n = a.shape ipiv = cupy.empty((min(m, n), ), dtype=numpy.intc) buffersize = getrf_bufferSize(cusolver_handle, m, n, a.data.ptr, m) workspace = cupy.empty(buffersize, dtype=dtype) # LU factorization getrf(cusolver_handle, m, n, a.data.ptr, m, workspace.data.ptr, ipiv.data.ptr, dev_info.data.ptr) if not runtime.is_hip and dev_info[0] < 0: # rocSOLVER does not inform us this info raise ValueError('illegal value in %d-th argument of ' 'internal getrf (lu_factor)' % -dev_info[0]) elif dev_info[0] > 0: warn('Diagonal number %d is exactly zero. Singular matrix.' % dev_info[0], RuntimeWarning, stacklevel=2) # cuSolver uses 1-origin while SciPy uses 0-origin ipiv -= 1 return (a, ipiv)
def test_li_pathological_arrays(): # See https://github.com/scikit-image/scikit-image/issues/4140 a = cp.asarray([0, 0, 1, 0, 0, 1, 0, 1]) b = cp.asarray([0, 0, 0.1, 0, 0, 0.1, 0, 0.1]) c = cp.asarray([0, 0, 0.1, 0, 0, 0.1, 0.01, 0.1]) d = cp.asarray([0, 0, 1, 0, 0, 1, 0.5, 1]) e = cp.asarray([1, 1]) f = cp.asarray([1, 2]) arrays = [a, b, c, d, e, f] thresholds = cp.asarray([float(threshold_li(arr)) for arr in arrays]) assert cp.all(cp.isfinite(thresholds))
def test_li_pathological_arrays(): # See https://github.com/scikit-image/scikit-image/issues/4140 a = cp.array([0, 0, 1, 0, 0, 1, 0, 1]) b = cp.array([0, 0, 0.1, 0, 0, 0.1, 0, 0.1]) c = cp.array([0, 0, 0.1, 0, 0, 0.1, 0.01, 0.1]) d = cp.array([0, 0, 1, 0, 0, 1, 0.5, 1]) e = cp.array([1, 1]) f = cp.asarray([1, 2]) arrays = [a, b, c, d, e, f] with np.errstate(divide='ignore'): # ignoring "divide by zero encountered in log" error from np.log(0) thresholds = cp.array([float(threshold_li(arr)) for arr in arrays]) assert cp.all(cp.isfinite(thresholds))
def test_blank_image_nans(): """Some of the corner detectors had a weakness in terms of returning NaN when presented with regions of constant intensity. This should be fixed by now. We test whether each detector returns something finite in the case of constant input""" # detectors = [corner_moravec, corner_harris, corner_shi_tomasi, # corner_kitchen_rosenfeld] detectors = [ corner_harris, corner_shi_tomasi, corner_kitchen_rosenfeld, ] constant_image = cp.zeros((20, 20)) for det in detectors: response = det(constant_image) assert cp.all(cp.isfinite(response)) w, q = corner_foerstner(constant_image) assert cp.all(cp.isfinite(w)) assert cp.all(cp.isfinite(q))
def log_softmax(x, axis=None): """Compute logarithm of softmax function Parameters ---------- x : array-like Input array axis : int or tuple of ints, optional Axis to compute values along. Default is None and softmax will be computed over the entire array `x` Returns ------- s : cupy.ndarry An array with the same shape as `x`. Exponential of the result will sum to 1 along the specified axis. If `x` is a scalar, a scalar is returned """ x_max = cp.amax(x, axis=axis, keepdims=True) if x_max.ndim > 0: x_max[~cp.isfinite(x_max)] = 0 elif not cp.isfinite(x_max): x_max = 0 tmp = x - x_max if tmp.dtype.kind in 'iu': for out_dtype in [cp.float16, cp.float32, cp.float64]: if cp.can_cast(tmp.dtype, out_dtype): tmp = tmp.astype(out_dtype) break out = _log_softmax_kernel(tmp, axis=axis, keepdims=True) out = tmp - out return out
def fhtcoeff(n, dln, mu, offset=0.0, bias=0.0): '''Compute the coefficient array for a fast Hankel transform. ''' lnkr, q = offset, bias # Hankel transform coefficients # u_m = (kr)^{-i 2m pi/(n dlnr)} U_mu(q + i 2m pi/(n dlnr)) # with U_mu(x) = 2^x Gamma((mu+1+x)/2)/Gamma((mu+1-x)/2) xp = (mu + 1 + q)/2 xm = (mu + 1 - q)/2 y = cupy.linspace(0, math.pi * (n // 2) / (n * dln), n // 2 + 1) u = cupy.empty(n // 2 + 1, dtype=complex) v = cupy.empty(n // 2 + 1, dtype=complex) u.imag[:] = y u.real[:] = xm loggamma(u, out=v) u.real[:] = xp loggamma(u, out=u) y *= 2 * (LN_2 - lnkr) u.real -= v.real u.real += LN_2 * q u.imag += v.imag u.imag += y cupy.exp(u, out=u) # fix last coefficient to be real u.imag[-1] = 0 # deal with special cases if not cupy.isfinite(u[0]): # write u_0 = 2^q Gamma(xp)/Gamma(xm) = 2^q poch(xm, xp-xm) # poch() handles special cases for negative integers correctly u[0] = 2**q * poch(xm, xp - xm) # the coefficient may be inf or 0, meaning the transform or the # inverse transform, respectively, is singular return u
def step(self, state, momentum, rng, **args): q = state.copy() p = self.draw_momentum(rng) q_new = deepcopy(q) p_new = deepcopy(p) epsilon = self.step_size path_length = cp.ceil(2 * cp.random.rand() * self.path_length / epsilon) grad_q = self.model.grad(q, **args) # SG-HMC leapfrog step for _ in cp.arange(path_length - 1): for var in self.start.keys(): dim = (cp.array(q_new[var])).size rvar = rng.normal(0, 2 * epsilon, dim).reshape(q[var].shape) q_new[var] += epsilon * p_new[var] grad_q = self.model.grad(q_new, **args) p_new[var] = ( 1 - epsilon) * p_new[var] + epsilon * grad_q[var] + rvar acceptprob = self.accept(q, q_new, p, p_new, **args) if cp.isfinite(acceptprob) and (cp.random.rand() < acceptprob): q = q_new.copy() p = p_new.copy() return q, p, acceptprob
def asarray_chkfinite(a, dtype=None, order=None): """Converts the given input to an array, and raises an error if the input contains NaNs or Infs. Args: a: array like. dtype: data type, optional order: {'C', 'F', 'A', 'K'}, optional Returns: cupy.ndarray: An array on the current device. .. note:: This function performs device synchronization. .. seealso:: :func:`numpy.asarray_chkfinite` """ a = cupy.asarray(a, dtype=dtype, order=order) if not cupy.isfinite(a).all(): raise ValueError("array must not contain Infs or NaNs") return a
def lstsq_grad( op, comm, data, probe, scan, psi, recover_psi=True, recover_probe=False, recover_positions=False, cg_iter=4, cost=None, eigen_probe=None, eigen_weights=None, ): # yapf: disable """Solve the ptychography problem using Odstrcil et al's approach. The near- and farfield- ptychography problems are solved separately using gradient descent in the farfield and linear-least-squares in the nearfield. Parameters ---------- op : tike.operators.Ptycho A ptychography operator. comm : tike.communicators.Comm An object which manages communications between GPUs and nodes. References ---------- Michal Odstrcil, Andreas Menzel, and Manuel Guizar-Sicaros. Iterative least-squares solver for generalized maximum-likelihood ptychography. Optics Express. 2018. """ data_ = data[0] probe = probe[0] scan_ = scan[0] psi = psi[0] if eigen_probe is not None: eigen_weights = eigen_weights[0] eigen_probe = eigen_probe[0] # ------------------------------------------------------------------------- common_probe = probe unique_probe = get_varying_probe( probe, eigen_probe=eigen_probe, weights=eigen_weights, ) farplane, cost = _update_wavefront(op, data_, unique_probe, scan_, psi) pad, end = op.diffraction.pad, op.diffraction.end # Solve the nearplane problem --------------------------------------------- for m in range(probe.shape[-3]): nearplane = farplane[..., m:m + 1, pad:end, pad:end] cprobe = common_probe[..., m:m + 1, :, :] uprobe = unique_probe[..., m:m + 1, :, :] patches = op.diffraction._patch( patches=cp.zeros(nearplane.shape, dtype='complex64'), psi=psi, scan=scan_, fwd=True, ) # χ (diff) is the target for the nearplane problem; the difference # between the desired nearplane and the current nearplane that we wish # to minimize. diff = nearplane - uprobe * patches logger.info('%10s cost is %+12.5e', 'nearplane', norm(diff)) if recover_psi: grad_psi = cp.conj(uprobe) * diff # (25b) Common object gradient. Use a weighted (normalized) sum # instead of division as described in publication to improve # numerical stability. common_grad_psi = op.diffraction._patch( patches=grad_psi, psi=cp.zeros(psi.shape, dtype='complex64'), scan=scan_, fwd=False, ) dOP = op.diffraction._patch( patches=cp.zeros(patches.shape, dtype='complex64'), psi=common_grad_psi, scan=scan_, fwd=True, ) * uprobe A1 = cp.sum((dOP * dOP.conj()).real + 0.5, axis=(-2, -1)) A1 += 0.5 * cp.mean(A1, axis=-3, keepdims=True) b1 = cp.sum((dOP.conj() * diff).real, axis=(-2, -1)) if recover_probe: grad_probe = cp.conj(patches) * diff # (25a) Common probe gradient. Use simple average instead of # division as described in publication because that's what # ptychoshelves does common_grad_probe = cp.mean( grad_probe, axis=-5, keepdims=True, ) dPO = common_grad_probe * patches A4 = cp.sum((dPO * dPO.conj()).real + 0.5, axis=(-2, -1)) A4 += 0.5 * cp.mean(A4, axis=-3, keepdims=True) b2 = cp.sum((dPO.conj() * diff).real, axis=(-2, -1)) if recover_probe and eigen_probe is not None: logger.info('Updating eigen probes') # (30) residual probe updates R = grad_probe - cp.mean(grad_probe, axis=-5, keepdims=True) for c in range(eigen_probe.shape[-4]): eigen_probe[..., c:c + 1, m:m + 1, :, :] = update_eigen_probe( R, eigen_probe[..., c:c + 1, m:m + 1, :, :], eigen_weights[..., c, m], β=0.01, # TODO: Adjust according to mini-batch size ) # Determine new eigen_weights for the updated eigen probe phi = patches * eigen_probe[..., c:c + 1, m:m + 1, :, :] n = cp.mean( cp.real(diff * phi.conj()), axis=(-1, -2), keepdims=True, ) norm_phi = cp.square(cp.abs(phi)) d = cp.mean(norm_phi, axis=(-1, -2), keepdims=True) d += 0.1 * cp.mean(d, axis=-5, keepdims=True) weight_update = (n / d).reshape(*eigen_weights[..., 0, 0].shape) assert cp.all(cp.isfinite(weight_update)) # (33) The sum of all previous steps constrained to zero-mean eigen_weights[..., c, m] += weight_update eigen_weights[..., c, m] -= cp.mean( eigen_weights[..., c, m], axis=-1, keepdims=True, ) if eigen_probe.shape[-4] <= c + 1: # Subtract projection of R onto new probe from R R -= projection( R, eigen_probe[..., c:c + 1, m:m + 1, :, :], axis=(-2, -1), ) # (22) Use least-squares to find the optimal step sizes simultaneously if recover_psi and recover_probe: A2 = cp.sum((dOP * dPO.conj()), axis=(-2, -1)) A3 = A2.conj() determinant = A1 * A4 - A2 * A3 x1 = -cp.conj(A2 * b2 - A4 * b1) / determinant x2 = cp.conj(A1 * b2 - A3 * b1) / determinant elif recover_psi: x1 = b1 / A1 elif recover_probe: x2 = b2 / A4 # Update each direction if recover_psi: step = x1[..., None, None] # (27b) Object update weighted_step = cp.mean(step, keepdims=True, axis=-5)[..., 0, 0, 0] psi += weighted_step * common_grad_psi if recover_probe: step = x2[..., None, None] # (27a) Probe update cprobe += common_grad_probe * cp.mean( step, axis=-5, keepdims=True, ) if __debug__: patches = op.diffraction._patch( patches=cp.zeros(nearplane.shape, dtype='complex64'), psi=psi, scan=scan_, fwd=True, ) logger.info('%10s cost is %+12.5e', 'nearplane', norm(cprobe * patches - nearplane)) result = { 'psi': [psi], 'probe': [probe], 'cost': cost, 'scan': scan, } if eigen_probe is not None: result['eigen_probe'] = [eigen_probe] result['eigen_weights'] = [eigen_weights] return result
def test_standard_logistic_isfinite(self): x = self.generate(size=10**7) self.assertTrue(cupy.isfinite(x).all())
def test_standard_exponential_isfinite(self): x = self.generate(size=10**7) assert cupy.isfinite(x).all()
def _check_cval(mode, cval, integer_output): if mode == 'constant' and integer_output and not cupy.isfinite(cval): raise NotImplementedError("Non-finite cval is not supported for " "outputs with integer dtype.")
def lu_solve(lu_and_piv, b, trans=0, overwrite_b=False, check_finite=True): """Solve an equation system, ``a * x = b``, given the LU factorization of ``a`` Args: lu_and_piv (tuple): LU factorization of matrix ``a`` (``(M, M)``) together with pivot indices. b (cupy.ndarray): The matrix with dimension ``(M,)`` or ``(M, N)``. trans ({0, 1, 2}): Type of system to solve: ======== ========= trans system ======== ========= 0 a x = b 1 a^T x = b 2 a^H x = b ======== ========= overwrite_b (bool): Allow overwriting data in b (may enhance performance) check_finite (bool): Whether to check that the input matrices contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns: cupy.ndarray: The matrix with dimension ``(M,)`` or ``(M, N)``. .. seealso:: :func:`scipy.linalg.lu_solve` """ (lu, ipiv) = lu_and_piv util._assert_cupy_array(lu) util._assert_rank2(lu) util._assert_nd_squareness(lu) m = lu.shape[0] if m != b.shape[0]: raise ValueError('incompatible dimensions.') dtype = lu.dtype if dtype.char == 'f': getrs = cusolver.sgetrs elif dtype.char == 'd': getrs = cusolver.dgetrs else: raise NotImplementedError('Only float32 and float64 are supported.') if trans == 0: trans = cublas.CUBLAS_OP_N elif trans == 1: trans = cublas.CUBLAS_OP_T elif trans == 2: trans = cublas.CUBLAS_OP_C else: raise ValueError('unknown trans') lu = lu.astype(dtype, order='F', copy=False) ipiv = ipiv.astype(ipiv.dtype, order='F', copy=True) # cuSolver uses 1-origin while SciPy uses 0-origin ipiv += 1 b = b.astype(dtype, order='F', copy=(not overwrite_b)) if check_finite: if lu.dtype.kind == 'f' and not cupy.isfinite(lu).all(): raise ValueError( 'array must not contain infs or NaNs.\n' 'Note that when a singular matrix is given, unlike ' 'scipy.linalg.lu_factor, cupyx.scipy.linalg.lu_factor ' 'returns an array containing NaN.') if b.dtype.kind == 'f' and not cupy.isfinite(b).all(): raise ValueError('array must not contain infs or NaNs') n = 1 if b.ndim == 1 else b.shape[1] cusolver_handle = device.get_cusolver_handle() dev_info = cupy.empty(1, dtype=numpy.int32) # solve for the inverse getrs(cusolver_handle, trans, m, n, lu.data.ptr, m, ipiv.data.ptr, b.data.ptr, m, dev_info.data.ptr) if dev_info[0] < 0: raise ValueError('illegal value in %d-th argument of ' 'internal getrs (lu_solve)' % -dev_info[0]) return b
def lu_factor(a, overwrite_a=False, check_finite=True): """LU decomposition. Decompose a given two-dimensional square matrix into ``P * L * U``, where ``P`` is a permutation matrix, ``L`` lower-triangular with unit diagonal elements, and ``U`` upper-triangular matrix. Note that in the current implementation ``a`` must be a real matrix, and only :class:`numpy.float32` and :class:`numpy.float64` are supported. Args: a (cupy.ndarray): The input matrix with dimension ``(M, N)`` overwrite_a (bool): Allow overwriting data in ``a`` (may enhance performance) check_finite (bool): Whether to check that the input matrices contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns: tuple: ``(lu, piv)`` where ``lu`` is a :class:`cupy.ndarray` storing ``U`` in its upper triangle, and ``L`` without unit diagonal elements in its lower triangle, and ``piv`` is a :class:`cupy.ndarray` storing pivot indices representing permutation matrix ``P``. For ``0 <= i < min(M,N)``, row ``i`` of the matrix was interchanged with row ``piv[i]`` .. seealso:: :func:`scipy.linalg.lu_factor` .. note:: Current implementation returns result different from SciPy when the matrix singular. SciPy returns an array containing ``0.`` while the current implementation returns an array containing ``nan``. >>> import numpy as np >>> import scipy.linalg >>> scipy.linalg.lu_factor(np.array([[0, 1], [0, 0]], \ dtype=np.float32)) (array([[0., 1.], [0., 0.]], dtype=float32), array([0, 1], dtype=int32)) >>> import cupy as cp >>> import cupyx.scipy.linalg >>> cupyx.scipy.linalg.lu_factor(cp.array([[0, 1], [0, 0]], \ dtype=cp.float32)) (array([[ 0., 1.], [nan, nan]], dtype=float32), array([0, 1], dtype=int32)) """ a = cupy.asarray(a) util._assert_rank2(a) dtype = a.dtype if dtype.char == 'f': getrf = cusolver.sgetrf getrf_bufferSize = cusolver.sgetrf_bufferSize elif dtype.char == 'd': getrf = cusolver.dgetrf getrf_bufferSize = cusolver.dgetrf_bufferSize else: raise NotImplementedError('Only float32 and float64 are supported.') a = a.astype(dtype, order='F', copy=(not overwrite_a)) if check_finite: if a.dtype.kind == 'f' and not cupy.isfinite(a).all(): raise ValueError('array must not contain infs or NaNs') cusolver_handle = device.get_cusolver_handle() dev_info = cupy.empty(1, dtype=numpy.int32) m, n = a.shape ipiv = cupy.empty((min(m, n), ), dtype=numpy.intc) buffersize = getrf_bufferSize(cusolver_handle, m, n, a.data.ptr, m) workspace = cupy.empty(buffersize, dtype=dtype) # LU factorization getrf(cusolver_handle, m, n, a.data.ptr, m, workspace.data.ptr, ipiv.data.ptr, dev_info.data.ptr) if dev_info[0] < 0: raise ValueError('illegal value in %d-th argument of ' 'internal getrf (lu_factor)' % -dev_info[0]) elif dev_info[0] > 0: warn('Diagonal number %d is exactly zero. Singular matrix.' % dev_info[0], RuntimeWarning, stacklevel=2) # cuSolver uses 1-origin while SciPy uses 0-origin ipiv -= 1 return (a, ipiv)
def test_standard_exponential_isfinite(self): for _ in range(10): x = self.generate(size=10**7) self.assertTrue(cupy.isfinite(x).all())
def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False, overwrite_b=False, check_finite=False): """Solve the equation a x = b for x, assuming a is a triangular matrix. Args: a (cupy.ndarray): The matrix with dimension ``(M, M)``. b (cupy.ndarray): The matrix with dimension ``(M,)`` or ``(M, N)``. lower (bool): Use only data contained in the lower triangle of ``a``. Default is to use upper triangle. trans (0, 1, 2, 'N', 'T' or 'C'): Type of system to solve: - *'0'* or *'N'* -- :math:`a x = b` - *'1'* or *'T'* -- :math:`a^T x = b` - *'2'* or *'C'* -- :math:`a^H x = b` unit_diagonal (bool): If ``True``, diagonal elements of ``a`` are assumed to be 1 and will not be referenced. overwrite_b (bool): Allow overwriting data in b (may enhance performance) check_finite (bool): Whether to check that the input matrices contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns: cupy.ndarray: The matrix with dimension ``(M,)`` or ``(M, N)``. .. seealso:: :func:`scipy.linalg.solve_triangular` """ _util._assert_cupy_array(a, b) if len(a.shape) != 2 or a.shape[0] != a.shape[1]: raise ValueError('expected square matrix') if len(a) != len(b): raise ValueError('incompatible dimensions') # Cast to float32 or float64 if a.dtype.char in 'fd': dtype = a.dtype else: dtype = numpy.promote_types(a.dtype.char, 'f') a = cupy.array(a, dtype=dtype, order='F', copy=False) b = cupy.array(b, dtype=dtype, order='F', copy=(not overwrite_b)) if check_finite: if a.dtype.kind == 'f' and not cupy.isfinite(a).all(): raise ValueError('array must not contain infs or NaNs') if b.dtype.kind == 'f' and not cupy.isfinite(b).all(): raise ValueError('array must not contain infs or NaNs') m, n = (b.size, 1) if b.ndim == 1 else b.shape cublas_handle = device.get_cublas_handle() if dtype == 'f': trsm = cublas.strsm elif dtype == 'd': trsm = cublas.dtrsm elif dtype == 'F': trsm = cublas.ctrsm else: # dtype == 'D' trsm = cublas.ztrsm one = numpy.array(1, dtype=dtype) if lower: uplo = cublas.CUBLAS_FILL_MODE_LOWER else: uplo = cublas.CUBLAS_FILL_MODE_UPPER if trans == 'N': trans = cublas.CUBLAS_OP_N elif trans == 'T': trans = cublas.CUBLAS_OP_T elif trans == 'C': trans = cublas.CUBLAS_OP_C if unit_diagonal: diag = cublas.CUBLAS_DIAG_UNIT else: diag = cublas.CUBLAS_DIAG_NON_UNIT trsm(cublas_handle, cublas.CUBLAS_SIDE_LEFT, uplo, trans, diag, m, n, one.ctypes.data, a.data.ptr, m, b.data.ptr, m) return b
def threshold_li(image, *, tolerance=None, initial_guess=None, iter_callback=None): """Compute threshold value by Li's iterative Minimum Cross Entropy method. Parameters ---------- image : ndarray Input image. tolerance : float, optional Finish the computation when the change in the threshold in an iteration is less than this value. By default, this is half the smallest difference between intensity values in ``image``. initial_guess : float or Callable[[array[float]], float], optional Li's iterative method uses gradient descent to find the optimal threshold. If the image intensity histogram contains more than two modes (peaks), the gradient descent could get stuck in a local optimum. An initial guess for the iteration can help the algorithm find the globally-optimal threshold. A float value defines a specific start point, while a callable should take in an array of image intensities and return a float value. Example valid callables include ``numpy.mean`` (default), ``lambda arr: numpy.quantile(arr, 0.95)``, or even :func:`skimage.filters.threshold_otsu`. iter_callback : Callable[[float], Any], optional A function that will be called on the threshold at every iteration of the algorithm. Returns ------- threshold : float Upper threshold value. All pixels with an intensity higher than this value are assumed to be foreground. References ---------- .. [1] Li C.H. and Lee C.K. (1993) "Minimum Cross Entropy Thresholding" Pattern Recognition, 26(4): 617-625 :DOI:`10.1016/0031-3203(93)90115-D` .. [2] Li C.H. and Tam P.K.S. (1998) "An Iterative Algorithm for Minimum Cross Entropy Thresholding" Pattern Recognition Letters, 18(8): 771-776 :DOI:`10.1016/S0167-8655(98)00057-9` .. [3] Sezgin M. and Sankur B. (2004) "Survey over Image Thresholding Techniques and Quantitative Performance Evaluation" Journal of Electronic Imaging, 13(1): 146-165 :DOI:`10.1117/1.1631315` .. [4] ImageJ AutoThresholder code, http://fiji.sc/wiki/index.php/Auto_Threshold Examples -------- >>> from skimage.data import camera >>> image = camera() >>> thresh = threshold_li(image) >>> binary = image > thresh """ # noqa # Remove nan: image = image[~cp.isnan(image)] if image.size == 0: return cp.nan # Make sure image has more than one value; otherwise, return that value # This works even for cp.inf val0 = image.ravel()[0] if cp.all(image == val0): # device synchronize! return val0 # At this point, the image only contains cp.inf, -cp.inf, or valid numbers image = image[cp.isfinite(image)] # if there are no finite values in the image, return 0. This is because # at this point we *know* that there are *both* inf and -inf values, # because inf == inf evaluates to True. We might as well separate them. if image.size == 0: return 0.0 # Li's algorithm requires positive image (because of log(mean)) image_min = cp.min(image) image -= image_min tolerance = tolerance or cp.min(cp.diff(cp.unique(image))) / 2 # Initial estimate for iteration. See "initial_guess" in the parameter list if initial_guess is None: t_next = cp.mean(image) elif callable(initial_guess): t_next = initial_guess(image) elif cp.isscalar(initial_guess): # convert to new, positive image range t_next = initial_guess - image_min image_max = cp.max(image) + image_min if not 0 < t_next < cp.max(image): msg = ('The initial guess for threshold_li must be within the ' 'range of the image. Got {} for image min {} and max {} '. format(initial_guess, image_min, image_max)) raise ValueError(msg) else: raise TypeError('Incorrect type for `initial_guess`; should be ' 'a floating point value, or a function mapping an ' 'array to a floating point value.') # initial value for t_curr must be different from t_next by at # least the tolerance. Since the image is positive, we ensure this # by setting to a large-enough negative number t_curr = -2 * tolerance # Callback on initial iterations if iter_callback is not None: iter_callback(t_next + image_min) # Stop the iterations when the difference between the # new and old threshold values is less than the tolerance while abs(t_next - t_curr) > tolerance: t_curr = t_next foreground = image > t_curr mean_fore = cp.mean(image[foreground]) mean_back = cp.mean(image[~foreground]) t_next = ((mean_back - mean_fore) / (cp.log(mean_back) - cp.log(mean_fore))) if iter_callback is not None: iter_callback(t_next + image_min) threshold = t_next + image_min return threshold
def test_standard_cauchy_isfinite(self): x = self.generate(size=10**7) assert cupy.isfinite(x).all()
#print(i) if i == 5000: P3 = cp.cov(Thetasim[0:i], rowvar=False) while go_on == 0: Thetac = cp.random.multivariate_normal(Thetasim[i, :], (c) * P3) try: G1, impact, RC, A, B, C, E, DD, R, V_s = REE_gen1( cp.asnumpy(Thetac)) except: RC = cp.zeros([2, 1]) go_on = param_checks(Thetac, RC) prioc = NK_priors(cp.asnumpy(Thetac)) likic, dropoutc = PFLIKE(Thetac, EPS, S, RR, randphi) objc = cp.float(NK_priors(cp.asnumpy(Thetac))) + cp.float(likic) #print(objc) if cp.isfinite(objc) == False: alpha = -1 u = 0 else: u = cp.log(cp.random.uniform(0, 1, 1)) alpha = objc - obj if alpha - u >= 0: Thetasim[i + 1, :] = Thetac accept = accept + 1 DROP[i + 1] = dropoutc logpost[i + 1] = objc LIK[i + 1] = likic obj = objc likij = likic dropoutj = dropoutc #print('accepted')