search.py 39.8 KB
Newer Older
1
#   Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 3 4 5 6 7 8 9 10 11 12 13
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
14 15 16

# TODO: define searching & indexing functions of a tensor

17
import numpy as np
18

Z
zhiboniu 已提交
19
import paddle
20
from paddle import _C_ops
21 22
from paddle.common_ops_import import VarDesc, Variable

23
from ..fluid.data_feeder import check_dtype, check_variable_and_dtype
24 25 26 27 28 29
from ..framework import (
    LayerHelper,
    convert_np_dtype_to_dtype_,
    core,
    in_dygraph_mode,
)
30

31 32
# from ..fluid.layers import has_inf  #DEFINE_ALIAS
# from ..fluid.layers import has_nan  #DEFINE_ALIAS
33

34 35
__all__ = []

36

37 38
def argsort(x, axis=-1, descending=False, name=None):
    """
39
    Sorts the input along the given axis, and returns the corresponding index tensor for the sorted output values. The default sort algorithm is ascending, if you want the sort algorithm to be descending, you must set the :attr:`descending` as True.
40 41 42 43 44 45

    Args:
        x(Tensor): An input N-D Tensor with type float32, float64, int16,
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is Rank(x). when axis<0, it works the same way
C
Chen Long 已提交
46
            as axis+R. Default is -1.
47 48 49
        descending(bool, optional) : Descending is a flag, if set to true,
            algorithm will sort by descending order, else sort by
            ascending order. Default is false.
50
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
51 52 53 54 55 56

    Returns:
        Tensor: sorted indices(with the same shape as ``x``
        and with data type int64).

    Examples:
李灿 已提交
57

58
        .. code-block:: python
李灿 已提交
59

60
            import paddle
61

62 63 64 65 66
            x = paddle.to_tensor([[[5,8,9,5],
                                   [0,0,1,7],
                                   [6,9,2,4]],
                                  [[5,2,4,2],
                                   [4,7,7,9],
67
                                   [1,7,0,6]]],
68
                                dtype='float32')
C
Chen Long 已提交
69 70 71
            out1 = paddle.argsort(x, axis=-1)
            out2 = paddle.argsort(x, axis=0)
            out3 = paddle.argsort(x, axis=1)
72

N
Noel 已提交
73
            print(out1)
W
wawltor 已提交
74 75 76
            #[[[0 3 1 2]
            #  [0 1 2 3]
            #  [2 3 0 1]]
77
            # [[1 3 2 0]
W
wawltor 已提交
78 79
            #  [0 1 2 3]
            #  [2 0 3 1]]]
80

N
Noel 已提交
81
            print(out2)
W
wawltor 已提交
82 83 84 85 86 87
            #[[[0 1 1 1]
            #  [0 0 0 0]
            #  [1 1 1 0]]
            # [[1 0 0 0]
            #  [1 1 1 1]
            #  [0 0 0 1]]]
88

N
Noel 已提交
89
            print(out3)
W
wawltor 已提交
90 91 92 93 94 95
            #[[[1 1 1 2]
            #  [0 0 2 0]
            #  [2 2 0 1]]
            # [[2 0 2 0]
            #  [1 1 0 2]
            #  [0 2 1 1]]]
96
    """
H
hong 已提交
97
    if in_dygraph_mode():
98
        _, ids = _C_ops.argsort(x, axis, descending)
H
hong 已提交
99
        return ids
100 101 102 103 104 105 106
    else:
        check_variable_and_dtype(
            x,
            'x',
            ['float32', 'float64', 'int16', 'int32', 'int64', 'uint8'],
            'argsort',
        )
H
hong 已提交
107

108 109 110 111 112 113 114 115 116 117 118 119
        helper = LayerHelper("argsort", **locals())
        out = helper.create_variable_for_type_inference(
            dtype=x.dtype, stop_gradient=True
        )
        ids = helper.create_variable_for_type_inference(
            VarDesc.VarType.INT64, stop_gradient=True
        )
        helper.append_op(
            type='argsort',
            inputs={'X': x},
            outputs={'Out': out, 'Indices': ids},
            attrs={'axis': axis, 'descending': descending},
120
        )
121 122 123
        return ids


124
def argmax(x, axis=None, keepdim=False, dtype="int64", name=None):
125
    """
126
    Computes the indices of the max elements of the input tensor's
127 128 129
    element along the provided axis.

    Args:
W
wawltor 已提交
130
        x(Tensor): An input N-D Tensor with type float32, float64, int16,
131 132
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
W
wawltor 已提交
133 134
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is None, the input `x` will be into the flatten tensor, and selecting the min value index.
135
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
136
        dtype(str|np.dtype, optional): Data type of the output tensor which can
137
                    be int32, int64. The default value is ``int64`` , and it will
138
                    return the int64 indices.
139
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
140 141

    Returns:
142
        Tensor, return the tensor of int32 if set :attr:`dtype` is int32, otherwise return the tensor of int64.
143 144 145 146

    Examples:
        .. code-block:: python

W
wawltor 已提交
147
            import paddle
148

149 150 151
            x = paddle.to_tensor([[5,8,9,5],
                                 [0,0,1,7],
                                 [6,9,2,4]])
W
wawltor 已提交
152
            out1 = paddle.argmax(x)
N
Noel 已提交
153
            print(out1) # 2
154
            out2 = paddle.argmax(x, axis=0)
155
            print(out2)
156
            # [2, 2, 0, 1]
W
wawltor 已提交
157
            out3 = paddle.argmax(x, axis=-1)
158
            print(out3)
159 160 161 162
            # [2, 3, 1]
            out4 = paddle.argmax(x, axis=0, keepdim=True)
            print(out4)
            # [[2, 2, 0, 1]]
163
    """
