Exemple #1
0
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)
Exemple #2
0
    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)
Exemple #4
0
 def g(x, y, z):
     return cupy.clip(x, y, z)
Exemple #5
0
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"))
Exemple #7
0
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
Exemple #8
0
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()
Exemple #9
0
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)
Exemple #10
0
 def step(self, model, step_num):
     """Step function, called by solver.
     """
     model._solution = cp.clip(model.solution, a_min=0)
Exemple #11
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
Exemple #14
0
 def tanh(X):
     X = cp.clip(X, -350, 350)
     return (1 - cp.exp(-2 * X)) / (1 + cp.exp(-2 * X))
Exemple #15
0
 def sigmoid(X):
     X = cp.clip(X, -700, 700)
     return 1 / (1. + cp.exp(-X))
Exemple #16
0
 def g(x, y, z):
     return cupy.clip(x, y, z)
Exemple #17
0
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
Exemple #19
0
    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])
Exemple #20
0
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}')
Exemple #21
0
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
Exemple #22
0
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)
Exemple #24
0
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)
Exemple #25
0
def sigmoid(x):
    x = np.clip(x, -500, 500)
    return 1. / (1 + np.exp(-x))
Exemple #26
0
 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
Exemple #27
0
 def clamp(self, _min: float, _max: float) -> Vec3:
     return Vec3(*cp.clip(self.e, _min, _max))
Exemple #28
0
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
Exemple #29
0
 def clip(tensor, a_min=None, a_max=None):
     return cp.clip(tensor, a_min, a_max)
Exemple #30
0
 def fn():
     with cupy.cuda.Device(node.device_id):
         cupy.clip(inp, a_min=min_v, a_max=max_v, out=output)
Exemple #31
0
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
Exemple #32
0
    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])