`ZeroSum` bijector and `ZeroSumNormal` distribution
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 38/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- python
调研方向
从 issue 中提议的 ZeroSum bijector 和 ZeroSumNormal distribution 开始,然后将它们的预期行为与链接的 NumPyro ZeroSumNormal 和 ZeroSumTransform 文档进行比较。在就受支持的 axis 行为达成一致,并交付具有经过验证的 zero-sum outputs 和 event shapes 的等效 TFP 功能后,即视为完成。
由索引模型根据 Issue 内容生成。
描述
numpyro and pymc have a zero sum normal distribution based on a zero sum bijector, (see e.g. numpyro zero sum normal and numpyro zero sum transform)).
I was wondering if there is any appetite in adding this to TFP? I have already got a simple port working (needs some changes, in particular maybe allowing variable number of axes to be constrained to sum to zero):
"""ZeroSum bijector."""
import tensorflow as tf
from tensorflow_probability.python.bijectors import bijector
from tensorflow_probability.python.internal import prefer_static as ps
from tensorflow_probability.python.internal import tensorshape_util
class ZeroSum(bijector.AutoCompositeTensorBijector):
def __init__(self, validate_args=False, name="zero_sum"):
parameters = dict(locals())
super(ZeroSum, self).__init__(
is_constant_jacobian=True,
forward_min_event_ndims=1,
validate_args=validate_args,
parameters=parameters,
name=name,
)
@classmethod
def _parameter_properties(cls, dtype):
return dict()
def _forward(self, x):
n = ps.cast(ps.shape(x)[-1], x.dtype) + 1
sum_vals = tf.reduce_sum(x, axis=-1, keepdims=True)
norm = sum_vals / (ps.sqrt(n) + n)
fill_val = norm - sum_vals / ps.sqrt(n)
out = tf.concat([x, fill_val], axis=-1)
return out - norm
def _inverse(self, y):
normalized_axis = ps.rank(y) - 1
n = ps.cast(ps.shape(y)[normalized_axis], y.dtype)
last = y[..., -1]
sum_vals = -last * ps.sqrt(n)
norm = sum_vals / (ps.sqrt(n) + n)
slice_before = (slice(None, None),) * normalized_axis
return y[(*slice_before, slice(None, -1))] + norm
def _inverse_log_det_jacobian(self, y):
return tf.zeros([], dtype=y.dtype)
def _forward_log_det_jacobian(self, x):
return tf.zeros([], dtype=x.dtype)
def _forward_event_shape(self, input_shape):
return tensorshape_util.concatenate(input_shape[:-1], input_shape[-1] + 1)
def _forward_event_shape_tensor(self, input_shape):
n = ps.shape(input_shape)[-1]
return ps.tensor_scatter_nd_add(input_shape, [[n - 1]], [1])
def _inverse_event_shape(self, input_shape):
return tensorshape_util.concatenate(input_shape[:-1], input_shape[-1] + 1)
def _inverse_event_shape_tensor(self, input_shape):
n = ps.shape(input_shape)[-1]
return ps.tensor_scatter_nd_sub(input_shape, [[n - 1]], [1])
usage:
import numpy as np
import tensorflow_probability as tfp
tfd = tfp.distributions
zero_sum_normal = tfd.TransformedDistribution(
distribution=tfd.MultivariateNormalDiag(loc=0.0, scale_diag=[1.0, 1.0]),
bijector=ZeroSum(),
)
zero_sum_normal
# <tfp.distributions.TransformedDistribution 'zero_sumMultivariateNormalDiag' batch_shape=[] event_shape=[3] dtype=float32>
samples = zero_sum_normal.sample(int(1e7))
np.max(np.abs(np.sum(samples, axis=-1)))
# 4.7683716e-07
np.mean(samples, axis=0)
# array([ 4.8274879e-04, -5.6865485e-04, 8.5900021e-05], dtype=float32)
np.std(samples, axis=0)
# array([0.8100124, 0.8101918, 0.8100392], dtype=float32)
compare to numpyro:
import jax.numpy as jnp
import jax.random as jr
import numpyro.distributions as dist
zero_sum_normal = dist.ZeroSumNormal(scale=jnp.array(1.0), event_shape=[3])
rng = jr.key(123)
samples = zero_sum_normal.sample(rng, sample_shape=(int(1e7),))
jnp.max(jnp.abs(jnp.sum(samples, axis=1)))
# Array(5.9604645e-07, dtype=float32)
jnp.mean(samples, axis=0)
# Array([-1.7739683e-04, -6.7088688e-05, 2.4448565e-04], dtype=float32)
jnp.std(samples, axis=0)
# Array([0.8164292 , 0.81622946, 0.8164195 ], dtype=float32)
If this is something useful, I can work on bits of it over the next couple of weeks, or if someone else wants to take it over, that's great too.
Thanks.
- 主要语言
- Jupyter Notebook
- 星标
- 4.4k
- 派生
- 1.1k
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
tensorflow/probability 的其他 Issue
-
KL divergence between two `TransformedDistribution`s with a shared non-injective bijector (`AbsoluteValue`) returns the base KL可能已有人在做 @Andreas-Hum 于 8 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 72/100
tensorflow/probability#2036 ·
-
难度 3/5 1-2 天 新手友好度 68/100
tensorflow/probability#2034 ·
-
难度 5/5 一周以上 新手友好度 35/100
tensorflow/probability#2021 ·
-
难度 4/5 3-5 天 新手友好度 30/100
tensorflow/probability#2015 ·
-
难度 3/5 1-2 天 新手友好度 48/100
tensorflow/probability#2013 ·
查看 tensorflow/probability 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 62/100
vllm-project/vllm-ascend#21392 · 1 条评论 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 68/100
维护者通常 2 天内回复
-
难度 1/5 1 小时以内 新手友好度 85/100
维护者通常 1 天内回复
-
type:epic-wave
难度 2/5 1-3 小时 新手友好度 75/100
jejjohnson/filterax#204 ·
维护者通常 1 天内回复
-
documentation good first issue
难度 2/5 1-3 小时 新手友好度 88/100
selimfirat/pysad#644 ·
维护者通常 1 天内回复