从分位数拟合分布

Fit a distribution from quantiles

我正在尝试 replicate an example 来自 SAS 的 Python ,在那里我从汇总统计数据中拟合分布。我可用的摘要统计信息是总计数、最小值、最大值、p50、p75、p85、p95、p98、p99 和 p99.9。测量来自分布式机器网络,包括延迟或大小分布。目标是从每台机器重新构建混合,然后组合这些分布以估计整个网络的分布,并以流式方式定期执行此操作。

我正在查看 PyMC, Pyro and Pomegranate 的文档并了解混合模型的一般要点,但我不明白的是如何为每个分布设置初始参数,哪个使用给定我可用的数据,或如何将每个分布移动到相应的分位数以构建整体分布。

给定这些框架中的任何一个都可能吗?

Pyro forums 的帮助下回答我自己的问题。下面的代码包含问题前半部分的解决方案,从收集的分位数中找到与参数匹配的分布:

import torch
import torch.distributions as dist
from torch.optim import Adam

from typing import List, Tuple


def find_cauchy_params(quantiles: List[Tuple[float, float]]):
    alpha = torch.tensor(1.0, requires_grad=True)
    beta = torch.tensor(1.0, requires_grad=True)

    quantile_tensors = [
        (quantile, torch.tensor(quantile_value))
        for quantile, quantile_value in quantiles
    ]

    def loss_fn():
        loss = 0.0
        d = dist.Cauchy(alpha, beta)
        for quantile, quantile_value in quantile_tensors:
            loss += (quantile - d.cdf(quantile_value)) ** 2

        return loss

    optim = Adam([alpha, beta], lr=0.01)
    for step in range(1000):
        optim.zero_grad()
        loss = loss_fn()
        print("loss", loss)
        loss.backward()
        optim.step()

    print("alpha = {}".format(alpha.item()))
    print("beta = {}".format(beta.item()))


find_cauchy_params(
    [(0.5, 0.0), (0.75, 0.0), (0.95, 1.0), (0.98, 1.0), (0.99, 8.0), (0.999, 11.0)]
)

截断输出:

...
loss tensor(0.0317, grad_fn=<AddBackward0>)
loss tensor(0.0317, grad_fn=<AddBackward0>)
loss tensor(0.0317, grad_fn=<AddBackward0>)
loss tensor(0.0317, grad_fn=<AddBackward0>)
alpha = -0.04828706011176109
beta = 0.11657208949327469