164
    if axis is not None and not isinstance(axis, (int, Variable)):
165
        raise TypeError(
166
            "The type of 'axis'  must be int or Tensor or None in argmax, but received %s."
167 168
            % (type(axis))
        )
169

170 171 172 173
    if dtype is None:
        raise ValueError(
            "the value of 'dtype' in argmax could not be None, but received None"
        )
174

175
    var_dtype = convert_np_dtype_to_dtype_(dtype)
W
wawltor 已提交
176 177 178 179 180
    flatten = False
    if axis is None:
        flatten = True
        axis = 0

H
hong 已提交
181
    if in_dygraph_mode():
182
        return _C_ops.argmax(x, axis, keepdim, flatten, var_dtype)
183 184 185
    else:
        helper = LayerHelper("argmax", **locals())
        check_variable_and_dtype(
186
            x,
187 188 189
            'x',
            ['float32', 'float64', 'int16', 'int32', 'int64', 'uint8'],
            'paddle.argmax',
190
        )
191 192 193 194 195 196 197 198 199 200 201
        check_dtype(var_dtype, 'dtype', ['int32', 'int64'], 'argmin')
        attrs = {}
        out = helper.create_variable_for_type_inference(var_dtype)
        attrs['keepdims'] = keepdim
        attrs['axis'] = axis
        attrs['flatten'] = flatten
        attrs['dtype'] = var_dtype
        helper.append_op(
            type='arg_max', inputs={'X': x}, outputs={'Out': [out]}, attrs=attrs
        )
        out.stop_gradient = True
W
wawltor 已提交
202 203 204
        return out


205
def argmin(x, axis=None, keepdim=False, dtype="int64", name=None):
W
wawltor 已提交
206
    """
207
    Computes the indices of the min elements of the input tensor's
W
wawltor 已提交
208 209 210 211 212 213 214 215
    element along the provided axis.

    Args:
        x(Tensor): An input N-D Tensor with type float32, float64, int16,
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is None, the input `x` will be into the flatten tensor, and selecting the min value index.
216
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
217
        dtype(str, optional): Data type of the output tensor which can
218
                    be int32, int64. The default value is 'int64', and it will
W
wawltor 已提交
219
                    return the int64 indices.
220
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
221

W
wawltor 已提交
222
    Returns:
223
        Tensor, return the tensor of `int32` if set :attr:`dtype` is `int32`, otherwise return the tensor of `int64`.
W
wawltor 已提交
224 225 226

    Examples:
        .. code-block:: python
227

W
wawltor 已提交
228 229
            import paddle

230 231 232
            x =  paddle.to_tensor([[5,8,9,5],
                                     [0,0,1,7],
                                     [6,9,2,4]])
W
wawltor 已提交
233
            out1 = paddle.argmin(x)
N
Noel 已提交
234
            print(out1) # 4
235
            out2 = paddle.argmin(x, axis=0)
236
            print(out2)
237
            # [1, 1, 1, 2]
W
wawltor 已提交
238
            out3 = paddle.argmin(x, axis=-1)
239
            print(out3)
240 241 242 243
            # [0, 0, 2]
            out4 = paddle.argmin(x, axis=0, keepdim=True)
            print(out4)
            # [[1, 1, 1, 2]]
W
wawltor 已提交
244
    """
245
    if axis is not None and not isinstance(axis, (int, Variable)):
246
        raise TypeError(
247
            "The type of 'axis'  must be int or Tensor or None in argmin, but received %s."
248 249
            % (type(axis))
        )
250

251 252 253 254
    if dtype is None:
        raise ValueError(
            "the value of 'dtype' in argmin could not be None, but received None"
        )
255

256
    var_dtype = convert_np_dtype_to_dtype_(dtype)
W
wawltor 已提交
257
    flatten = False
258
    if axis is None:
W
wawltor 已提交
259 260 261
        flatten = True
        axis = 0

H
hong 已提交
262
    if in_dygraph_mode():
263
        return _C_ops.argmin(x, axis, keepdim, flatten, var_dtype)
264 265 266
    else:
        helper = LayerHelper("argmin", **locals())
        check_variable_and_dtype(
267
            x,
268 269 270
            'x',
            ['float32', 'float64', 'int16', 'int32', 'int64', 'uint8'],
            'paddle.argmin',
271
        )
272 273 274 275 276 277 278 279 280 281 282
        check_dtype(var_dtype, 'dtype', ['int32', 'int64'], 'argmin')
        out = helper.create_variable_for_type_inference(var_dtype)
        attrs = {}
        attrs['keepdims'] = keepdim
        attrs['axis'] = axis
        attrs['flatten'] = flatten
        attrs['dtype'] = var_dtype
        helper.append_op(
            type='arg_min', inputs={'X': x}, outputs={'Out': [out]}, attrs=attrs
        )
        out.stop_gradient = True
