#zfit
#zfit
Вопрос:
Прежде всего, я хотел бы сказать, что у меня есть концептуальные трудности с этой темой, поэтому, пожалуйста, поправьте меня, если мое намерение не имеет смысла.
Я пытаюсь проверить модель, которую я использую для извлечения выхода сигнала из дистрибутива. Для простоты предположим, что есть только распределение сигнала и нет фона. Модель представляет собой стандартный файл Gauss, и я создал расширенный PDF-файл.
По моему мнению, я бы создал образцы данных из этого PDF-файла и изменил только количество событий, то есть только масштабирование. Затем я бы поместил этот образец toy и сравнил сгенерированное количество событий с установленным выходом сигнала путем вычисления
pull = (N_generated - N_fit) / sigma_Nfit
Чего я не понимаю, так это как я устанавливаю и получаю сгенерированное число. В поколении я хочу установить количество событий случайным образом (я думаю, Пуассон распределен?) и сохраните все остальные параметры модели фиксированными.
В итоге у меня есть распределения сигнала фона и я хочу:
- изменять количество сигналов фиксировать количество фонов
- исправить сигнал изменить фон
- изменить дробь в n_total = n_signal дробь * 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.
Ответ №1:
Это выглядит разумно. Вопрос в том, действительно ли вы хотите изменять только signal и только bkg, но это, конечно, бесплатно.
Тогда вам нужно что-то более сложное.
Перво-наперво: resample
метод фактически снова выполняет выборку из PDF. Однако из всего PDF-файла, а не из частей.
Что вам нужно, так это цикл for, и внутри этого цикла for вы можете использовать sample
метод from 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, для более сложных первый метод — очистка кэша — должен работать лучше.