-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
【Hackathon 4th No.13】为 Paddle 新增 Bernoulli API #52244
Conversation
你的PR提交成功,感谢你对开源项目的贡献! |
scipy基础版本升级可能比较麻烦,建议 1)你可以修改Paddle/python/unittest_py/requirements.txt 中的scipy版本尝试,如果CI出现大范围报错,则 2) 用numpy实现个bernoulli作为基准进行测试 |
收到!我先试一下第一个方法,谢谢!:) |
如果CI没有问题的话,建议单独提一个PR把scipy版本做升级 |
python/unittest_py/requirements.txt
Outdated
@@ -8,7 +8,7 @@ hypothesis | |||
opencv-python<=4.2.0.32 | |||
visualdl | |||
paddle2onnx>=0.9.6 | |||
scipy>=1.6 | |||
scipy>=1.6, !=1.7.2, !=1.7.3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2023-04-03 14:06:08 Collecting scipy!=1.7.2,!=1.7.3,>=1.6
2023-04-03 14:06:09 Using cached scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (34.5 MB)
可以直接写 1.10.1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2023-04-03 14:06:08 Collecting scipy!=1.7.2,!=1.7.3,>=1.6 2023-04-03 14:06:09 Using cached scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (34.5 MB)
可以直接写 1.10.1?
可以,AI STUDIO 上就是1.10.1,可以过测。
只是这样的话会绑定python版本,以后scipy更新也要修改,所以就写成我这样了。
谢谢! |
你可以写 >=1.10.1
意思就是先提一个单独的PR修改unittest_py/requirements.txt 中的scipy版本(因为CI环境的变化需要其他审核人看),merge之后再更新这个API的PR(你可以先同步保留这个PR中scipy版本的修改,便于 @cxxly 继续审核,不然你这个PR的CI都过不去)
请 @cxxly 看下是否可以修改 timeout,还是单测写法上可以改进下。 |
收到,那我先去提个PR修改scipy版本。 |
已经提交PR,#52476
|
Mac 是在CI配置中写的 unittest_py/requirements.txt ,因此等 PR merge后重新rerun下即可。 |
目前CI还有两个必须需要手动确认的项目了~ 请评审,谢谢! |
'float32': 1e-03, | ||
'float64': 1e-05, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
paddle.finfo(paddle.float32).eps paddle.finfo(paddle.float64).eps能否满足要求,如果不能,此处eps取值需要通过注释说明原因
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
应该是这样写,可是有几个问题:
- paddle里面我现在只找到
iinfo
,没有finfo
- 如果有,且与
numpy
的eps
一致的话,单测是过不了的,因为单测里面的np.testing.assert_allclose
是按照config
来设置的
RTOL = {
'float32': 1e-03,
'complex64': 1e-3,
'float64': 1e-5,
'complex128': 1e-5,
}
https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/unittests/distribution/config.py#L25
而 numpy
的值跟这个不一样
print(np.finfo('float32').eps, np.finfo('float64').eps)
# 1.1920929e-07 2.220446049250313e-16
这咋处理?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1)paddle develop 包含 finfo
2) 你这里eps不是仅仅为了clip用嘛,没太明白allclose阈值有啥关系
3)paddle.finfo 和 numpy finfo 是一样的
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1)我在develop里面已经找到 finfo
了,谢谢!
2)我又看了一下当时因为 eps
错误的用例,应该是 scipy
的 entropy
方法与 paddle
的实现有少许区别导致的。假设 probs=1.0
:
# --------------------------
# scipy
def entr(x):
return -x*np.log(x)
def _entropy_scipy(p):
return entr(p) + entr(1-p)
# --------------------------
# paddle
def _probs_to_logits(probs, is_binary=False):
return ((paddle.log(probs) -
paddle.log1p(-probs)) if is_binary else paddle.log(probs))
def _entropy_paddle(logits, probs):
return paddle.max(logits, 0)-logits*probs+paddle.log(1+paddle.exp(-paddle.abs(logits)))
# --------------------------
# 测试 scipy 与 paddle 的区别
probs = (1.0-np.finfo('float32').eps).astype('float32')
logits = _probs_to_logits(paddle.to_tensor(probs, dtype='float32'), True)
entropy_np = _entropy_scipy(probs)
entropy_paddle = _entropy_paddle(logits, probs)
print(entropy_np)
print(entropy_paddle.numpy())
# 2.0196896973703793e-06
# [2.026558e-06]
这时候如果再用allclose进行声明就会报错:
np.testing.assert_allclose(
entropy_np,
entropy_paddle,
rtol=1e-03,
atol=0,
)
# AssertionError:
# Not equal to tolerance rtol=0.001, atol=0
# Mismatched elements: 1 / 1 (100%)
# Max absolute difference: 6.8682766e-09
# Max relative difference: 0.00338913
# x: array(2.01969e-06)
# y: array([2.026558e-06], dtype=float32)
这样吧,我把 scipy
的 entropy
改为与 paddle
一致的算法,这样应该就可以了。
谢谢!:)
|
||
Args: | ||
probs (float|list|tuple|numpy.ndarray|Tensor): The ``probs`` input of Bernoulli distribution. The data type is float32 or float64. The range must be in [0, 1]. | ||
name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
无需支持 list/tuple/numpy.ndarray,支持scalar/Tensor即可
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
改成 float|Tensor
吧,保持与 _to_tensor
一致,而且包含复数也没什么意义。
# Clip probs from [0, 1] to (0, 1) with smallest representable number `eps`. | ||
self.probs = _clip_probs(self.probs) | ||
self.logits = self._probs_to_logits(self.probs, is_binary=True) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上,支持scalar/Tensor即可,简化代码复杂度
Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`. | ||
The shape of the sampled data have ndim lager than 1. | ||
|
||
Examples: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
此处应该需要空行吧,请确认下
'shape', | ||
(np.ndarray, tensor.Variable, list, tuple), | ||
name, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上
Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`. | ||
The shape of the sampled data have ndim lager than 1. | ||
|
||
Examples: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上
'temperature', | ||
(float,), | ||
name, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上
shape = shape if isinstance(shape, tuple) else tuple(shape) | ||
shape = self._extend_shape(shape) | ||
|
||
temperature = paddle.full(shape=[1], fill_value=temperature) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
飞桨已支持0D Tensor, paddle.full(shape=(), fill_value=...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0D
好像现在支持的还不好,这里如果改成 0D
,后面的 paddle.divide
会报错,比如:
paddle.divide(paddle.to_tensor([0.3]), paddle.full(shape=[1], fill_value=0.1))
# Tensor(shape=[1], dtype=float32, place=Place(gpu:0), stop_gradient=True, [3.])
paddle.divide(paddle.to_tensor([0.3]), paddle.full(shape=(), fill_value=0.1))
# ---------------------------------------------------------------------------
# ValueError Traceback (most recent call last)
# /tmp/ipykernel_1677/1739005628.py in <module>
# ----> 1 paddle.divide(paddle.to_tensor([0.3]), paddle.full(shape=(), fill_value=0.1))
# /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/tensor/math.py in divide(x, y, name)
# 716 act = None
# 717 if in_dygraph_mode():
# --> 718 return _C_ops.divide( x, y)
# 719 else:
# 720 if _in_legacy_dygraph():
# ValueError: (InvalidArgument) Axis should be less than 1, but received axis is 1.
# [Hint: Expected axis < max_dim, but received axis:1 >= max_dim:1.] (at /paddle/paddle/phi/kernels/funcs/common_shape.h:53)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
因为to_tensor会产生1D,能否也用full替代,或者reshape到0D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
刚又重新试了下develop版本,之前很多0D的运算问题都没有了,我把整体代码逻辑优化一下。谢谢!:)
temperature, | ||
) | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要测试 rsample的反向
可以的,需要定位并说明原因 |
不用改了,我这里修改静态图的测试流程,不会 |
@megemini 如果上一轮comment意见都修改完了,请评论告诉我们可以启动下一轮review |
可以了,请评审! 谢谢! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@megemini 中文文档链接请附一下 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
PR types
New features
PR changes
APIs
Describe
[used AI Studio]
其他说明:
谢谢评审!
p.s. 2023-04-09 CI情况反馈
根据评审意见修改:
float|Tensor
,并且优化初始化逻辑。EPS
使用paddle.finfo
代替,并且修改单测中BernoulliNumpy
的entropy
方法。temperature
使用paddle.full(shape=(), fill_value=...)
。rsample
的反向单测。doc string
中的例子,增加0D的情况。doc string
中的空行。请评审,谢谢!
p.s. 2023-04-06 CI情况反馈
重新提交之后,CI只剩下两个必须需要手工确认的了:
BernoulliNumpy
的初始化方式,规避掉scipy
版本的问题。统一用
float64
初始化,然后在各个返回值中(如mean
、variance
等)再转换为原始数据类型(astype
,如float32
、float64
)。这样可以在不破坏原有测试用例的基础上规避掉scipy
版本的问题。test_distribution_bernoulli_static
的测试流程,较少了测试时间。将原有的
parameterize_cls
中多个测试参数合并为一个,并且将test_xxx
统一转换为私有方法_test_xxx
,再由test_all
一并调用。这样可以在不减少测试用例的基础上,省掉每次测试的初始化过程,最终静态图的测试时间约为动态图的一半。请评审,谢谢!
p.s. 2023-04-03 CI情况反馈
通过修改
unittest_py/requirements.txt
中scipy
的版本,已经可以正常跑通PR-CI-Coverage
中动态图单测,但是PR-CI-Coverage
中静态图的单测提示超时15s
了。在 AI Studio 中静态图的单测大约在
12s
左右,CI 环境比较慢。请指导一下,是否可以通过修改
CMakeLists.txt
的方式延长单测时间,修改哪一部分?60s
应该足够。非常感谢!:)
p.s. 2023-03-29 CI情况反馈
今天查看CI的执行情况,发现单测通过不了,具体看了一下,应该是scipy版本的问题。
CI环境中的scipy版本是
scipy==1.7.3
,这个版本对于float32
的处理存在问题:而对于其他版本,如
scipy==1.7.1
,或最新的1.10.x
版本,结果是正确的:单测中的
np.testing.assert_allclose
错误,进而导致CI无法通过。以上问题,在
scipy
的issue
中已有类似的反馈:BUG: scipy.stats.beta and bernoulli fails with float32 inputs #15961
BUG: Overflow when using stats.beta.mean #16478
另外,
1.7.3
版本已经不在scipy
正式文档列表中了,是否可以更新一下CI环境重新测试。还请知悉,非常感谢!