W
wawltor 已提交
283 284
        return out

285

286
def index_select(x, index, axis=0, name=None):
287
    """
S
swtkiwi 已提交
288

289 290 291 292
    Returns a new tensor which indexes the ``input`` tensor along dimension ``axis`` using
    the entries in ``index`` which is a Tensor. The returned tensor has the same number
    of dimensions as the original ``x`` tensor. The dim-th dimension has the same
    size as the length of ``index``; other dimensions have the same size as in the ``x`` tensor.
C
Chengmo 已提交
293

294
    Args:
295 296 297
        x (Tensor): The input Tensor to be operated. The data of ``x`` can be one of float32, float64, int32, int64.
        index (Tensor): The 1-D Tensor containing the indices to index. The data type of ``index`` must be int32 or int64.
        axis (int, optional): The dimension in which we index. Default: if None, the ``axis`` is 0.
298
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
299 300

    Returns:
301
        Tensor: A Tensor with same data type as ``x``.
302

303 304
    Examples:
        .. code-block:: python
305

306 307
            import paddle

308 309 310 311
            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]])
            index = paddle.to_tensor([0, 1, 1], dtype='int32')
312 313 314 315 316 317 318 319
            out_z1 = paddle.index_select(x=x, index=index)
            #[[1. 2. 3. 4.]
            # [5. 6. 7. 8.]
            # [5. 6. 7. 8.]]
            out_z2 = paddle.index_select(x=x, index=index, axis=1)
            #[[ 1.  2.  2.]
            # [ 5.  6.  6.]
            # [ 9. 10. 10.]]
320
    """
321

F
From00 已提交
322
    if in_dygraph_mode():
323
        return _C_ops.index_select(x, index, axis)
324 325 326 327 328 329 330 331 332 333 334 335 336 337
    else:
        helper = LayerHelper("index_select", **locals())
        check_variable_and_dtype(
            x,
            'x',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.tensor.search.index_select',
        )
        check_variable_and_dtype(
            index,
            'index',
            ['int32', 'int64'],
            'paddle.tensor.search.index_select',
        )
F
From00 已提交
338

339
        out = helper.create_variable_for_type_inference(x.dtype)
340

341 342 343 344 345 346 347
        helper.append_op(
            type='index_select',
            inputs={'X': x, 'Index': index},
            outputs={'Out': out},
            attrs={'dim': axis},
        )
        return out
348 349


350
def nonzero(x, as_tuple=False):
351
    """
352 353 354 355 356 357
    Return a tensor containing the indices of all non-zero elements of the `input`
    tensor. If as_tuple is True, return a tuple of 1-D tensors, one for each dimension
    in `input`, each containing the indices (in that dimension) of all non-zero elements
    of `input`. Given a n-Dimensional `input` tensor with shape [x_1, x_2, ..., x_n], If
    as_tuple is False, we can get a output tensor with shape [z, n], where `z` is the
    number of all non-zero elements in the `input` tensor. If as_tuple is True, we can get
358
    a 1-D tensor tuple of length `n`, and the shape of each 1-D tensor is [z, 1].
C
Chengmo 已提交
359

360
    Args:
361
        x (Tensor): The input tensor variable.
362
        as_tuple (bool, optional): Return type, Tensor or tuple of Tensor.
363 364

    Returns:
365
        Tensor. The data type is int64.
366 367

    Examples:
368

N
Noel 已提交
369
        .. code-block:: python
李灿 已提交
370

371
            import paddle
372 373

            x1 = paddle.to_tensor([[1.0, 0.0, 0.0],
N
Noel 已提交
374 375
                                   [0.0, 2.0, 0.0],
                                   [0.0, 0.0, 3.0]])
376 377
            x2 = paddle.to_tensor([0.0, 1.0, 0.0, 3.0])
            out_z1 = paddle.nonzero(x1)
N
Noel 已提交
378
            print(out_z1)
379 380 381 382 383
            #[[0 0]
            # [1 1]
            # [2 2]]
            out_z1_tuple = paddle.nonzero(x1, as_tuple=True)
            for out in out_z1_tuple:
N
Noel 已提交
384
                print(out)
385 386 387 388 389 390 391
            #[[0]
            # [1]
            # [2]]
            #[[0]
            # [1]
            # [2]]
            out_z2 = paddle.nonzero(x2)
N
Noel 已提交
392
            print(out_z2)
393 394 395 396
            #[[1]
            # [3]]
            out_z2_tuple = paddle.nonzero(x2, as_tuple=True)
            for out in out_z2_tuple:
N
Noel 已提交
397
                print(out)
398 399
            #[[1]
            # [3]]
N
Noel 已提交
400

401 402
    """
    list_out = []
403
    shape = x.shape
404 405
    rank = len(shape)

406
    if in_dygraph_mode():
407
        outs = _C_ops.nonzero(x)
408
    else:
409 410 411
        helper = LayerHelper("where_index", **locals())

        outs = helper.create_variable_for_type_inference(
412 413
            dtype=core.VarDesc.VarType.INT64
        )
414

