首页 > 解决方案 > 从 zFit 中的玩具中提取情节

问题描述

首先我想说我在这个话题上确实有概念上的困难,所以如果我的意图没有意义,请纠正我。

我正在尝试验证用于从分布中提取信号产量的模型。为简单起见,假设只有信号分布而没有背景。该模型是标准高斯模型,我创建了扩展 PDF。

在我的想法中,我会从该 PDF 创建示例数据,并且只更改事件的数量,即仅缩放。比我适合这个玩具样本并通过计算将生成的事件数量与拟合的信号产量进行比较

pull = (N_generated - N_fit) / sigma_Nfit

我不明白的是我如何设置获取生成的数字。在这一代中,我想随机设置事件的数量(我猜是泊松分布?)并保持所有其他模型参数固定。

最后我有信号+背景分布并且想要:

  1. 改变信号数量+保持背景数量固定
  2. 修复信号+改变背景
  3. 改变 n_total 中的分数 = n_signal + fraction * n_background

以下代码取自 zfit-tutorials 并更新为具有扩展模型(也可在此处找到:https ://github.com/holyschmoly/zfit_toymc ):

mu = zfit.Parameter('mu', 0, -1, 1)
sigma = zfit.Parameter('sigma', 1, 0.5, 1.5)
model = zfit.pdf.Gauss(obs=obs, mu=mu, sigma=sigma)

# do i need this range here?
nsig_toy = 1e4
nsig_range = 0.1
n_sig = zfit.Parameter('n_sig', nsig_toy, nsig_toy*(1-nsig_range), nsig_toy*(1+nsig_range))
model = model.create_extended(n_sig)

# vary only n_sig
sampler = model.create_sampler(fixed_params=[mu, sigma])
nll = zfit.loss.ExtendedUnbinnedNLL(model, sampler)

minimizer = zfit.minimize.Minuit(
    strategy=zfit.minimize.DefaultToyStrategy(),
    verbosity=0,
    tolerance=1e-3,
    use_minuit_grad=True)
params = nll.get_params()

fit_results = []
ntoys = 10

while len(fit_results) < ntoys:

    # What does really happen here?
    sampler.resample()

    # I think this is probably not what I want but I don't understand why
    # this is needed in the first place.
    # I want something like: vary n_sig randomly, keep mu and sigma fixed
    for param in params:
       param.randomize()

    result = minimizer.minimize(nll)

    if result.converged:
        result.hesse()
        fit_results.append(result)
    
# Now I want something like this:
# pull =  (N_generated - N_fit ) / sigma_fit
# for each fit_result.

标签: zfit

解决方案


这看起来是一件合理的事情。问题是您是否真的只想改变信号和只改变 bkg,但这当然是免费的。

那么你需要的是更复杂的东西。

首先要做的事情是:该resample方法实际上再次从 PDF 中采样。但是,来自整个 PDF,而不是部分。

您需要的是一个 for 循环,在这个 for 循环中,您可以使用samplefrom 方法pdf生成各个部分。然后你将它们缝合在一起并造成损失。然后你把这个损失给最小化器。让我画一下:

for i in ntoys:
    # calculate how many background and signal samples you want, e.g. with numpy
    sample_bkg = bkg_pdf.sample(n=...)
    sample_signal = sig_pdf.sample(n=...)
    sample = tf.concat([sample_sig.value(), sample_bkg.value()], axis=0)
    data = zfit.Data.from_tensor(tensor=sample, obs=obs)
    nll = zfit.loss.ExtendedUnbinnedNLL(model, data)
    result = minimizer.minimize(nll)
    # use the result to get the param values
    nsig = result.param[sig_yield]['value']  # assuming sig_yield is a zfit.Parameter, the yield of the signal
    # calculate pull, add it to a list of pulls

也许您想在循环的开头添加 a ,否则内存会不断增长,或者在脚本的开头zfit.run.clear_graph_cache()使用 a 以急切模式运行所有内容。zfit.run.set_graph_mode(False)这可能更快或更慢,具体取决于复杂性。对于简单、快速的拟合,预计将图形模式设置为 False 会更快,对于更复杂的情况,第一种方法 - 清除缓存 - 应该会执行得更好。


推荐阅读