Извлекать сюжет из игрушек в zFit

#zfit

#zfit

Вопрос:

Прежде всего, я хотел бы сказать, что у меня есть концептуальные трудности с этой темой, поэтому, пожалуйста, поправьте меня, если мое намерение не имеет смысла.

Я пытаюсь проверить модель, которую я использую для извлечения выхода сигнала из дистрибутива. Для простоты предположим, что есть только распределение сигнала и нет фона. Модель представляет собой стандартный файл Gauss, и я создал расширенный PDF-файл.

По моему мнению, я бы создал образцы данных из этого PDF-файла и изменил только количество событий, то есть только масштабирование. Затем я бы поместил этот образец toy и сравнил сгенерированное количество событий с установленным выходом сигнала путем вычисления

pull = (N_generated - N_fit) / sigma_Nfit

Чего я не понимаю, так это как я устанавливаю и получаю сгенерированное число. В поколении я хочу установить количество событий случайным образом (я думаю, Пуассон распределен?) и сохраните все остальные параметры модели фиксированными.

В итоге у меня есть распределения сигнала фона и я хочу:

  1. изменять количество сигналов фиксировать количество фонов
  2. исправить сигнал изменить фон
  3. изменить дробь в 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, для более сложных первый метод — очистка кэша — должен работать лучше.