415 416 417
        helper.append_op(
            type='where_index', inputs={'Condition': x}, outputs={'Out': [outs]}
        )
418 419 420 421 422 423 424 425

    if not as_tuple:
        return outs
    elif rank == 1:
        return tuple([outs])
    else:
        for i in range(rank):
            list_out.append(
426 427
                paddle.slice(outs, axes=[1], starts=[i], ends=[i + 1])
            )
428 429 430
        return tuple(list_out)


431
def sort(x, axis=-1, descending=False, name=None):
432
    """
S
swtkiwi 已提交
433

434
    Sorts the input along the given axis, and returns the sorted output tensor. The default sort algorithm is ascending, if you want the sort algorithm to be descending, you must set the :attr:`descending` as True.
C
Chengmo 已提交
435

436
    Args:
437
        x(Tensor): An input N-D Tensor with type float32, float64, int16,
438 439 440
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is Rank(x). when axis<0, it works the same way
441
            as axis+R. Default is -1.
442 443 444
        descending(bool, optional) : Descending is a flag, if set to true,
            algorithm will sort by descending order, else sort by
            ascending order. Default is false.
445
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
446

447
    Returns:
W
wawltor 已提交
448
        Tensor: sorted tensor(with the same shape and data type as ``x``).
449
    Examples:
N
Noel 已提交
450

451
        .. code-block:: python
N
Noel 已提交
452

453
            import paddle
N
Noel 已提交
454

455 456 457 458 459
            x = paddle.to_tensor([[[5,8,9,5],
                                   [0,0,1,7],
                                   [6,9,2,4]],
                                  [[5,2,4,2],
                                   [4,7,7,9],
460
                                   [1,7,0,6]]],
461
                                 dtype='float32')
462 463 464
            out1 = paddle.sort(x=x, axis=-1)
            out2 = paddle.sort(x=x, axis=0)
            out3 = paddle.sort(x=x, axis=1)
N
Noel 已提交
465
            print(out1)
W
wawltor 已提交
466 467 468 469 470 471
            #[[[5. 5. 8. 9.]
            #  [0. 0. 1. 7.]
            #  [2. 4. 6. 9.]]
            # [[2. 2. 4. 5.]
            #  [4. 7. 7. 9.]
            #  [0. 1. 6. 7.]]]
N
Noel 已提交
472
            print(out2)
473
            #[[[5. 2. 4. 2.]
W
wawltor 已提交
474 475 476 477 478
            #  [0. 0. 1. 7.]
            #  [1. 7. 0. 4.]]
            # [[5. 8. 9. 5.]
            #  [4. 7. 7. 9.]
            #  [6. 9. 2. 6.]]]
N
Noel 已提交
479
            print(out3)
480
            #[[[0. 0. 1. 4.]
W
wawltor 已提交
481 482 483 484 485
            #  [5. 8. 2. 5.]
            #  [6. 9. 9. 7.]]
            # [[1. 2. 0. 2.]
            #  [4. 7. 4. 6.]
            #  [5. 7. 7. 9.]]]
486
    """
487
    if in_dygraph_mode():
488
        outs, _ = _C_ops.argsort(x, axis, descending)
489
        return outs
490 491 492 493
    else:
        helper = LayerHelper("sort", **locals())
        out = helper.create_variable_for_type_inference(
            dtype=x.dtype, stop_gradient=False
494
        )
495 496 497 498 499 500 501 502 503 504
        ids = helper.create_variable_for_type_inference(
            VarDesc.VarType.INT64, stop_gradient=True
        )
        helper.append_op(
            type='argsort',
            inputs={'X': x},
            outputs={'Out': out, 'Indices': ids},
            attrs={'axis': axis, 'descending': descending},
        )
        return out
C
Chengmo 已提交
505 506


507 508
def mode(x, axis=-1, keepdim=False, name=None):
    """
509
    Used to find values and indices of the modes at the optional axis.
510 511 512 513 514 515 516

    Args:
        x(Tensor): Tensor, an input N-D Tensor with type float32, float64, int32, int64.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is -1.
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
517
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
518 519 520 521 522 523 524 525 526

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.

    Examples:

        .. code-block:: python

           import paddle
527

528 529 530 531 532 533 534 535
           tensor = paddle.to_tensor([[[1,2,2],[2,3,3]],[[0,5,5],[9,9,0]]], dtype=paddle.float32)
           res = paddle.mode(tensor, 2)
           print(res)
           # (Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
           #   [[2., 3.],
           #    [5., 9.]]), Tensor(shape=[2, 2], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
           #   [[1, 1],
           #    [1, 0]]))
536

537
    """
538
    if in_dygraph_mode():
539
        return _C_ops.mode(x, axis, keepdim)
540 541 542 543 544 545
    else:
        helper = LayerHelper("mode", **locals())
        inputs = {"X": [x]}
        attrs = {}
        attrs['axis'] = axis
        attrs['keepdim'] = keepdim
546

547 548
        values = helper.create_variable_for_type_inference(dtype=x.dtype)
        indices = helper.create_variable_for_type_inference(dtype="int64")
549

550 551 552 553 554 555 556 557
        helper.append_op(
            type="mode",
            inputs=inputs,
            outputs={"Out": [values], "Indices": [indices]},
            attrs=attrs,
        )
        indices.stop_gradient = True
        return values, indices
