Skip to content

Commit 56624d0

Browse files
authored
【Hackathon No.5】为 Paddle 新增 bucketize (#176)
* Create 20220708_api_design_for_bucketize.md * Update 20220708_api_design_for_bucketize.md * Update 20220708_api_design_for_bucketize.md 更新测试案例说明 * update test example.
1 parent 40ce78d commit 56624d0

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# paddle.Tensor.bucketize 设计文档
2+
3+
|API名称 | paddle.bucketize |
4+
|---|---|
5+
|提交作者<input type="checkbox" class="rowselector hidden"> | 李芳钰 |
6+
|提交时间<input type="checkbox" class="rowselector hidden"> | 2022-07-8 |
7+
|版本号 | V1.0 |
8+
|依赖飞桨版本<input type="checkbox" class="rowselector hidden"> | develop |
9+
|文件名 | 20220708_api_design_for_bucketize.md<br> |
10+
11+
# 一、概述
12+
13+
## 1、相关背景
14+
为了提升飞桨API丰富度,Paddle需要扩充API`paddle.bucketize`的功能。
15+
## 2、功能目标
16+
增加API`paddle.bucketize`,实现根据边界返回输入值的桶索引。
17+
## 3、意义
18+
飞桨支持`paddle.bucketize`的API功能。
19+
20+
# 二、飞桨现状
21+
目前paddle可直接由`paddle.searchsorted`API,直接实现该功能。
22+
23+
paddle已经实现了[paddle.searchsorted](https://github.com/PaddlePaddle/Paddle/blob/release/2.3/python/paddle/tensor/search.py#L910)API,所以只需要调用该API既可以实现该功能。
24+
25+
需要注意的是`paddle.bucketize`处理的sorted_sequence特殊要求为1-D Tensor。
26+
27+
# 三、业内方案调研
28+
## Numpy
29+
### 实现方法
30+
以现有numpy python API组合实现,[代码位置](https://github.com/numpy/numpy/blob/v1.23.0/numpy/lib/function_base.py#L5447-L5555).
31+
其中核心代码为:
32+
```Python
33+
x = _nx.asarray(x)
34+
bins = _nx.asarray(bins)
35+
36+
# here for compatibility, searchsorted below is happy to take this
37+
if np.issubdtype(x.dtype, _nx.complexfloating):
38+
raise TypeError("x may not be complex")
39+
40+
mono = _monotonicity(bins)
41+
if mono == 0:
42+
raise ValueError("bins must be monotonically increasing or decreasing")
43+
44+
# this is backwards because the arguments below are swapped
45+
side = 'left' if right else 'right'
46+
if mono == -1:
47+
# reverse the bins, and invert the results
48+
return len(bins) - _nx.searchsorted(bins[::-1], x, side=side)
49+
else:
50+
return _nx.searchsorted(bins, x, side=side)
51+
```
52+
整体逻辑为:
53+
54+
- 通过`_monotonicity`判断箱子是否单调递增或者递减。
55+
- 然后根据`mono`和参数`right`决定是否需要反转箱子。
56+
- 最后也是通过`searchsorted`直接返回输入对应的箱子索引。
57+
58+
## Pytorch
59+
Pytorch中有API`torch.bucketize(input, boundaries, *, out_int32=False, right=False, out=None) → Tensor`。在pytorch中,介绍为:
60+
```
61+
Returns the indices of the buckets to which each value in the input belongs, where the boundaries of the buckets are set by boundaries. Return a new tensor with the same size as input. If right is False (default), then the left boundary is closed.
62+
```
63+
64+
### 实现方法
65+
在实现方法上,Pytorch的整体逻辑与Numpy基本一致,[代码位置](https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/native/Bucketization.cpp)。其中核心代码为:
66+
```c++
67+
Tensor& bucketize_out_cpu(const Tensor& self, const Tensor& boundaries, bool out_int32, bool right, Tensor& result) {
68+
TORCH_CHECK(boundaries.dim() == 1, "boundaries tensor must be 1 dimension, but got dim(", boundaries.dim(), ")");
69+
at::native::searchsorted_out_cpu(boundaries, self, out_int32, right, nullopt, nullopt, result);
70+
return result;
71+
}
72+
```
73+
整体逻辑为:
74+
- 检查输入参数`boundaries`。
75+
- 然后直接利用`searchsorted_out_cpu`返回结果。
76+
77+
## Tensorflow
78+
Tensorflow`tft.bucketize(
79+
x: common_types.ConsistentTensorType,
80+
num_buckets: int,
81+
epsilon: Optional[float] = None,
82+
weights: Optional[tf.Tensor] = None,
83+
elementwise: bool = False,
84+
name: Optional[str] = None
85+
) -> common_types.ConsistentTensorType`。在Tensorflow中,介绍为:
86+
Returns a bucketized column, with a bucket index assigned to each input.
87+
88+
### 实现方法
89+
在实现方法上,Tensorflow的API参数设计于Numpy和Pytorch都不大相同,[代码位置](https://github.com/tensorflow/transform/blob/v1.9.0/tensorflow_transform/mappers.py#L1690-L1770)。这里就不具体分析其核心代码了,因为和我们想要实现的功能有很大的差距。
90+
91+
92+
# 四、对比分析
93+
- 使用场景与功能:Pytorch会比Numpy更贴和我们想要实现的功能,因为Pytorch也是仅针对1-D Tensor,而Numpy支持多维。
94+
95+
# 五、方案设计
96+
## 命名与参数设计
97+
API设计为`paddle.bucketize(x, sorted_sequence, out_int32=False, right=False, name=None)`
98+
命名与参数顺序为:形参名`input`->`x`, 与paddle其他API保持一致性,不影响实际功能使用。
99+
参数类型中,`x`为N-D Tensor,`sorted_sequence`为1-D Tensor。
100+
101+
## 底层OP设计
102+
使用已有API组合实现,不再单独设计OP。
103+
104+
## API实现方案
105+
主要按下列步骤进行实现,实现位置为`paddle/tensor/math.py`与`searchsorted`方法放在一起:
106+
1. 使用`len(sorted_sequence)`检验参数`sorted_sequence`的维度。
107+
2. 使用`paddle.searchsorted`得到输入的桶索引。
108+
109+
110+
# 六、测试和验收的考量
111+
测试考虑的case如下:
112+
113+
- 和numpy结果的数值的一致性, `paddle.bucketize`,和`numpy.searchsorted`结果是否一致;
114+
- 参数`right`为True和False时输出的正确性;
115+
- `out_int32`为True和False时输出dtype正确性;
116+
- 未输入`right`时的输出正确性;
117+
- 未输入`out_int32`时的输出正确性;
118+
- 错误检查:输入`x`不是Tensor时,能否正确抛出错误;
119+
- 错误检查:输入`sorted_sequence`不是一维张量时,能否正确抛出错误;
120+
- 错误检查:未输入`x`和`sorted_sequence`时,能否正确抛出错误;
121+
122+
# 七、可行性分析及规划排期
123+
124+
方案主要依赖现有paddle api组合而成,且依赖的`paddle.searchsorted`已经在 Paddle repo 的 python/paddle/tensor/search.py [目录中](https://github.com/PaddlePaddle/Paddle/blob/release/2.3/python/paddle/tensor/search.py#L910)。工期上可以满足在当前版本周期内开发完成。
125+
126+
# 八、影响面
127+
为独立新增API,对其他模块没有影响
128+
129+
# 名词解释
130+
131+
# 附件及参考资料
132+
133+

0 commit comments

Comments
 (0)