def inertia_tensor_eigvals(image, mu=None, T=None): """Compute the eigenvalues of the inertia tensor of the image. The inertia tensor measures covariance of the image intensity along the image axes. (See `inertia_tensor`.) The relative magnitude of the eigenvalues of the tensor is thus a measure of the elongation of a (bright) object in the image. Parameters ---------- image : array The input image. mu : array, optional The pre-computed central moments of ``image``. T : array, shape ``(image.ndim, image.ndim)`` The pre-computed inertia tensor. If ``T`` is given, ``mu`` and ``image`` are ignored. Returns ------- eigvals : list of float, length ``image.ndim`` The eigenvalues of the inertia tensor of ``image``, in descending order. Notes ----- Computing the eigenvalues requires the inertia tensor of the input image. This is much faster if the central moments (``mu``) are provided, or, alternatively, one can provide the inertia tensor (``T``) directly. """ if T is None: T = inertia_tensor(image, mu) eigvals = cp.linalg.eigvalsh(T) # Floating point precision problems could make a positive # semidefinite matrix have an eigenvalue that is very slightly # negative. This can cause problems down the line, so set values # very near zero to zero. eigvals = cp.clip(eigvals, 0, None, out=eigvals) return sorted(eigvals, reverse=True)
def generate(self, __noise): unix = time.time() z = Variable(__noise) print(1, (time.time() - unix) * 10000) unix = time.time() x = self.generator(z) print(2, (time.time() - unix) * 10000) unix = time.time() images = np.array([]) for i in range(0, x.shape[0]): x_clipped = (x.data[i, :, :, :] + 1) / 2 image = (x_clipped[0] + x_clipped[1] + x_clipped[2]) / 3 * 255 image = np.clip(image, 0, 255) image = image.flatten() images = np.concatenate((images, image), axis=0) return images
def iterative_gradient(self, eps, alpha =1, n_iter = None): xp = AdvImage.xp if n_iter is None: n_iter = int(min(eps + 4, 1.25 * eps)) t = xp.array([self.index], dtype=xp.int32) out_layer = AdvImage.last_layer target_org = self.target.data.copy() for _ in range(n_iter): x = AdvImage.model(self.target, layers=[out_layer])[out_layer] loss = F.softmax_cross_entropy(x, t) self.target.cleargrad() AdvImage.model.cleargrads() loss.backward() perturb = xp.sign(self.target.grad) updated_data = self.target.data + alpha * perturb clipped_data = xp.clip(updated_data, target_org - eps, target_org + eps) self.target = Variable(clipped_data) self.adv_image = self._restore_image(self.target)
def g(x, y, z): return cupy.clip(x, y, z)
def ravel_multi_index(multi_index, dims, mode='wrap', order='C'): """ Converts a tuple of index arrays into an array of flat indices, applying boundary modes to the multi-index. Args: multi_index (tuple of cupy.ndarray) : A tuple of integer arrays, one array for each dimension. dims (tuple of ints): The shape of array into which the indices from ``multi_index`` apply. mode ('raise', 'wrap' or 'clip'), optional: Specifies how out-of-bounds indices are handled. Can specify either one mode or a tuple of modes, one mode per index: - *'raise'* -- raise an error - *'wrap'* -- wrap around (default) - *'clip'* -- clip to the range In 'clip' mode, a negative index which would normally wrap will clip to 0 instead. order ('C' or 'F'), optional: Determines whether the multi-index should be viewed as indexing in row-major (C-style) or column-major (Fortran-style) order. Returns: raveled_indices (cupy.ndarray): An array of indices into the flattened version of an array of dimensions ``dims``. .. warning:: This function may synchronize the device when ``mode == 'raise'``. Notes ----- Note that the default `mode` (``'wrap'``) is different than in NumPy. This is done to avoid potential device synchronization. Examples -------- >>> cupy.ravel_multi_index(cupy.asarray([[3,6,6],[4,5,1]]), (7,6)) array([22, 41, 37]) >>> cupy.ravel_multi_index(cupy.asarray([[3,6,6],[4,5,1]]), (7,6), ... order='F') array([31, 41, 13]) >>> cupy.ravel_multi_index(cupy.asarray([[3,6,6],[4,5,1]]), (4,6), ... mode='clip') array([22, 23, 19]) >>> cupy.ravel_multi_index(cupy.asarray([[3,6,6],[4,5,1]]), (4,4), ... mode=('clip', 'wrap')) array([12, 13, 13]) >>> cupy.ravel_multi_index(cupy.asarray((3,1,4,1)), (6,7,8,9)) array(1621) .. seealso:: :func:`numpy.ravel_multi_index`, :func:`unravel_index` """ ndim = len(dims) if len(multi_index) != ndim: raise ValueError( "parameter multi_index must be a sequence of " "length {}".format(ndim)) for d in dims: if not isinstance(d, numbers.Integral): raise TypeError( "{} object cannot be interpreted as an integer".format( type(d))) if isinstance(mode, str): mode = (mode, ) * ndim if functools.reduce(operator.mul, dims) > cupy.iinfo(cupy.int64).max: raise ValueError("invalid dims: array size defined by dims is larger " "than the maximum possible size") s = 1 ravel_strides = [1] * ndim if order is None: order = "C" if order == "C": for i in range(ndim - 2, -1, -1): s = s * dims[i + 1] ravel_strides[i] = s elif order == "F": for i in range(1, ndim): s = s * dims[i - 1] ravel_strides[i] = s else: raise TypeError("order not understood") multi_index = cupy.broadcast_arrays(*multi_index) raveled_indices = cupy.zeros(multi_index[0].shape, dtype=cupy.int64) for d, stride, idx, _mode in zip(dims, ravel_strides, multi_index, mode): if not isinstance(idx, cupy.ndarray): raise TypeError("elements of multi_index must be cupy arrays") if not cupy.can_cast(idx, cupy.int64, 'same_kind'): raise TypeError( 'multi_index entries could not be cast from dtype(\'{}\') to ' 'dtype(\'{}\') according to the rule \'same_kind\''.format( idx.dtype, cupy.int64().dtype)) idx = idx.astype(cupy.int64, copy=False) if _mode == "raise": if cupy.any(cupy.logical_or(idx >= d, idx < 0)): raise ValueError("invalid entry in coordinates array") elif _mode == "clip": idx = cupy.clip(idx, 0, d - 1) elif _mode == 'wrap': idx = idx % d else: raise TypeError("Unrecognized mode: {}".format(_mode)) raveled_indices += stride * idx return raveled_indices
def target_encode_cudf_v3( train, valid, col, tar, n_folds=5, min_ct=0, smooth=20, seed=42, shuffle=False, t2=None, v2=None, x=-1, ): # # col = column to target encode (or if list of columns then multiple groupby) # tar = tar column encode against # if min_ct>0 then all classes with <= min_ct are consider in new class "other" # smooth = Bayesian smooth parameter # seed = for 5 Fold if shuffle==True # if x==-1 result appended to train and valid # if x>=0 then result returned in column x of t2 and v2 # # SINGLE OR MULTIPLE COLUMN if not isinstance(col, list): col = [col] if (min_ct > 0) & (len(col) > 1): print("WARNING: Setting min_ct=0 with multiple columns. Not implemented") min_ct = 0 name = "_".join(col) # FIT ALL TRAIN gf = cudf.from_pandas(train[col + [tar]]).reset_index(drop=True) gf["idx"] = gf.index # needed because cuDF merge returns out of order if min_ct > 0: # USE MIN_CT? other = gf.groupby(col[0]).size() other = other[other <= min_ct].index save = gf[col[0]].values.copy() gf.loc[gf[col[0]].isin(other), col[0]] = -1 te = gf.groupby(col)[[tar]].agg(["mean", "count"]).reset_index() te.columns = col + ["m", "c"] mn = gf[tar].mean().astype("float32") te["smooth"] = ((te["m"] * te["c"]) + (mn * smooth)) / (te["c"] + smooth) if min_ct > 0: gf[col[0]] = save.copy() # PREDICT VALID gf2 = cudf.from_pandas(valid[col]).reset_index(drop=True) gf2["idx"] = gf2.index if min_ct > 0: gf2.loc[gf2[col[0]].isin(other), col[0]] = -1 gf2 = gf2.merge(te[col + ["smooth"]], on=col, how="left", sort=False).sort_values( "idx" ) if x == -1: valid[f"TE_{name}_{tar}"] = ( gf2["smooth"].fillna(mn).astype("float32").to_array() ) elif x >= 0: v2[:, x] = gf2["smooth"].fillna(mn).astype("float32").to_array() # KFOLD ON TRAIN tmp = cupy.zeros((train.shape[0]), dtype="float32") gf["fold"] = 0 if shuffle: # shuffling is 2x slower kf = KFold(n_folds, random_state=seed, shuffle=shuffle) for k, (idxT, idxV) in enumerate(kf.split(train)): gf.loc[idxV, "fold"] = k else: fsize = train.shape[0] // n_folds gf["fold"] = cupy.clip(gf.idx.values // fsize, 0, n_folds - 1) for k in range(n_folds): if min_ct > 0: # USE MIN CT? if k < n_folds - 1: save = gf[col[0]].values.copy() other = gf.loc[gf.fold != k].groupby(col[0]).size() other = other[other <= min_ct].index gf.loc[gf[col[0]].isin(other), col[0]] = -1 te = ( gf.loc[gf.fold != k] .groupby(col)[[tar]] .agg(["mean", "count"]) .reset_index() ) te.columns = col + ["m", "c"] mn = gf.loc[gf.fold != k, tar].mean().astype("float32") te["smooth"] = ((te["m"] * te["c"]) + (mn * smooth)) / (te["c"] + smooth) gf = gf.merge(te[col + ["smooth"]], on=col, how="left", sort=False).sort_values( "idx" ) tmp[(gf.fold.values == k)] = ( gf.loc[gf.fold == k, "smooth"].fillna(mn).astype("float32").values ) gf.drop_column("smooth") if (min_ct > 0) & (k < n_folds - 1): gf[col[0]] = save.copy() if x == -1: train[f"TE_{name}_{tar}"] = cupy.asnumpy(tmp.astype("float32")) elif x >= 0: t2[:, x] = cupy.asnumpy(tmp.astype("float32"))
def categorical_cross_entropy(x, y, epsilon=10**(-13)): x = cp.clip(x, epsilon, 1. - epsilon) N = x.shape[0] return -cp.sum(y * cp.log(x + 0.00001)) / N
def log_loss(y_true, y_pred, eps=1e-15, normalize=True, sample_weight=None) -> float: """ Log loss, aka logistic loss or cross-entropy loss. This is the loss function used in (multinomial) logistic regression and extensions of it such as neural networks, defined as the negative log-likelihood of a logistic model that returns ``y_pred`` probabilities for its training data ``y_true``. The log loss is only defined for two or more labels. Parameters ---------- y_true : array-like, shape = (n_samples,) y_pred : array-like of float, shape = (n_samples, n_classes) or (n_samples,) eps : float (default=1e-15) Log loss is undefined for p=0 or p=1, so probabilities are clipped to max(eps, min(1 - eps, p)). normalize : bool, optional (default=True) If true, return the mean loss per sample. Otherwise, return the sum of the per-sample losses. sample_weight : array-like of shape (n_samples,), default=None Sample weights. Returns ------- loss : float Examples -------- .. code-block:: python >>> from cuml.metrics import log_loss >>> import cupy as cp >>> log_loss(cp.array([1, 0, 0, 1]), ... cp.array([[.1, .9], [.9, .1], [.8, .2], [.35, .65]])) 0.21616... References ---------- C.M. Bishop (2006). Pattern Recognition and Machine Learning. Springer, p. 209. Notes ----- The logarithm used is the natural logarithm (base-e). """ y_true, n_rows, n_cols, ytype = \ input_to_cupy_array(y_true, check_dtype=[np.int32, np.int64, np.float32, np.float64]) if y_true.dtype.kind == 'f' and np.any(y_true != y_true.astype(int)): raise ValueError("'y_true' can only have integer values") if y_true.min() < 0: raise ValueError("'y_true' cannot have negative values") y_pred, _, _, _ = \ input_to_cupy_array(y_pred, check_dtype=[np.int32, np.int64, np.float32, np.float64], check_rows=n_rows) y_true_max = y_true.max() if (y_pred.ndim == 1 and y_true_max > 1) \ or (y_pred.ndim > 1 and y_pred.shape[1] <= y_true_max): raise ValueError("The shape of y_pred doesn't " "match the number of classes") y_true = y_true.astype('int32') y_pred = cp.clip(y_pred, eps, 1 - eps) if y_pred.ndim == 1: y_pred = cp.expand_dims(y_pred, axis=1) if y_pred.shape[1] == 1: y_pred = cp.hstack([1 - y_pred, y_pred]) y_pred /= cp.sum(y_pred, axis=1, keepdims=True) loss = -cp.log(y_pred)[cp.arange(y_pred.shape[0]), y_true] return _weighted_sum(loss, sample_weight, normalize).item()
def rescale_intensity(image, in_range="image", out_range="dtype"): """Return image after stretching or shrinking its intensity levels. The desired intensity range of the input and output, `in_range` and `out_range` respectively, are used to stretch or shrink the intensity range of the input image. See examples below. Parameters ---------- image : array Image array. in_range, out_range : str or 2-tuple, optional Min and max intensity values of input and output image. The possible values for this parameter are enumerated below. 'image' Use image min/max as the intensity range. 'dtype' Use min/max of the image's dtype as the intensity range. dtype-name Use intensity range based on desired `dtype`. Must be valid key in `DTYPE_RANGE`. 2-tuple Use `range_values` as explicit min/max intensities. Returns ------- out : array Image array after rescaling its intensity. This image is the same dtype as the input image. Notes ----- .. versionchanged:: 0.17 The dtype of the output array has changed to match the output dtype, or float if the output range is specified by a pair of floats. See Also -------- equalize_hist Examples -------- By default, the min/max intensities of the input image are stretched to the limits allowed by the image's dtype, since `in_range` defaults to 'image' and `out_range` defaults to 'dtype': >>> image = cp.asarray([51, 102, 153], dtype=np.uint8) >>> rescale_intensity(image) array([ 0, 127, 255], dtype=uint8) It's easy to accidentally convert an image dtype from uint8 to float: >>> 1.0 * image array([ 51., 102., 153.]) Use `rescale_intensity` to rescale to the proper range for float dtypes: >>> image_float = 1.0 * image >>> rescale_intensity(image_float) array([0. , 0.5, 1. ]) To maintain the low contrast of the original, use the `in_range` parameter: >>> rescale_intensity(image_float, in_range=(0, 255)) array([0.2, 0.4, 0.6]) If the min/max value of `in_range` is more/less than the min/max image intensity, then the intensity levels are clipped: >>> rescale_intensity(image_float, in_range=(0, 102)) array([0.5, 1. , 1. ]) If you have an image with signed integers but want to rescale the image to just the positive range, use the `out_range` parameter. In that case, the output dtype will be float: >>> image = cp.asarray([-10, 0, 10], dtype=np.int8) >>> rescale_intensity(image, out_range=(0, 127)) array([ 0. , 63.5, 127. ]) To get the desired range with a specific dtype, use ``.astype()``: >>> rescale_intensity(image, out_range=(0, 127)).astype(np.int8) array([ 0, 63, 127], dtype=int8) If the input image is constant, the output will be clipped directly to the output range: >>> image = cp.asarray([130, 130, 130], dtype=np.int32) >>> rescale_intensity(image, out_range=(0, 127)).astype(np.int32) array([127, 127, 127], dtype=int32) """ if out_range in ["dtype", "image"]: out_dtype = _output_dtype(image.dtype.type) else: out_dtype = _output_dtype(out_range) imin, imax = map(float, intensity_range(image, in_range)) omin, omax = map( float, intensity_range(image, out_range, clip_negative=(imin >= 0)) ) if np.any(np.isnan([imin, imax, omin, omax])): warn( "One or more intensity levels are NaN. Rescaling will broadcast " "NaN to the full image. Provide intensity levels yourself to " "avoid this. E.g. with np.nanmin(image), np.nanmax(image).", stacklevel=2, ) image = cp.clip(image, imin, imax) if imin != imax: image = (image - imin) / (imax - imin) return cp.asarray(image * (omax - omin) + omin, dtype=out_dtype) else: return cp.clip(image, omin, omax).astype(out_dtype, copy=False)
def step(self, model, step_num): """Step function, called by solver. """ model._solution = cp.clip(model.solution, a_min=0)
def _mean_std(image, w): """Return local mean and standard deviation of each pixel using a neighborhood defined by a rectangular window size ``w``. The algorithm uses integral images to speedup computation. This is used by :func:`threshold_niblack` and :func:`threshold_sauvola`. Parameters ---------- image : ndarray Input image. w : int, or iterable of int Window size specified as a single odd integer (3, 5, 7, …), or an iterable of length ``image.ndim`` containing only odd integers (e.g. ``(1, 5, 5)``). Returns ------- m : ndarray of float, same shape as ``image`` Local mean of the image. s : ndarray of float, same shape as ``image`` Local standard deviation of the image. References ---------- .. [1] F. Shafait, D. Keysers, and T. M. Breuel, "Efficient implementation of local adaptive thresholding techniques using integral images." in Document Recognition and Retrieval XV, (San Jose, USA), Jan. 2008. :DOI:`10.1117/12.767755` """ if not isinstance(w, Iterable): w = (w, ) * image.ndim _validate_window_size(w) pad_width = tuple((k // 2 + 1, k // 2) for k in w) padded = cp.pad(image.astype('float'), pad_width, mode='reflect') integral = integral_image(padded) padded *= padded integral_sq = integral_image(padded) # Store the kernel as a list 2-tuples where: # - The first element is an index into the kernel (of shape w). # - The second element is the value at that index. kernel_indices_and_values = [] for indices in itertools.product(*tuple([(0, _w) for _w in w])): kernel_indices_and_values.append( (indices, (-1)**(image.ndim % 2 != np.sum(indices) % 2))) total_window_size = _misc.prod(w) kernel_shape = tuple(_w + 1 for _w in w) m = _correlate_sparse(integral, kernel_shape, kernel_indices_and_values) m /= total_window_size g2 = _correlate_sparse(integral_sq, kernel_shape, kernel_indices_and_values) g2 /= total_window_size # Note: we use np.clip because g2 is not guaranteed to be greater than # m*m when floating point error is considered s = cp.clip(g2 - m * m, 0, None) cp.sqrt(s, out=s) return m, s
def __getitem__(self, index): image_content = self.txn.get("image_{}".format(index).encode()) image_content = np.asarray(bytearray(image_content), dtype="uint8") image = cv2.imdecode(image_content, cv2.IMREAD_COLOR) image = cupy.asarray(image, dtype=cupy.float32) / 255.0 has_face = np.frombuffer(self.txn.get( "has_face_{}".format(index).encode()), dtype=np.bool)[0] if has_face: face_boxes = np.frombuffer(self.txn.get( "face_boxes_{}".format(index).encode()), dtype=np.int32) face_boxes = face_boxes.reshape(-1, 4).copy() face_keys = np.ones( (face_boxes.shape[0], 5, 3), dtype=np.float32) * -1 if self.is_train: face_keys = np.frombuffer(self.txn.get( "face_keys_{}".format(index).encode()), dtype=np.float32) face_keys = face_keys.reshape(-1, 5, 3).copy() face_boxes = cupy.asarray(face_boxes, dtype=cupy.float32) face_keys = cupy.asarray(face_keys) image, face_boxes, face_keys = Data_anchor_sample( image, face_boxes, face_keys) height, width, channel = image.shape c, s, rot, flipped = get_center_scale(image, self.is_train) if flipped: image = image[:, ::-1, :] c[0] = width - c[0] - 1 trans_input = get_affine_transform( c, s, 0, [g_config.input_res, g_config.input_res], inv=1) trans_input = cupy.asarray(trans_input) trans_input[[0, 1], :] = trans_input[[1, 0], :] trans_input[:, [0, 1]] = trans_input[:, [1, 0]] input_image = cupy.zeros( (g_config.input_res, g_config.input_res, channel), dtype=cupy.float32) for i in range(channel): ndimage.affine_transform(image[:, :, i], trans_input, order=1, output_shape=(g_config.input_res, g_config.input_res), output=input_image[:, :, i]) # 随机图片增强 if self.is_train: color_aug(self.data_rng, input_image, self.eig_val, self.eig_vec) input_image = (input_image - self.mean) / self.std input_image = input_image.transpose(2, 0, 1) output_res = g_config.output_res trans_output = get_affine_transform(c, s, rot, [output_res, output_res]) trans_output = cupy.asarray(trans_output) num_faces = 1 if has_face: num_faces = len(face_boxes) heat_map = cupy.zeros((1, output_res, output_res), dtype=cupy.float32) wh_gt = cupy.zeros((num_faces, 2), dtype=cupy.float32) face_index = cupy.zeros((num_faces), dtype=cupy.int32) face_off = cupy.zeros((num_faces, 2), dtype=cupy.float32) face_mask = cupy.zeros((num_faces), dtype=cupy.int8) face_key_off = cupy.zeros((num_faces, 5 * 2), dtype=cupy.float32) face_key_mask = cupy.zeros((num_faces, 5 * 2), dtype=cupy.int8) if has_face: boxes = face_boxes.copy() boxes[:, 2] += boxes[:, 0] boxes[:, 3] += boxes[:, 1] if flipped: boxes[:, [0, 2]] = width - boxes[:, [2, 0]] - 1 face_keys[:, :, 0] = width - face_keys[:, :, 0] - 1 face_keys[:, [0, 1, 3, 4], :] = face_keys[:, [1, 0, 4, 3], :] boxes[:, 0:2] = affine_transform(boxes[:, 0:2], trans_output) boxes[:, 2:4] = affine_transform(boxes[:, 2:4], trans_output) face_keys[:, :, 0:2] = affine_transform(face_keys[:, :, 0:2], trans_output) boxes = cupy.clip(boxes, 0, output_res - 1) boxes_w = boxes[:, 2] - boxes[:, 0] boxes_h = boxes[:, 3] - boxes[:, 1] for i in range(num_faces): w = boxes_w[i] h = boxes_h[i] if w > 0 and h > 0: radius = gaussian_radius((math.ceil(h), math.ceil(w))) radius = max(0, int(radius)) wh_gt[i, 0] = cupy.log(w) wh_gt[i, 1] = cupy.log(h) # 人脸中心点 face_center = cupy.array([(boxes[i, 0] + boxes[i, 2]) / 2, (boxes[i, 1] + boxes[i, 3]) / 2], dtype=cupy.float32) face_center_int = face_center.astype(cupy.int32) face_index[ i] = face_center_int[1] * output_res + face_center_int[ 0] # 人脸bbox在1/4特征图中的索引 face_off[ i] = face_center - face_center_int # 人脸box中心点整数化的偏差 face_mask[i] = 1 if face_keys[i, 0, 2] >= 0 and w * h > 2: # 太小的人脸忽略 for j in range(5): if 0 <= face_keys[i, j, 0] < output_res and \ 0 <= face_keys[i, j, 1] < output_res: face_key_off[i, 2 * j] = (face_keys[i, j, 0] - face_center_int[0]) / w face_key_off[i, 2 * j + 1] = (face_keys[i, j, 1] - face_center_int[1]) / h face_key_mask[i, 2 * j:2 * j + 2] = 1 draw_gaussian(heat_map[0], face_center_int, radius) return (input_image, heat_map, wh_gt, face_index, face_off, face_mask, face_key_off, face_key_mask)
def relu_cuda(X): cp.clip(X, 0, np.finfo(X.dtype).max, out=X) return X
def tanh(X): X = cp.clip(X, -350, 350) return (1 - cp.exp(-2 * X)) / (1 + cp.exp(-2 * X))
def sigmoid(X): X = cp.clip(X, -700, 700) return 1 / (1. + cp.exp(-X))
def g(x, y, z): return cupy.clip(x, y, z)
def eig_special_3d(S, full=False): """Eigensolution for symmetric real 3-by-3 matrices. Arguments: S: array-like A floating point array with shape ``(6, ...)`` containing structure tensor. Use float64 to avoid numerical errors. When using lower precision, ensure that the values of S are not very small/large. Pass cupy.ndarray to avoid copying S. full: bool, optional A flag indicating that all three eigenvalues should be returned. Returns: val: cupy.ndarray An array with shape ``(3, ...)`` containing sorted eigenvalues vec: cupy.ndarray An array with shape ``(3, ...)`` containing eigenvector corresponding to the smallest eigenvalue. If full, vec has shape ``(3, 3, ...)`` and contains all three eigenvectors. More: An analytic solution of eigenvalue problem for real symmetric matrix, using an affine transformation and a trigonometric solution of third order polynomial. See https://en.wikipedia.org/wiki/Eigenvalue_algorithm which refers to Smith's algorithm https://dl.acm.org/citation.cfm?id=366316. Authors: [email protected], 2019; [email protected], 2019-2020 """ S = np.asarray(S) # Check data type. Must be floating point. if not np.issubdtype(S.dtype, np.floating): raise ValueError('S must be floating point type.') # Flatten S. input_shape = S.shape S = S.reshape(6, -1) # Create v vector. v = np.array([[2 * np.pi / 3], [4 * np.pi / 3]], dtype=S.dtype) # Computing eigenvalues. # Allocate vec and val. We will use them for intermediate computations as well. if full: val = np.empty((3, ) + S.shape[1:], dtype=S.dtype) vec = np.empty((9, ) + S.shape[1:], dtype=S.dtype) tmp = np.empty((4, ) + S.shape[1:], dtype=S.dtype) B03 = val B36 = vec[:3] else: val = np.empty((3, ) + S.shape[1:], dtype=S.dtype) vec = np.empty((3, ) + S.shape[1:], dtype=S.dtype) tmp = np.empty((4, ) + S.shape[1:], dtype=S.dtype) B03 = val B36 = vec # Views for B. B0 = B03[0] B1 = B03[1] B2 = B03[2] B3 = B36[0] B4 = B36[1] B5 = B36[2] # Compute q, mean of diagonal. We need to use q multiple times later. # Using np.mean has precision issues. q = np.add(S[0], S[1], out=tmp[0]) q += S[2] q /= 3 # Compute S minus q. Insert it directly into B where it'll stay. Sq = np.subtract(S[:3], q, out=B03) # Compute s, off-diagonal elements. Store in part of B not yet used. s = np.sum(np.multiply(S[3:], S[3:], out=B36), axis=0, out=tmp[1]) s *= 2 # Compute p. p = np.sum(np.multiply(Sq, Sq, out=B36), axis=0, out=tmp[2]) del Sq # Last use of Sq. p += s p *= 1 / 6 np.sqrt(p, out=p) # Compute inverse p, while avoiding 0 division. # Reuse s allocation and delete s to ensure we don't efter it's been reused. p_inv = s del s non_zero_p_mask = p == 0 np.divide(1, p, out=p_inv) p_inv[non_zero_p_mask] = 0 # Compute B. First part is already filled. B03 *= p_inv np.multiply(S[3:], p_inv, out=B36) # Compute d, determinant of B. d = np.prod(B03, axis=0, out=tmp[3]) # Reuse allocation for p_inv and delete variable. d_tmp = p_inv del p_inv # Computation of d. np.multiply(B2, B3, d_tmp) d_tmp *= B3 d -= d_tmp np.multiply(B4, B4, out=d_tmp) d_tmp *= B1 d -= d_tmp np.prod(B36, axis=0, out=d_tmp) d_tmp *= 2 d += d_tmp np.multiply(B5, B5, out=d_tmp) d_tmp *= B0 d -= d_tmp d *= 0.5 # Ensure -1 <= d/2 <= 1. np.clip(d, -1, 1, out=d) # Compute phi. Beware that we reuse d variable! phi = d del d phi = np.arccos(phi, out=phi) phi /= 3 # Compute val, ordered eigenvalues. Resuing B allocation. del B03, B36, B0, B1, B2, B3, B4, B5 np.add(v, phi[np.newaxis], out=val[:2]) val[2] = phi np.cos(val, out=val) p *= 2 val *= p val += q # Remove all variable using tmp allocation. del q del p del phi del d_tmp # Computing eigenvectors -- either only one or all three. if full: l = val vec = vec.reshape(3, 3, -1) vec_tmp = tmp[:3] else: l = val[0] vec_tmp = tmp[2] # Compute vec. The tmp variable can be reused. # u = S[4] * S[5] - (S[2] - l) * S[3] u = np.subtract(S[2], l, out=vec[0]) np.multiply(u, S[3], out=u) u_tmp = np.multiply(S[4], S[5], out=tmp[3]) np.subtract(u_tmp, u, out=u) # Put values of u into vector 2 aswell. # v = S[3] * S[5] - (S[1] - l) * S[4] v = np.subtract(S[1], l, out=vec_tmp) np.multiply(v, S[4], out=v) v_tmp = np.multiply(S[3], S[5], out=tmp[3]) np.subtract(v_tmp, v, out=v) # w = S[3] * S[4] - (S[0] - l) * S[5] w = np.subtract(S[0], l, out=vec[2]) np.multiply(w, S[5], out=w) w_tmp = np.multiply(S[3], S[4], out=tmp[3]) np.subtract(w_tmp, w, out=w) vec[1] = u np.multiply(u, v, out=vec[0]) u = vec[1] np.multiply(u, w, out=vec[1]) np.multiply(v, w, out=vec[2]) # Remove u, v, w and l variables. del u del v del w del l # Normalizing -- depends on number of vectors. if full: # vec is [x1 x2 x3, y1 y2 y3, z1 z2 z3] l = np.sum(np.square(vec), axis=0, out=vec_tmp)[:, np.newaxis] vec = np.swapaxes(vec, 0, 1) else: # vec is [x1 y1 z1] = v1 l = np.sum(np.square(vec, out=tmp[:3]), axis=0, out=vec_tmp) cp.rsqrt(l, out=l) vec *= l return val.reshape(val.shape[:-1] + input_shape[1:]), vec.reshape(vec.shape[:-1] + input_shape[1:])
def ridge_regression( X_train, X_test, y_train, y_test, svd_solve=False, lambdas=[1e2], return_preds=True, return_model=False, clip_bounds=None, intercept=False, allow_linalg_warning_instances=False, ): """Train ridge regression model for a series of regularization parameters. Optionally clip the predictions to bounds. Used as the default solve_function argument for single_solve() and kfold_solve() below. Parameters ---------- X_{train,test} : :class:`numpy.ndarray` Features for training/test data (n_obs_{train,test} X n_ftrs 2darray). y_{train,test} : :class:`numpy.ndarray` Labels for training/test data (n_obs_{train,test} X n_outcomes 2darray). svd_solve : bool, optional If true, uses SVD to compute w^*, otherwise does matrix inverse for each lambda. lambdas : list of floats, optional Regularization values to sweep over. return_preds : bool, optional Whether to return predictions for training and test sets. return_model : bool, optional Whether to return the trained weights that define the ridge regression model. clip_bounds : array-like, optional If None, do not clip predictions. If not None, must be ann array of dimension ``n_outcomes X 2``. If any of the elements of the array are None, ignore that bound (e.g. if a row of the array is [None, 10], apply an upper bound of 10 but no lower bound). intercept : bool, optional Whether to add an unregulated intercept (or, equivalently, center the X and Y data). allow_linalg_warning_instances : bool, optional If False (default), track for which hyperparameters did ``scipy.linalg`` raise an ill-conditioned matrix error, which could lead to poor performance. This is used to discard these models in a cross-validation context. If True, allow these models to be included in the hyperparameter grid search. Note that these errors will not occur when using ``cupy.linalg`` (i.e. if a GPU is detected), so the default setting may give differing results across platforms. Returns ------- dict of :class:`numpy.ndarray` The results dictionary will always include the following key/value pairs: ``metrics_{test,train}`` : array of dimension n_outcomes X n_lambdas Each element is a dictionary of {Out-of,In}-sample model performance metrics for each lambda If ``return_preds``, the following arrays will be appended in order: ``y_pred_{test,train}`` : array of dimension n_outcomes X n_lambdas Each element is itself a 1darray of {Out-of,In}-sample predictions for each lambda. Each 1darray contains n_obs_{test,train} values if return_model, the following array will be appended: ``models`` : array of dimension n_outcomes X n_lambdas: Each element is itself a 1darray of model weights for each lambda. Each 1darray contains n_ftrs values """ # get dimensions needed to shape arrays n_ftrs, n_outcomes, n_obs_train, n_obs_test = get_dim_lengths( X_train, y_train, y_test) n_lambdas = len(lambdas) # center data if needed X_train, y_train, X_offset, y_offset, _ = _preprocess_data(X_train, y_train, intercept, normalize=False) # set up the data structures for reporting results results_dict = _initialize_results_arrays((n_outcomes, n_lambdas), return_preds, return_model) t1 = time.time() # send to GPU if available X_train = xp.asarray(X_train) y_train = xp.asarray(y_train) if DEBUG: if GPU: print( f"Time to transfer X_train and y_train to GPU: {time.time() - t1}" ) t1 = time.time() # precomputing large matrices to avoid redundant computation if svd_solve: # precompute the SVD U, s, Vh = linalg.svd(X_train, full_matrices=False) V = Vh.T UT_dot_y_train = U.T.dot(y_train) else: XtX = X_train.T.dot(X_train) XtY = X_train.T.dot(y_train) if DEBUG: t2 = time.time() print("Time to create XtX matrix:", t2 - t1) # iterate over the lambda regularization values training_time = 0 pred_time = 0 for lx, lambdan in enumerate(lambdas): if DEBUG: t3 = time.time() # train model if svd_solve: s_lambda = s / (s**2 + lambdan * xp.ones_like(s)) model = (V * s_lambda).dot(UT_dot_y_train) lambda_warning = None else: with warnings.catch_warnings(record=True) as w: # bind warnings to the value of w warnings.simplefilter("always") lambda_warning = False model = linalg.solve( XtX + lambdan * xp.eye(n_ftrs, dtype=np.float64), XtY, **linalg_solve_kwargs, ) # if there is a warning if len(w) > 1: for this_w in w: print(this_w.message) # more than one warning is bad raise Exception( "warning/exception other than LinAlgWarning") if len(w) > 0: # if it is a linalg warning if w[0].category == LinAlgWarning: print("linalg warning on lambda={0}: ".format(lambdan), end="") # linalg warning if not allow_linalg_warning_instances: print( "we will discard this model upon model selection" ) lambda_warning = True else: lambda_warning = None print( "we will allow this model upon model selection" ) else: raise Exception( "warning/exception other than LinAlgWarning") if DEBUG: t4 = time.time() training_time += t4 - t3 print(f"Training time for lambda {lambdan}: {t4 - t3}") ##################### # compute predictions ##################### # send to gpu if available X_test = xp.asarray(X_test) y_test = xp.asarray(y_test) y_offset = xp.asarray(y_offset) X_offset = xp.asarray(X_offset) if DEBUG: t5 = time.time() # train pred_train = X_train.dot(model) + y_offset pred_train = y_to_matrix(pred_train) # test pred_test = X_test.dot(model) - X_offset.dot(model) + y_offset pred_test = y_to_matrix(pred_test) # clip if needed if clip_bounds is not None: for ix, i in enumerate(clip_bounds): # only apply if both bounds aren't None for this outcome if not (i == None).all(): pred_train[:, ix] = xp.clip(pred_train[:, ix], *i) pred_test[:, ix] = xp.clip(pred_test[:, ix], *i) if DEBUG: t6 = time.time() pred_time += t6 - t5 # bring back to cpu if needed pred_train, pred_test = asnumpy(pred_train), asnumpy(pred_test) y_train, y_test, model = ( y_to_matrix(asnumpy(y_train)), y_to_matrix(asnumpy(y_test)), y_to_matrix(asnumpy(model)), ) # create tuple of lambda index to match argument structure # of _fill_results_arrays function hp_tuple = (lx, ) # Transpose model results so that n_outcomes is first dimension # so that _fill_results_array can handle it model = model.T # populate results dict with results from this lambda results_dict = _fill_results_arrays( y_train, y_test, pred_train, pred_test, model, hp_tuple, results_dict, hp_warning=lambda_warning, ) if DEBUG: print("Training time:", training_time) print("Prediction time:", pred_time) print("Total time:", time.time() - t1) return results_dict
def train(self): # clear grads self.q_func.zerograds() # pull tuples from memory pool batch_tuples = self.replay.pull(Config.batch_size) if not len(batch_tuples): return # stack inputs cur_x = [self.env.getX(t.state) for t in batch_tuples] next_x = [self.env.getX(t.next_state) for t in batch_tuples] # merge inputs into one array if Config.gpu: cur_x = [cupy.expand_dims(t, 0) for t in cur_x] cur_x = cupy.concatenate(cur_x, 0) next_x = [cupy.expand_dims(t, 0) for t in next_x] next_x = cupy.concatenate(next_x, 0) else: cur_x = np.stack(cur_x) next_x = np.stack(next_x) # get cur outputs cur_output = self.QFunc(self.q_func, cur_x) # get next outputs, NOT target next_output = self.QFunc(self.q_func, next_x) # choose next action for each output next_action = [ self.env.getBestAction(o.data, [t.next_state for t in batch_tuples]) for o in next_output # for each head in Model ] # get next outputs, target next_output = self.QFunc(self.target_q_func, next_x) # clear err of tuples for t in batch_tuples: t.err = 0. # store err count err_count_list = [0.] * len(batch_tuples) # compute grad's weights weights = np.array([t.P for t in batch_tuples], np.float32) if Config.gpu: weights = cuda.to_gpu(weights) if self.replay.getPoolSize(): weights *= self.replay.getPoolSize() weights = weights**-Config.beta weights /= weights.max() if Config.gpu: weights = cupy.expand_dims(weights, 1) else: weights = np.expand_dims(weights, 1) # update beta Config.beta = min(1, Config.beta + Config.beta_add) # compute grad for each head for k in range(Config.K): if Config.gpu: cur_output[k].grad = cupy.zeros_like(cur_output[k].data) else: cur_output[k].grad = np.zeros_like(cur_output[k].data) # compute grad from each tuples for i in range(len(batch_tuples)): if batch_tuples[i].mask[k]: cur_action_value = \ cur_output[k].data[i][batch_tuples[i].action].tolist() reward = batch_tuples[i].reward next_action_value = \ next_output[k].data[i][next_action[k][i]].tolist() target_value = reward # if not empty position, not terminal state if batch_tuples[i].next_state.in_game: target_value += Config.gamma * next_action_value loss = cur_action_value - target_value cur_output[k].grad[i][batch_tuples[i].action] = 2 * loss # count err if cur_action_value: batch_tuples[i].err += abs(loss / cur_action_value) err_count_list[i] += 1 # multiply weights with grad and clip if Config.gpu: cur_output[k].grad = cupy.multiply(cur_output[k].grad, weights) cur_output[k].grad = cupy.clip(cur_output[k].grad, -1, 1) else: cur_output[k].grad = np.multiply(cur_output[k].grad, weights) cur_output[k].grad = np.clip(cur_output[k].grad, -1, 1) # backward cur_output[k].backward() # adjust grads of shared for param in self.q_func.shared.params(): param.grad /= Config.K # update params self.optimizer.update() # avg err for i in range(len(batch_tuples)): if err_count_list[i] > 0: batch_tuples[i].err /= err_count_list[i] self.replay.merge(Config.alpha) return np.mean([t.err for t in batch_tuples])
def main(): # Main function to collect configuration file and run the script print(f'GPU REPLICAS: {strategy.num_replicas_in_sync}') t0 = time.time() # Initialize dataframe with data details df_data = pd.read_csv(config.PREP_DATA_FILE) # create directory to store dataset os.system(f'mkdir -p {config.PREP_TRAIN_OUTDIR} {config.PREP_VAL_OUTDIR}') # Iterate over each training raster from df_data for ind in df_data.index: # Specify data files to read and process fimg = os.path.join(config.PREP_DATA_INPDIR, df_data['data'][ind]) fmask = os.path.join(config.PREP_LABELS_INPDIR, df_data['label'][ind]) print(f'Processing file #{ind+1}: ', df_data['data'][ind]) # Read imagery from disk img = xr.open_rasterio(fimg, chunks=config.DASK_SIZE).load() mask = xr.open_rasterio(fmask, chunks=config.DASK_SIZE).load() config.NODATA_VAL = img.attrs['nodatavals'][0] # Map to GPU memory img = img.map_blocks(cp.asarray) mask = mask.map_blocks(cp.asarray).squeeze() print(f'Image and mask shape: {img.shape} {mask.shape}') # ------------------------------------------------------------- # Unique processing for this project - Start # Might not be necessary for other projects # ------------------------------------------------------------- # need to merge a class with another class? # mask[mask == 3] = 1 # merge thin clouds into clouds class # get only necessary channels for training img = img[:len(config.PREP_BANDS_OUTPUT), :, :] # accounting for contaminated pixels, TOA values # remove lower and higher bound values img = cp.clip(img, 0, 10000) # adding indices if required, only if data does not come with # dedicated indices and need to be calculated on the fly. # Examples you can use: # fdi = \ # indices.fdi(img, BANDS_INPUT, factor=INDICES_FACTOR, vtype='int16') # si = \ # indices.si(img, BANDS_INPUT, factor=INDICES_FACTOR, vtype='int16') # ndwi = \ # indices.ndwi(img, BANDS_INPUT, factor=INDICES_FACTOR, vtype='int16') # concatenate all indices # img = cp.concatenate((img, fdi, si, ndwi), axis=0) # print("Image and mask shape after indices: ", img.shape, mask.shape) # ------------------------------------------------------------- # Unique processing for this project - End # ------------------------------------------------------------- # Generate training data gen_data_npz(fimg=df_data['data'][ind], img=img, mask=mask, config=config, ntiles=df_data['ntiles_train'][ind], save_dir=config.PREP_TRAIN_OUTDIR) # Generate validation data gen_data_npz(fimg=df_data['data'][ind], img=img, mask=mask, config=config, ntiles=df_data['ntiles_val'][ind], save_dir=config.PREP_VAL_OUTDIR) print(f'Execution time: {time.time() - t0}')
def random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs): """ Function to add random noise of various types to a floating-point image. Parameters ---------- image : ndarray Input image data. Will be converted to float. mode : str, optional One of the following strings, selecting the type of noise to add: - 'gaussian' Gaussian-distributed additive noise. - 'localvar' Gaussian-distributed additive noise, with specified local variance at each point of `image`. - 'poisson' Poisson-distributed noise generated from the data. - 'salt' Replaces random pixels with 1. - 'pepper' Replaces random pixels with 0 (for unsigned images) or -1 (for signed images). - 's&p' Replaces random pixels with either 1 or `low_val`, where `low_val` is 0 for unsigned images or -1 for signed images. - 'speckle' Multiplicative noise using out = image + n*image, where n is Gaussian noise with specified mean & variance. seed : int, optional If provided, this will set the random seed before generating noise, for valid pseudo-random comparisons. clip : bool, optional If True (default), the output will be clipped after noise applied for modes `'speckle'`, `'poisson'`, and `'gaussian'`. This is needed to maintain the proper image data range. If False, clipping is not applied, and the output may extend beyond the range [-1, 1]. mean : float, optional Mean of random distribution. Used in 'gaussian' and 'speckle'. Default : 0. var : float, optional Variance of random distribution. Used in 'gaussian' and 'speckle'. Note: variance = (standard deviation) ** 2. Default : 0.01 local_vars : ndarray, optional Array of positive floats, same shape as `image`, defining the local variance at every image point. Used in 'localvar'. amount : float, optional Proportion of image pixels to replace with noise on range [0, 1]. Used in 'salt', 'pepper', and 'salt & pepper'. Default : 0.05 salt_vs_pepper : float, optional Proportion of salt vs. pepper noise for 's&p' on range [0, 1]. Higher values represent more salt. Default : 0.5 (equal amounts) Returns ------- out : ndarray Output floating-point image data on range [0, 1] or [-1, 1] if the input `image` was unsigned or signed, respectively. Notes ----- Speckle, Poisson, Localvar, and Gaussian noise may generate noise outside the valid image range. The default is to clip (not alias) these values, but they may be preserved by setting `clip=False`. Note that in this case the output may contain values outside the ranges [0, 1] or [-1, 1]. Use this option with care. Because of the prevalence of exclusively positive floating-point images in intermediate calculations, it is not possible to intuit if an input is signed based on dtype alone. Instead, negative values are explicitly searched for. Only if found does this function assume signed input. Unexpected results only occur in rare, poorly exposes cases (e.g. if all values are above 50 percent gray in a signed `image`). In this event, manually scaling the input to the positive domain will solve the problem. The Poisson distribution is only defined for positive integers. To apply this noise type, the number of unique values in the image is found and the next round power of two is used to scale up the floating-point result, after which it is scaled back down to the floating-point image range. To generate Poisson noise against a signed image, the signed image is temporarily converted to an unsigned image in the floating point domain, Poisson noise is generated, then it is returned to the original range. """ mode = mode.lower() # Detect if a signed image was input if image.min() < 0: low_clip = -1.0 else: low_clip = 0.0 image = img_as_float(image) if seed is not None: cp.random.seed(seed=seed) allowedtypes = { 'gaussian': 'gaussian_values', 'localvar': 'localvar_values', 'poisson': 'poisson_values', 'salt': 'sp_values', 'pepper': 'sp_values', 's&p': 's&p_values', 'speckle': 'gaussian_values' } kwdefaults = { 'mean': 0.0, 'var': 0.01, 'amount': 0.05, 'salt_vs_pepper': 0.5, 'local_vars': cp.zeros_like(image) + 0.01 } allowedkwargs = { 'gaussian_values': ['mean', 'var'], 'localvar_values': ['local_vars'], 'sp_values': ['amount'], 's&p_values': ['amount', 'salt_vs_pepper'], 'poisson_values': [] } for key in kwargs: if key not in allowedkwargs[allowedtypes[mode]]: raise ValueError('%s keyword not in allowed keywords %s' % (key, allowedkwargs[allowedtypes[mode]])) # Set kwarg defaults for kw in allowedkwargs[allowedtypes[mode]]: kwargs.setdefault(kw, kwdefaults[kw]) if mode == 'gaussian': noise = cp.random.normal(kwargs['mean'], kwargs['var']**0.5, image.shape) out = image + noise elif mode == 'localvar': # Ensure local variance input is correct if (kwargs['local_vars'] <= 0).any(): raise ValueError('All values of `local_vars` must be > 0.') # Safe shortcut usage broadcasts kwargs['local_vars'] as a ufunc # CuPy Backend: Must supply size argument to get around a CuPy bug # https://github.com/cupy/cupy/pull/4457 out = image + cp.random.normal(0, kwargs["local_vars"]**0.5, kwargs["local_vars"].shape) elif mode == 'poisson': # Determine unique values in image & calculate the next power of two vals = len(cp.unique(image)) vals = 2**cp.ceil(cp.log2(vals)) # Ensure image is exclusively positive if low_clip == -1.0: old_max = image.max() image = (image + 1.0) / (old_max + 1.0) # Generating noise for each unique value in image. out = cp.random.poisson(image * vals) / float(vals) # Return image to original range if input was signed if low_clip == -1.0: out = out * (old_max + 1.0) - 1.0 elif mode == 'salt': # Re-call function with mode='s&p' and p=1 (all salt noise) out = random_noise(image, mode='s&p', seed=seed, amount=kwargs['amount'], salt_vs_pepper=1.) elif mode == 'pepper': # Re-call function with mode='s&p' and p=1 (all pepper noise) out = random_noise(image, mode='s&p', seed=seed, amount=kwargs['amount'], salt_vs_pepper=0.) elif mode == 's&p': out = image.copy() p = kwargs['amount'] q = kwargs['salt_vs_pepper'] flipped = cp.random.choice([True, False], size=image.shape, p=[p, 1 - p]) salted = cp.random.choice([True, False], size=image.shape, p=[q, 1 - q]) peppered = ~salted out[flipped & salted] = 1 out[flipped & peppered] = low_clip elif mode == 'speckle': noise = cp.random.normal(kwargs['mean'], kwargs['var']**0.5, image.shape) out = image + image * noise # Clip back to original range, if necessary if clip: out = cp.clip(out, low_clip, 1.0) return out
def reconstruct_alt(imgs, discs, hres_size, row, n_iters=1, o_f_init=None, del_1=1000, del_2=1, round_values=True, plot_per_frame=False, show_interval=None, subtract_bg=False, out_path=None): """The main reconstruction algorithm. Adapted from Tian et. al.""" # Put input images on GPU, estimate background noise imgs = [cp.array(img) for img in imgs] bgs = get_bg(imgs) if subtract_bg else cp.zeros(len(imgs)) IMAGESIZE = imgs[0].shape[0] CUTOFF_FREQ_px = get_cutoff(row) FRAMES = len(imgs) orig = IMAGESIZE // 2 - 1 # Low-res origin lres_size = (IMAGESIZE, IMAGESIZE) m1, n1 = lres_size m, n = hres_size losses = [] # Reconstruction Loss convs = [] # Inverse Convergence index # Initial high-res guess if lres_size == hres_size: # Initialize with ones # Use old algorithm F = lambda x: cp.fft.fftshift(cp.fft.fft2(x)) Ft = lambda x: cp.fft.ifft2(cp.fft.ifftshift(x)) o = cp.ones(hres_size) o_f = F(o) elif o_f_init is not None: # Initialize with given initialization F = lambda x: cp.fft.fftshift(cp.fft.fft2(cp.fft.ifftshift(x))) Ft = lambda x: cp.fft.fftshift(cp.fft.ifft2(cp.fft.ifftshift(x))) o = cp.zeros_like(o_f_init) o_f = o_f_init else: # Intialize with resized first frame from imgs F = lambda x: cp.fft.fftshift(cp.fft.fft2(cp.fft.ifftshift(x))) Ft = lambda x: cp.fft.fftshift(cp.fft.ifft2(cp.fft.ifftshift(x))) o = cp.sqrt( cp.array(cv2.resize(cp.asnumpy(imgs[0] - bgs[0]), hres_size))) o_f = Ft(o) # Pupil Function p = cp.zeros(lres_size) p = cp.array(cv2.circle(cp.asnumpy(p), (orig, orig), CUTOFF_FREQ_px, 1, -1)) ctf = p.copy() # Ideal Pupil, for filtering later on # Main Loop log = tqdm( total=n_iters, desc=f'Starting...', bar_format= '{percentage:3.0f}% [{elapsed}<{remaining} ({rate_inv_fmt})]{bar}{desc}', leave=False, ascii=True) for j in range(n_iters): conv = [] # Convergence Index for i in range(FRAMES): if discs[i] == 0: # Empty frame continue # Get k0x, k0y and hence, shifting values k0x, k0y = discs[i] # Construct auxillary functions for the set of LEDs (= 1, here) if hres_size == lres_size: shift_x, shift_y = [ -round(k0x - orig), -round(k0y - orig) ] if round_values else [-(k0x - orig), -(k0y - orig)] if not round_values: o_f_i = FourierShift2D(o_f, [shift_x, shift_y]) # O_i(k - k_m) else: o_f_i = cp.roll(o_f, int(shift_y), axis=0) o_f_i = cp.roll(o_f_i, int(shift_x), axis=1) yl, xl = 0, 0 # To reduce code later on else: # Output size larger than individual frames _orig = hres_size[0] // 2 - 1 del_x, del_y = k0x - orig, k0y - orig x, y = round(_orig - del_x), round(_orig - del_y) yl = int(y - m1 // 2) xl = int(x - n1 // 2) assert xl > 0 and yl > 0, 'Both should be > 0' o_f_i = o_f[yl:yl + n1, xl:xl + m1].copy() psi_k = o_f_i * p * ctf #DEBUG: REPLACE * ctf with * p # Plot outputs after each frame, for debugging if plot_per_frame: o_i = Ft(o_f_i * p) plt.figure(figsize=(10, 2)) plt.subplot(161) plt.imshow(cp.asnumpy(correct(abs(o_i)))) plt.title(f'$I_{{l}}({i})$') opts() #DEBUG plt.subplot(162) plt.imshow( cp.asnumpy( cv2.convertScaleAbs( cp.asnumpy(20 * cp.log(1 + abs(o_f_i * p)))))) plt.title(f'$S_{{l}}({i})$') opts() #DEBUG # Impose intensity constraint and update auxillary function psi_r = F(psi_k) #DEBUG: CHANGE BACK TO F # Low-res estimate obtained from our reconstruction I_l = abs(psi_r) if lres_size != hres_size else abs(psi_r) # Subtract background noise and clip values to avoid NaN I_hat = cp.clip(imgs[i] - bgs[i], a_min=0) phi_r = cp.sqrt(I_hat / (cp.abs(psi_r)**2)) * psi_r phi_k = Ft(phi_r) #DEBUG: CHANGE BACK TO Ft # Update object and pupil estimates if hres_size == lres_size: if not round_values: p_i = FourierShift2D(p, [-shift_x, -shift_y]) # P_i(k+k_m) else: p_i = cp.roll(p, int(-shift_y), axis=0) p_i = cp.roll(p_i, int(-shift_x), axis=1) if not round_values: phi_k_i = FourierShift2D( phi_k, [-shift_x, -shift_y]) # Phi_m_i(k+k_m) else: phi_k_i = cp.roll(phi_k, int(-shift_y), axis=0) phi_k_i = cp.roll(phi_k_i, int(-shift_x), axis=1) else: # Output size larger than individual frames p_i = p.copy() phi_k_i = phi_k.copy() ## O_{i+1}(k) temp = o_f[yl:yl + n1, xl:xl + m1].copy() + ( cp.abs(p_i) * cp.conj(p_i) * (phi_k_i - o_f[yl:yl + n1, xl:xl + m1].copy() * p_i) ) / \ ( cp.abs(p).max() * (cp.abs(p_i) ** 2 + del_1) ) ## P_{i+1}(k) p = p + ( cp.abs(o_f_i) * cp.conj(o_f_i) * (phi_k - o_f_i * p) ) / \ ( cp.abs(o_f[yl:yl + n1, xl:xl + m1].copy()).max() * (cp.abs(o_f_i) ** 2 + del_2) ) o_f[yl:yl + n1, xl:xl + m1] = temp.copy() ###### Using F here instead of Ft to get upright image o = F(o_f) if lres_size != hres_size else Ft(o_f) ###### if plot_per_frame: plt.subplot(163) plt.imshow(cp.asnumpy(cp.mod(ctf * cp.angle(p), 2 * cp.pi))) plt.title(f'P({i})') opts() #DEBUG plt.subplot(164) plt.imshow(cp.asnumpy(correct(abs(o)))) plt.title(f'$I_{{h}}({i})$') opts() #DEBUG plt.subplot(165) plt.imshow(cp.asnumpy(correct(cp.angle(o)))) plt.title(f'$\\theta(I_{{h}}({i}))$') opts() #DEBUG plt.subplot(166) plt.imshow(cp.asnumpy(show(cp.asnumpy(o_f)))) plt.title(f'$S_{{h}}({i})$') opts() plt.show() #DEBUG c = inv_conv_idx(I_l, imgs[i]) conv.append(c) if not plot_per_frame and (show_interval is not None and j % show_interval == 0): o_i = Ft(o_f_i * p) #DEBUG plt.figure(figsize=(10, 2)) plt.subplot(161) plt.imshow(cp.asnumpy(correct(abs(o_i)))) plt.title(f'$I_{{l}}({i})$') opts() #DEBUG plt.subplot(162) plt.imshow( cp.asnumpy( cv2.convertScaleAbs( cp.asnumpy(20 * cp.log(1 + abs(o_f_i * p)))))) plt.title(f'$S_{{l}}({i})$') opts() #DEBUG plt.subplot(163) plt.imshow(cp.asnumpy(cp.mod(ctf * cp.angle(p), 2 * cp.pi))) plt.title(f'P({i})') opts() #DEBUG plt.subplot(164) plt.imshow(cp.asnumpy(correct(abs(o)))) plt.title(f'$I_{{h}}({i})$') opts() #DEBUG plt.subplot(165) plt.imshow(cp.asnumpy(correct(cp.angle(o)))) plt.title(f'$\\theta(I_{{h}}({i}))$') opts() #DEBUG plt.subplot(166) plt.imshow( cp.asnumpy( cv2.convertScaleAbs(cp.asnumpy(20 * cp.log(1 + abs(o_f)))))) plt.title(f'$S_{{h}}({i})$') opts() plt.show() #DEBUG loss = metric_norm(imgs, o_f_i, p) losses.append(loss) conv = float(sum(conv) / len(conv)) convs.append(conv) log.set_description_str( f'[Iteration {j + 1}] Convergence Loss: {cp.asnumpy(conv):e}') log.update(1) scale = 7 plt.figure(figsize=(3 * scale, 4 * scale)) plt.subplot(421) plt.plot(cp.asnumpy(cp.arange(len(losses))), cp.asnumpy(cp.clip(cp.array(losses), a_min=None, a_max=1e4)), 'b-') plt.title('Loss Curve') plt.ylabel('Loss Value') plt.xlabel('Iteration') plt.subplot(422) plt.plot(cp.asnumpy(cp.arange(len(convs))), cp.asnumpy(cp.clip(cp.array(convs), a_min=None, a_max=1e14)), 'b-') plt.title('Convergence Index Curve') plt.ylabel('Convergence Index') plt.xlabel('Iteration') amp = cp.array(cv2.resize( read_tiff(row.AMPLITUDE.values[0])[0], hres_size)) phase = cp.array(cv2.resize(read_tiff(row.PHASE.values[0])[0], hres_size)) plt.subplot(434) plt.title(f'amplitude (Scaled up from {lres_size})') plt.imshow(cp.asnumpy(to_uint8(amp))) opts() plt.subplot(435) plt.title(f'phase (Scaled up from {lres_size})') plt.imshow(cp.asnumpy(to_uint8(phase))) plt.subplot(436) rec = abs(cp.sqrt(amp) * cp.exp(1j * phase)) plt.title(f'Ground Truth (Scaled up from {lres_size})') plt.imshow(cp.asnumpy(to_uint8(rec))) plt.subplot(437) plt.title('Reconstruction Amplitude') amp = abs(o) if lres_size == hres_size: amp = correct(amp) plt.imshow(cp.asnumpy(to_uint8((amp)))) plt.subplot(438) plt.title('Reconstruction Phase') phase = cp.angle(o) if lres_size == hres_size: phase = correct(phase) plt.imshow(cp.asnumpy(to_uint8(phase))) plt.subplot(439) plt.title('Reconstructed Image') rec = abs(cp.sqrt(amp) * cp.exp(1j * phase)) plt.imshow(cp.asnumpy(to_uint8(rec))) plt.subplot(427) plt.title(f'Recovered Pupil') p_show = cp.mod(ctf * cp.angle(p), 2 * cp.pi) p_show = (p_show / p_show.max() * 255).astype(np.uint8) plt.imshow(cp.asnumpy(p_show), cmap='nipy_spectral') plt.subplot(428) plt.title(f'Raw frames\' mean (Scaled up from {lres_size})') plt.imshow(cv2.resize(cp.asnumpy(cp.array(imgs).mean(axis=0)), hres_size)) if out_path is None: plt.show() else: plt.savefig(out_path, bbox_inches='tight') plt.close('all') # Ignore early noise and print where the error is lowest if n_iters > 10: it = cp.argmin(cp.array(convs[10:])) + 11 if out_path is not None: print(f'Convergence index lowest at {it}th iteration.') else: it = cp.argmin(cp.array(convs)) + 1 if out_path is not None: print(f'Convergence index lowest at {it}th iteration.') if lres_size == hres_size: o = correct(o) return o, p, it
def clip(tensor, a_min=None, a_max=None, inplace=False): return cp.clip(tensor, a_min, a_max)
def _convert(image, dtype, force_copy=False, uniform=False): """ Convert an image to the requested data-type. Warnings are issued in case of precision loss, or when negative values are clipped during conversion to unsigned integer types (sign loss). Floating point values are expected to be normalized and will be clipped to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or signed integers respectively. Numbers are not shifted to the negative side when converting from unsigned to signed integer types. Negative values will be clipped when converting to unsigned integers. Parameters ---------- image : ndarray Input image. dtype : dtype Target data-type. force_copy : bool, optional Force a copy of the data, irrespective of its current dtype. uniform : bool, optional Uniformly quantize the floating point range to the integer range. By default (uniform=False) floating point values are scaled and rounded to the nearest integers, which minimizes back and forth conversion errors. .. versionchanged :: 0.15 ``_convert`` no longer warns about possible precision or sign information loss. See discussions on these warnings at: https://github.com/scikit-image/scikit-image/issues/2602 https://github.com/scikit-image/scikit-image/issues/543#issuecomment-208202228 https://github.com/scikit-image/scikit-image/pull/3575 References ---------- .. [1] DirectX data conversion rules. https://msdn.microsoft.com/en-us/library/windows/desktop/dd607323%28v=vs.85%29.aspx .. [2] Data Conversions. In "OpenGL ES 2.0 Specification v2.0.25", pp 7-8. Khronos Group, 2010. .. [3] Proper treatment of pixels as integers. A.W. Paeth. In "Graphics Gems I", pp 249-256. Morgan Kaufmann, 1990. .. [4] Dirty Pixels. J. Blinn. In "Jim Blinn's corner: Dirty Pixels", pp 47-57. Morgan Kaufmann, 1998. """ dtypeobj_in = image.dtype if dtype is cp.floating: dtypeobj_out = cp.dtype("float64") else: dtypeobj_out = cp.dtype(dtype) dtype_in = dtypeobj_in.type dtype_out = dtypeobj_out.type kind_in = dtypeobj_in.kind kind_out = dtypeobj_out.kind itemsize_in = dtypeobj_in.itemsize itemsize_out = dtypeobj_out.itemsize # Below, we do an `issubdtype` check. Its purpose is to find out # whether we can get away without doing any image conversion. This happens # when: # # - the output and input dtypes are the same or # - when the output is specified as a type, and the input dtype # is a subclass of that type (e.g. `cp.floating` will allow # `float32` and `float64` arrays through) if cp.issubdtype(dtype_in, cp.obj2sctype(dtype)): if force_copy: image = image.copy() return image if not (dtype_in in _supported_types and dtype_out in _supported_types): raise ValueError("Can not convert from {} to {}.".format( dtypeobj_in, dtypeobj_out)) if kind_in in 'ui': imin_in = cp.iinfo(dtype_in).min imax_in = cp.iinfo(dtype_in).max if kind_out in 'ui': imin_out = cp.iinfo(dtype_out).min imax_out = cp.iinfo(dtype_out).max # any -> binary if kind_out == 'b': return image > dtype_in(dtype_range[dtype_in][1] / 2) # binary -> any if kind_in == 'b': result = image.astype(dtype_out) if kind_out != 'f': result *= dtype_out(dtype_range[dtype_out][1]) return result # float -> any if kind_in == 'f': if kind_out == 'f': # float -> float return image.astype(dtype_out) if cp.min(image) < -1.0 or cp.max(image) > 1.0: raise ValueError("Images of type float must be between -1 and 1.") # floating point -> integer # use float type that can represent output integer type computation_type = _dtype_itemsize(itemsize_out, dtype_in, cp.float32, cp.float64) if not uniform: if kind_out == 'u': image_out = cp.multiply(image, imax_out, dtype=computation_type) else: image_out = cp.multiply(image, (imax_out - imin_out) / 2, dtype=computation_type) image_out -= 1.0 / 2.0 cp.rint(image_out, out=image_out) cp.clip(image_out, imin_out, imax_out, out=image_out) elif kind_out == 'u': image_out = cp.multiply(image, imax_out + 1, dtype=computation_type) cp.clip(image_out, 0, imax_out, out=image_out) else: image_out = cp.multiply(image, (imax_out - imin_out + 1.0) / 2.0, dtype=computation_type) cp.floor(image_out, out=image_out) cp.clip(image_out, imin_out, imax_out, out=image_out) return image_out.astype(dtype_out) # signed/unsigned int -> float if kind_out == 'f': # use float type that can exactly represent input integers computation_type = _dtype_itemsize(itemsize_in, dtype_out, cp.float32, cp.float64) if kind_in == 'u': # using cp.divide or cp.multiply doesn't copy the data # until the computation time image = cp.multiply(image, 1. / imax_in, dtype=computation_type) # DirectX uses this conversion also for signed ints # if imin_in: # cp.maximum(image, -1.0, out=image) else: image = cp.add(image, 0.5, dtype=computation_type) image *= 2 / (imax_in - imin_in) return image.astype(dtype_out, copy=False) # unsigned int -> signed/unsigned int if kind_in == 'u': if kind_out == 'i': # unsigned int -> signed int image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1) return image.view(dtype_out) else: # unsigned int -> unsigned int return _scale(image, 8 * itemsize_in, 8 * itemsize_out) # signed int -> unsigned int if kind_out == 'u': image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out) result = cp.empty(image.shape, dtype_out) cp.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe') return result # signed int -> signed int if itemsize_in > itemsize_out: return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1) image = image.astype(_dtype_bits('i', itemsize_out * 8)) image -= imin_in image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False) image += imin_out return image.astype(dtype_out)
def sigmoid(x): x = np.clip(x, -500, 500) return 1. / (1 + np.exp(-x))
def f(self, S, y): eps = 1e-18 y_hot = one_hot_encode(y, self.n_c) n = y.shape[0] loss = - cp.sum(y_hot * cp.log(cp.clip(S, eps, 1.))) / n return loss
def clamp(self, _min: float, _max: float) -> Vec3: return Vec3(*cp.clip(self.e, _min, _max))
import numpy as np import cupy as cp import pytest from skimage import data # TODO: remove need for skimage import from cupyimg.skimage.metrics import structural_similarity from cupyimg.skimage._shared._warnings import expected_warnings # need exact NumPy seed here. (CuPy as it won't be identical) np.random.seed(5) cam = cp.asarray(data.camera()) sigma = 20.0 noise = cp.asarray(sigma * np.random.randn(*cam.shape)) cam_noisy = cp.clip(cam + noise, 0, 255) cam_noisy = cam_noisy.astype(cam.dtype) cp.random.seed(1234) assert_equal = cp.testing.assert_array_equal assert_almost_equal = cp.testing.assert_array_almost_equal assert_array_almost_equal = cp.testing.assert_array_almost_equal def test_structural_similarity_patch_range(): N = 51 rstate = cp.random.RandomState(1234) X = (rstate.rand(N, N) * 255).astype(cp.uint8) Y = (rstate.rand(N, N) * 255).astype(cp.uint8) # grlee77: increase value from 0.1 to 0.15
def clip(tensor, a_min=None, a_max=None): return cp.clip(tensor, a_min, a_max)
def fn(): with cupy.cuda.Device(node.device_id): cupy.clip(inp, a_min=min_v, a_max=max_v, out=output)
def qmf(hk): """ Return high-pass qmf filter from low-pass Parameters ---------- hk : array_like Coefficients of high-pass filter. """ N = len(hk) - 1 asgn = [{0: 1, 1: -1}[k % 2] for k in range(N + 1)] return hk[::-1] * cp.array(asgn) """ Return (x, phi, psi) at dyadic points ``K/2**J`` from filter coefficients. Parameters ---------- hk : array_like Coefficients of low-pass filter. J : int, optional Values will be computed at grid points ``K/2**J``. Default is 7. Returns ------- x : ndarray The dyadic points ``K/2**J`` for ``K=0...N * (2**J)-1`` where ``len(hk) = len(gk) = N+1``. phi : ndarray The scaling function ``phi(x)`` at `x`: ``phi(x) = sum(hk * phi(2x-k))``, where k is from 0 to N. psi : ndarray, optional The wavelet function ``psi(x)`` at `x`: ``phi(x) = sum(gk * phi(2x-k))``, where k is from 0 to N. `psi` is only returned if `gk` is not None. Notes ----- The algorithm uses the vector cascade algorithm described by Strang and Nguyen in "Wavelets and Filter Banks". It builds a dictionary of values and slices for quick reuse. Then inserts vectors into final vector at the end. """ N = len(hk) - 1 if (J > 30 - cp.log2(N + 1)): raise ValueError("Too many levels.") if (J < 1): raise ValueError("Too few levels.") # construct matrices needed nn, kk = cp.ogrid[:N, :N] s2 = cp.sqrt(2) # append a zero so that take works thk = cp.r_[hk, 0] gk = qmf(hk) tgk = cp.r_[gk, 0] indx1 = cp.clip(2 * nn - kk, -1, N + 1) indx2 = cp.clip(2 * nn - kk + 1, -1, N + 1) m = cp.zeros((2, 2, N, N), 'd') m[0, 0] = cp.take(thk, indx1, 0) m[0, 1] = cp.take(thk, indx2, 0) m[1, 0] = cp.take(tgk, indx1, 0) m[1, 1] = cp.take(tgk, indx2, 0) m *= s2 # construct the grid of points x = cp.arange(0, N * (1 << J), dtype=float) / (1 << J) phi = 0 * x psi = 0 * x # find phi0, and phi1 lam, v = eig(m[0, 0]) ind = cp.argmin(cp.absolute(lam - 1)) # a dictionary with a binary representation of the # evaluation points x < 1 -- i.e. position is 0.xxxx v = cp.real(v[:, ind]) # need scaling function to integrate to 1 so find # eigenvector normalized to sum(v,axis=0)=1 sm = cp.sum(v) if sm < 0: # need scaling function to integrate to 1 v = -v sm = -sm bitdic = {'0': v / sm} bitdic['1'] = cp.dot(m[0, 1], bitdic['0']) step = 1 << J phi[::step] = bitdic['0'] phi[(1 << (J - 1))::step] = bitdic['1'] psi[::step] = cp.dot(m[1, 0], bitdic['0']) psi[(1 << (J - 1))::step] = cp.dot(m[1, 1], bitdic['0']) # descend down the levels inserting more and more values # into bitdic -- store the values in the correct location once we # have computed them -- stored in the dictionary # for quicker use later. prevkeys = ['1'] for level in range(2, J + 1): newkeys = ['%d%s' % (xx, yy) for xx in [0, 1] for yy in prevkeys] fac = 1 << (J - level) for key in newkeys: # convert key to number num = 0 for pos in range(level): if key[pos] == '1': num += (1 << (level - 1 - pos)) pastphi = bitdic[key[1:]] ii = int(key[0]) temp = cp.dot(m[0, ii], pastphi) bitdic[key] = temp phi[num * fac::step] = temp psi[num * fac::step] = cp.dot(m[1, ii], pastphi) prevkeys = newkeys return x, phi, psi
def train(self): # clear grads self.q_func.zerograds() # pull tuples from memory pool batch_tuples = self.replay.pull(Config.batch_size) if not len(batch_tuples): return # stack inputs cur_x = [self.env.getX(t.state) for t in batch_tuples] next_x = [self.env.getX(t.next_state) for t in batch_tuples] # merge inputs into one array if Config.gpu: cur_x = [cupy.expand_dims(t, 0) for t in cur_x] cur_x = cupy.concatenate(cur_x, 0) next_x = [cupy.expand_dims(t, 0) for t in next_x] next_x = cupy.concatenate(next_x, 0) else: cur_x = np.stack(cur_x) next_x = np.stack(next_x) # get cur outputs cur_output = self.QFunc(self.q_func, cur_x) # get next outputs, NOT target next_output = self.QFunc(self.q_func, next_x) # choose next action for each output next_action = [ self.env.getBestAction( o.data, [t.next_state for t in batch_tuples] ) for o in next_output # for each head in Model ] # get next outputs, target next_output = self.QFunc(self.target_q_func, next_x) # clear err of tuples for t in batch_tuples: t.err = 0. # store err count err_count_list = [0.] * len(batch_tuples) # compute grad's weights weights = np.array([t.P for t in batch_tuples], np.float32) if Config.gpu: weights = cuda.to_gpu(weights) if self.replay.getPoolSize(): weights *= self.replay.getPoolSize() weights = weights ** -Config.beta weights /= weights.max() if Config.gpu: weights = cupy.expand_dims(weights, 1) else: weights = np.expand_dims(weights, 1) # update beta Config.beta = min(1, Config.beta + Config.beta_add) # compute grad for each head for k in range(Config.K): if Config.gpu: cur_output[k].grad = cupy.zeros_like(cur_output[k].data) else: cur_output[k].grad = np.zeros_like(cur_output[k].data) # compute grad from each tuples for i in range(len(batch_tuples)): if batch_tuples[i].mask[k]: cur_action_value = \ cur_output[k].data[i][batch_tuples[i].action].tolist() reward = batch_tuples[i].reward next_action_value = \ next_output[k].data[i][next_action[k][i]].tolist() target_value = reward # if not empty position, not terminal state if batch_tuples[i].next_state.in_game: target_value += Config.gamma * next_action_value loss = cur_action_value - target_value cur_output[k].grad[i][batch_tuples[i].action] = 2 * loss # count err if cur_action_value: batch_tuples[i].err += abs(loss / cur_action_value) err_count_list[i] += 1 # multiply weights with grad and clip if Config.gpu: cur_output[k].grad = cupy.multiply( cur_output[k].grad, weights) cur_output[k].grad = cupy.clip(cur_output[k].grad, -1, 1) else: cur_output[k].grad = np.multiply( cur_output[k].grad, weights) cur_output[k].grad = np.clip(cur_output[k].grad, -1, 1) # backward cur_output[k].backward() # adjust grads of shared for param in self.q_func.shared.params(): param.grad /= Config.K # update params self.optimizer.update() # avg err for i in range(len(batch_tuples)): if err_count_list[i] > 0: batch_tuples[i].err /= err_count_list[i] self.replay.merge(Config.alpha) return np.mean([t.err for t in batch_tuples])