558 559


R
ronnywang 已提交
560
def where(condition, x=None, y=None, name=None):
561
    r"""
562
    Return a Tensor of elements selected from either :attr:`x` or :attr:`y` according to corresponding elements of :attr:`condition`. Concretely,
R
ronnywang 已提交
563

564
    .. math::
C
Chengmo 已提交
565

566 567 568 569 570
        out_i =
        \begin{cases}
        x_i, & \text{if}  \ condition_i \  \text{is} \ True \\
        y_i, & \text{if}  \ condition_i \  \text{is} \ False \\
        \end{cases}.
C
Chengmo 已提交
571

572
    Notes:
张春乔 已提交
573
        ``numpy.where(condition)`` is identical to ``paddle.nonzero(condition, as_tuple=True)``, please refer to :ref:`api_paddle_nonzero`.
574

575
    Args:
576 577 578 579
        condition (Tensor): The condition to choose x or y. When True (nonzero), yield x, otherwise yield y.
        x (Tensor|scalar, optional): A Tensor or scalar to choose when the condition is True with data type of float32, float64, int32 or int64. Either both or neither of x and y should be given.
        y (Tensor|scalar, optional): A Tensor or scalar to choose when the condition is False with data type of float32, float64, int32 or int64. Either both or neither of x and y should be given.
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
580

581
    Returns:
582
        Tensor: A Tensor with the same shape as :attr:`condition` and same data type as :attr:`x` and :attr:`y`.
583

584
    Examples:
585

586 587
        .. code-block:: python

588
            import paddle
589

590 591
            x = paddle.to_tensor([0.9383, 0.1983, 3.2, 1.2])
            y = paddle.to_tensor([1.0, 1.0, 1.0, 1.0])
592

593 594 595
            out = paddle.where(x>1, x, y)
            print(out)
            #out: [1.0, 1.0, 3.2, 1.2]
596

597 598 599 600 601
            out = paddle.where(x>1)
            print(out)
            #out: (Tensor(shape=[2, 1], dtype=int64, place=CPUPlace, stop_gradient=True,
            #            [[2],
            #             [3]]),)
602
    """
R
ronnywang 已提交
603
    if np.isscalar(x):
604
        x = paddle.full([1], x, np.array([x]).dtype.name)
R
ronnywang 已提交
605 606

    if np.isscalar(y):
607
        y = paddle.full([1], y, np.array([y]).dtype.name)
R
ronnywang 已提交
608

R
ronnywang 已提交
609 610 611 612 613 614
    if x is None and y is None:
        return nonzero(condition, as_tuple=True)

    if x is None or y is None:
        raise ValueError("either both or neither of x and y should be given")

615
    condition_shape = list(condition.shape)
616 617
    x_shape = list(x.shape)
    y_shape = list(y.shape)
618

619
    if x_shape == y_shape and condition_shape == x_shape:
620 621 622 623
        broadcast_condition = condition
        broadcast_x = x
        broadcast_y = y
    else:
Z
zhiboniu 已提交
624 625 626 627 628 629 630 631 632 633 634 635 636
        zeros_like_x = paddle.zeros_like(x)
        zeros_like_y = paddle.zeros_like(y)
        zeros_like_condition = paddle.zeros_like(condition)
        zeros_like_condition = paddle.cast(zeros_like_condition, x.dtype)
        cast_cond = paddle.cast(condition, x.dtype)

        broadcast_zeros = paddle.add(zeros_like_x, zeros_like_y)
        broadcast_zeros = paddle.add(broadcast_zeros, zeros_like_condition)
        broadcast_x = paddle.add(x, broadcast_zeros)
        broadcast_y = paddle.add(y, broadcast_zeros)
        broadcast_condition = paddle.add(cast_cond, broadcast_zeros)
        broadcast_condition = paddle.cast(broadcast_condition, 'bool')

J
Jiabin Yang 已提交
637
    if in_dygraph_mode():
638
        return _C_ops.where(broadcast_condition, broadcast_x, broadcast_y)
639
    else:
640 641 642 643 644 645 646 647
        check_variable_and_dtype(condition, 'condition', ['bool'], 'where')
        check_variable_and_dtype(
            x, 'x', ['float32', 'float64', 'int32', 'int64'], 'where'
        )
        check_variable_and_dtype(
            y, 'y', ['float32', 'float64', 'int32', 'int64'], 'where'
        )

648 649
        helper = LayerHelper("where", **locals())
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
650

651 652 653 654 655 656 657 658 659 660 661
        helper.append_op(
            type='where',
            inputs={
                'Condition': broadcast_condition,
                'X': broadcast_x,
                'Y': broadcast_y,
            },
            outputs={'Out': [out]},
        )

        return out
662 663


