Exclude/Ignore 多项式拟合 (zfit) 中的数据区域

Exclude/Ignore data region in polynomial fit (zfit)

我想知道是否有一种方法可以排除多项式拟合中的一个或多个数据区域。目前这似乎不像我预期的那样有效。这里有一个小例子:

import numpy as np
import pandas as pd
import zfit

# Create test data
left_data = np.random.uniform(0, 3, size=1000).tolist()
mid_data = np.random.uniform(3, 6, size=5000).tolist()
right_data = np.random.uniform(6, 9, size=1000).tolist()
testsample = pd.DataFrame(left_data + mid_data + right_data, columns=["x"])

# Define fit parameter
coeff1 = zfit.Parameter('coeff1', 0.1, -3, 3)
coeff2 = zfit.Parameter('coeff2', 0.1, -3, 3)

# Define Space for the fit
obs_all = zfit.Space("x", limits=(0, 9))

# Perform the fit
bkg_fit = zfit.pdf.Chebyshev(obs=obs_all, coeffs=[coeff1, coeff2], coeff0=1)
new_testsample = zfit.Data.from_pandas(obs=obs_all, df=testsample.query("x<3 or x>6"), weights=None)
nll = zfit.loss.UnbinnedNLL(model=bkg_fit, data=new_testsample)
minimizer = zfit.minimize.Minuit()
result = minimizer.minimize(nll)

TestSample.png

我在这里创建了一个包含 3 个均匀分布数据的小型测试样本。我只想使用 x < 3 OR x > 6 中的数据,忽略中间的 'peak'。由于它们的形状和高度相同,我预计 coeff1 和 coeff2 将(几乎)为零,并且拟合曲线将是一条水平直线。显然这不会发生,因为 zfit 假设 3 和 6 之间没有条目。

我还尝试使用 MultiSpaces 通过

忽略该区域
limit1 = zfit.Space("x", limits=(0, 3))
limit2 = zfit.Space("x", limits=(6, 9))
obs_data = limit1 + limit2

但这会导致

ValueError: obs need to be a Space with exactly one limit if rescaling is requested.

有人知道如何解决这个问题吗?

提前致谢^^

确实,这是一个有点棘手的问题,但这可能只需要在 zfit 中进行一个小的更新。

您所做的是正确的:只需使用所需区域中的数据即可。然而,这还不是全部,因为存在一个“归一化范围”:从概率上讲,这就像对某个区域的条件化,因为我们知道数据只能在特定区域。因此,PDF 的规范化应该只对包含的(LOW 和 HIGH)区域进行整合。

这通常可以通过两种方式完成:

使用多space

像您一样使用 multispace 属性。这应该可行(虽然很可能不是未来的方式),除了多项式函数中的一个怪癖:多项式定义为 -1 到 1。目前,数据只是重新缩放因此在 - 1 和 1(为此它应该使用 PDF 的“space”属性)。目前,这需要一个简单的 space( 原则上也可以允许,使用限制的最小值和最大值)。

同时配合

正如@jtlz2 评论中提到的,您可以同时进行拟合。这没什么好担心的,它只是将可能性分成两部分。由于它是概率的乘积,我们可以在概念上将它分成两个乘积并相乘(或添加它们的对数)。

因此您可以让 pdf 同时适合下部区域和上部区域。 但是,这并没有解决归一化的问题:PDF应该归一化成什么?我们将运行陷入同样的​​问题。

解决方案 1:不同 space 和标准

Space 和归一化范围不一样。默认情况下,space(通常称为'obs')也用作默认规范化范围但不是必需的。因此,您可以使用从最低点到最大点的一个 space 作为 obs,然后 使用您的 multispaceset_norm 应该这样做,或者 set_norm_range 如果您使用的不是最新版本)。我认为这应该可以解决问题。

方案二:手动重新缩放

实际问题是它抱怨 重新缩放 到 -1 和 1 无法完成。每个执行此操作的多项式也可以通过使用 apply_scaling=False 参数被告知不要执行此操作。这样,您负责在 -1 和 1 范围内缩放数据(因为多项式未在外部定义)并且不应该有任何错误。