C
Chengmo 已提交
664 665 666 667
def index_sample(x, index):
    """
    **IndexSample Layer**

668 669
    IndexSample OP returns the element of the specified location of X,
    and the location is specified by Index.
C
Chengmo 已提交
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687

    .. code-block:: text


                Given:

                X = [[1, 2, 3, 4, 5],
                     [6, 7, 8, 9, 10]]

                Index = [[0, 1, 3],
                         [0, 2, 4]]

                Then:

                Out = [[1, 2, 4],
                       [6, 8, 10]]

    Args:
688
        x (Tensor): The source input tensor with 2-D shape. Supported data type is
689
            int32, int64, float16, float32, float64.
690
        index (Tensor): The index input tensor with 2-D shape, first dimension should be same with X.
C
Chengmo 已提交
691 692 693
            Data type is int32 or int64.

    Returns:
C
Chengmo 已提交
694
        output (Tensor): The output is a tensor with the same shape as index.
C
Chengmo 已提交
695 696 697 698 699 700

    Examples:

        .. code-block:: python

            import paddle
701 702 703 704 705 706 707 708 709 710 711

            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]], dtype='float32')
            index = paddle.to_tensor([[0, 1, 2],
                                      [1, 2, 3],
                                      [0, 0, 0]], dtype='int32')
            target = paddle.to_tensor([[100, 200, 300, 400],
                                       [500, 600, 700, 800],
                                       [900, 1000, 1100, 1200]], dtype='int32')
            out_z1 = paddle.index_sample(x, index)
N
Noel 已提交
712
            print(out_z1)
713 714 715 716 717 718 719 720
            #[[1. 2. 3.]
            # [6. 7. 8.]
            # [9. 9. 9.]]

            # Use the index of the maximum value by topk op
            # get the value of the element of the corresponding index in other tensors
            top_value, top_index = paddle.topk(x, k=2)
            out_z2 = paddle.index_sample(target, top_index)
N
Noel 已提交
721
            print(top_value)
722 723 724 725
            #[[ 4.  3.]
            # [ 8.  7.]
            # [12. 11.]]

N
Noel 已提交
726
            print(top_index)
727 728 729 730
            #[[3 2]
            # [3 2]
            # [3 2]]

N
Noel 已提交
731
            print(out_z2)
732 733 734
            #[[ 400  300]
            # [ 800  700]
            # [1200 1100]]
C
Chengmo 已提交
735

C
Chengmo 已提交
736
    """
J
Jiabin Yang 已提交
737
    if in_dygraph_mode():
738
        return _C_ops.index_sample(x, index)
J
Jiabin Yang 已提交
739
    else:
740 741 742 743 744 745 746 747 748 749 750 751 752 753
        helper = LayerHelper("index_sample", **locals())
        check_variable_and_dtype(
            x,
            'x',
            ['float16', 'float32', 'float64', 'int32', 'int64'],
            'paddle.tensor.search.index_sample',
        )
        check_variable_and_dtype(
            index,
            'index',
            ['int32', 'int64'],
            'paddle.tensor.search.index_sample',
        )
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
J
Jiabin Yang 已提交
754

755 756 757 758 759 760
        helper.append_op(
            type='index_sample',
            inputs={'X': x, 'Index': index},
            outputs={'Out': out},
        )
        return out
761 762 763 764


def masked_select(x, mask, name=None):
    """
C
Chen Long 已提交
765
    Returns a new 1-D tensor which indexes the input tensor according to the ``mask``
766 767 768
    which is a tensor with data type of bool.

    Args:
769
        x (Tensor): The input Tensor, the data type can be int32, int64, float32, float64.
770
        mask (Tensor): The Tensor containing the binary mask to index with, it's data type is bool.
771
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
772

773
    Returns:
774
        A 1-D Tensor which is the same data type  as ``x``.
775

776 777 778 779 780
    Examples:

        .. code-block:: python

            import paddle
781 782 783 784 785 786 787

            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]])
            mask = paddle.to_tensor([[True, False, False, False],
                                     [True, True, False, False],
                                     [True, False, False, False]])
788 789 790 791
            out = paddle.masked_select(x, mask)
            #[1.0 5.0 6.0 9.0]
    """

H
hong 已提交
792
    if in_dygraph_mode():
793
        return _C_ops.masked_select(x, mask)
H
hong 已提交
794

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
    else:
        helper = LayerHelper("masked_select", **locals())
        check_variable_and_dtype(
            x,
            'x',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.tensor.search.mask_select',
        )
        check_variable_and_dtype(
            mask, 'mask', ['bool'], 'paddle.tensor.search.masked_select'
        )
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
        helper.append_op(
            type='masked_select',
            inputs={'X': x, 'Mask': mask},
            outputs={'Y': out},
        )
        return out
W
wawltor 已提交
813 814 815 816


def topk(x, k, axis=None, largest=True, sorted=True, name=None):
    """
817
    Return values and indices of the k largest or smallest at the optional axis.
W
wawltor 已提交
818 819 820 821 822 823 824 825 826 827 828 829
    If the input is a 1-D Tensor, finds the k largest or smallest values and indices.
    If the input is a Tensor with higher rank, this operator computes the top k values and indices along the :attr:`axis`.

    Args:
        x(Tensor): Tensor, an input N-D Tensor with type float32, float64, int32, int64.
        k(int, Tensor): The number of top elements to look for along the axis.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is -1.
        largest(bool, optional) : largest is a flag, if set to true,
            algorithm will sort by descending order, otherwise sort by
            ascending order. Default is True.
830
        sorted(bool, optional): controls whether to return the elements in sorted order, default value is True. In gpu device, it always return the sorted value.
W
wawltor 已提交
831 832 833 834 835 836 837 838
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.

    Examples:

        .. code-block:: python
839

840
            import paddle
W
wawltor 已提交
841

842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
            data_1 = paddle.to_tensor([1, 4, 5, 7])
            value_1, indices_1 = paddle.topk(data_1, k=1)
            print(value_1) # [7]
            print(indices_1) # [3]

            data_2 = paddle.to_tensor([[1, 4, 5, 7], [2, 6, 2, 5]])
            value_2, indices_2 = paddle.topk(data_2, k=1)
            print(value_2) # [[7], [6]]
            print(indices_2) # [[3], [1]]

            value_3, indices_3 = paddle.topk(data_2, k=1, axis=-1)
            print(value_3) # [[7], [6]]
            print(indices_3) # [[3], [1]]

            value_4, indices_4 = paddle.topk(data_2, k=1, axis=0)
            print(value_4) # [[2, 6, 5, 7]]
            print(indices_4) # [[1, 1, 0, 0]]
W
wawltor 已提交
859 860 861


    """
H
hong 已提交
862

H
hong 已提交
863
    if in_dygraph_mode():
864
        if axis is None:
H
hong 已提交
865
            axis = -1
866
        out, indices = _C_ops.topk(x, k, axis, largest, sorted)
H
hong 已提交
867
        return out, indices
W
wawltor 已提交
868
    else:
869 870 871 872 873 874 875 876 877 878 879
        helper = LayerHelper("top_k_v2", **locals())
        inputs = {"X": [x]}
        attrs = {}
        if isinstance(k, Variable):
            inputs['K'] = [k]
        else:
            attrs = {'k': k}
        attrs['largest'] = largest
        attrs['sorted'] = sorted
        if axis is not None:
            attrs['axis'] = axis
W
wawltor 已提交
880

881 882
        values = helper.create_variable_for_type_inference(dtype=x.dtype)
        indices = helper.create_variable_for_type_inference(dtype="int64")
W
wawltor 已提交
883

884 885 886 887 888 889 890 891
        helper.append_op(
            type="top_k_v2",
            inputs=inputs,
            outputs={"Out": [values], "Indices": [indices]},
            attrs=attrs,
        )
        indices.stop_gradient = True
        return values, indices
Y
Yanxing Shi 已提交
892 893


894 895 896 897 898 899
def bucketize(x, sorted_sequence, out_int32=False, right=False, name=None):
    """
    This API is used to find the index of the corresponding 1D tensor `sorted_sequence` in the innermost dimension based on the given `x`.

    Args:
        x(Tensor): An input N-D tensor value with type int32, int64, float32, float64.
900
        sorted_sequence(Tensor): An input 1-D tensor with type int32, int64, float32, float64. The value of the tensor monotonically increases in the innermost dimension.
901 902
        out_int32(bool, optional): Data type of the output tensor which can be int32, int64. The default value is False, and it indicates that the output data type is int64.
        right(bool, optional): Find the upper or lower bounds of the sorted_sequence range in the innermost dimension based on the given `x`. If the value of the sorted_sequence is nan or inf, return the size of the innermost dimension.
903
                               The default value is False and it shows the lower bounds.
904
        name(str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`.
905

906
    Returns:
907 908
        Tensor(the same sizes of the `x`), return the tensor of int32 if set :attr:`out_int32` is True, otherwise return the tensor of int64.

909 910 911
    Examples:

        .. code-block:: python
912

913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
            import paddle

            sorted_sequence = paddle.to_tensor([2, 4, 8, 16], dtype='int32')
            x = paddle.to_tensor([[0, 8, 4, 16], [-1, 2, 8, 4]], dtype='int32')
            out1 = paddle.bucketize(x, sorted_sequence)
            print(out1)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 2, 1, 3],
            #         [0, 0, 2, 1]])
            out2 = paddle.bucketize(x, sorted_sequence, right=True)
            print(out2)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 3, 2, 4],
            #         [0, 1, 3, 2]])
            out3 = x.bucketize(sorted_sequence)
            print(out3)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 2, 1, 3],
            #         [0, 0, 2, 1]])
            out4 = x.bucketize(sorted_sequence, right=True)
            print(out4)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 3, 2, 4],
            #         [0, 1, 3, 2]])
937

938
    """
939 940 941 942 943 944
    check_variable_and_dtype(
        sorted_sequence,
        'SortedSequence',
        ['float32', 'float64', 'int32', 'int64'],
        'paddle.searchsorted',
    )
945 946 947 948 949 950 951
    if sorted_sequence.dim() != 1:
        raise ValueError(
            f"sorted_sequence tensor must be 1 dimension, but got dim {sorted_sequence.dim()}"
        )
    return searchsorted(sorted_sequence, x, out_int32, right, name)


952 953 954
def searchsorted(
    sorted_sequence, values, out_int32=False, right=False, name=None
):
Y
Yanxing Shi 已提交
955
    """
956
    Find the index of the corresponding `sorted_sequence` in the innermost dimension based on the given `values`.
Y
Yanxing Shi 已提交
957 958

    Args:
959
        sorted_sequence(Tensor): An input N-D or 1-D tensor with type int32, int64, float32, float64. The value of the tensor monotonically increases in the innermost dimension.
Y
Yanxing Shi 已提交
960 961 962
        values(Tensor): An input N-D tensor value with type int32, int64, float32, float64.
        out_int32(bool, optional): Data type of the output tensor which can be int32, int64. The default value is False, and it indicates that the output data type is int64.
        right(bool, optional): Find the upper or lower bounds of the sorted_sequence range in the innermost dimension based on the given `values`. If the value of the sorted_sequence is nan or inf, return the size of the innermost dimension.
963
                               The default value is False and it shows the lower bounds.
964
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
965

Y
Yanxing Shi 已提交
966
    Returns:
967 968
        Tensor(the same sizes of the `values`), return the tensor of int32 if set :attr:`out_int32` is True, otherwise return the tensor of int64.

Y
Yanxing Shi 已提交
969 970 971
    Examples:

        .. code-block:: python
972

Y
Yanxing Shi 已提交
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
            import paddle

            sorted_sequence = paddle.to_tensor([[1, 3, 5, 7, 9, 11],
                                                [2, 4, 6, 8, 10, 12]], dtype='int32')
            values = paddle.to_tensor([[3, 6, 9, 10], [3, 6, 9, 10]], dtype='int32')
            out1 = paddle.searchsorted(sorted_sequence, values)
            print(out1)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[1, 3, 4, 5],
            #         [1, 2, 4, 4]])
            out2 = paddle.searchsorted(sorted_sequence, values, right=True)
            print(out2)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[2, 3, 5, 5],
            #         [1, 3, 4, 5]])
            sorted_sequence_1d = paddle.to_tensor([1, 3, 5, 7, 9, 11, 13])
989
            out3 = paddle.searchsorted(sorted_sequence_1d, values)
Y
Yanxing Shi 已提交
990 991 992 993
            print(out3)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[1, 3, 4, 5],
            #         [1, 3, 4, 5]])
994

Y
Yanxing Shi 已提交
995
    """
F
From00 已提交
996
    if in_dygraph_mode():
997
        return _C_ops.searchsorted(sorted_sequence, values, out_int32, right)
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
    else:
        check_variable_and_dtype(
            sorted_sequence,
            'SortedSequence',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.searchsorted',
        )
        check_variable_and_dtype(
            values,
            'Values',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.searchsorted',
1010
        )
Y
Yanxing Shi 已提交
1011

1012 1013 1014 1015 1016 1017 1018 1019 1020
        helper = LayerHelper('searchsorted', **locals())
        out_type = 'int32' if out_int32 else 'int64'
        out = helper.create_variable_for_type_inference(dtype=out_type)
        helper.append_op(
            type='searchsorted',
            inputs={'SortedSequence': sorted_sequence, "Values": values},
            outputs={'Out': out},
            attrs={"out_int32": out_int32, "right": right},
        )
Y
Yanxing Shi 已提交
1021

1022
        return out
1023 1024 1025 1026


def kthvalue(x, k, axis=None, keepdim=False, name=None):
    """
1027
    Find values and indices of the k-th smallest at the axis.
1028 1029 1030 1031 1032 1033 1034 1035

    Args:
        x(Tensor): A N-D Tensor with type float32, float64, int32, int64.
        k(int): The k for the k-th smallest number to look for along the axis.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. The default is None. And if the axis is None, it will computed as -1 by default.
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
1036
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
1037 1038 1039

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.
1040

1041 1042 1043
    Examples:

        .. code-block:: python
1044

1045
            import paddle
1046

1047 1048 1049 1050 1051 1052 1053 1054
            x = paddle.randn((2,3,2))
            # Tensor(shape=[2, 3, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
            #       [[[ 0.22954939, -0.01296274],
            #         [ 1.17135799, -0.34493217],
            #         [-0.19550551, -0.17573971]],
            #
            #        [[ 0.15104349, -0.93965352],
            #         [ 0.14745511,  0.98209465],
1055 1056
            #         [ 0.10732264, -0.55859774]]])
            y = paddle.kthvalue(x, 2, 1)
1057 1058 1059 1060 1061 1062
            # (Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
            # [[ 0.22954939, -0.17573971],
            #  [ 0.14745511, -0.55859774]]), Tensor(shape=[2, 2], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #  [[0, 2],
            #  [1, 2]]))
    """
1063
    if in_dygraph_mode():
1064
        if axis is not None:
1065
            return _C_ops.kthvalue(x, k, axis, keepdim)
1066
        else:
1067
            return _C_ops.kthvalue(x, k, -1, keepdim)
1068 1069 1070 1071 1072 1073 1074 1075 1076

    helper = LayerHelper("kthvalue", **locals())
    inputs = {"X": [x]}
    attrs = {'k': k}
    if axis is not None:
        attrs['axis'] = axis
    values = helper.create_variable_for_type_inference(dtype=x.dtype)
    indices = helper.create_variable_for_type_inference(dtype="int64")

1077 1078 1079 1080 1081 1082
    helper.append_op(
        type="kthvalue",
        inputs=inputs,
        outputs={"Out": [values], "Indices": [indices]},
        attrs=attrs,
    )
1083 1084
    indices.stop_gradient = True
    return values, indices