Skip to content

Fix pdf() function#799

Merged
klemens-floege merged 2 commits into
mainfrom
klemens/fix-pdf
Feb 27, 2026
Merged

Fix pdf() function#799
klemens-floege merged 2 commits into
mainfrom
klemens/fix-pdf

Conversation

@klemens-floege

Copy link
Copy Markdown
Contributor

#796 highlighted that we might have a problem with the pdf() function that returns an inverse probability as opposed to the actual probability.

This PR now fixes the pdf() function, the function is not used in our repo, since it is external API we could just leave it in?

TabPFN) klemensfloege@Klemenss-MacBook-Pro TabPFN % python3 reproduce_pdf_bug.py
forward() (NLL = -log p(y)): 1.092203
Buggy pdf()  = exp(NLL):     2.980833
Correct pdf  = exp(-NLL):    0.335477

buggy_pdf * correct_pdf = 1.000000  (should be 1.0 if they are inverses)

my script:

"""Reproduce the pdf() bug in FullSupportBarDistribution.

The forward() method returns the negative log density (NLL loss), i.e. -log(p(y)).
Therefore:
    pdf() = exp(forward(logits, y)) = exp(-log(p(y))) = 1/p(y)   <-- WRONG
    pdf() = exp(-forward(logits, y)) = exp(log(p(y))) = p(y)      <-- CORRECT
"""

import torch
from tabpfn.architectures.base.bar_distribution import FullSupportBarDistribution

# Create a simple FullSupportBarDistribution with uniform-width buckets
borders = torch.linspace(-3.0, 3.0, 102)  # 101 buckets
dist = FullSupportBarDistribution(borders)

# Create fake logits (batch of 1) and a target value
logits = torch.randn(1, dist.num_bars)
y = torch.tensor([0.5])

# Get the NLL from forward()
nll = dist.forward(logits, y)
print(f"forward() (NLL = -log p(y)): {nll.item():.6f}")

# Current (buggy) pdf: exp(NLL) = exp(-log p(y)) = 1/p(y)
buggy_pdf = dist.pdf(logits, y)
print(f"Buggy pdf()  = exp(NLL):     {buggy_pdf.item():.6f}")

# Correct pdf: exp(-NLL) = exp(log p(y)) = p(y)
correct_pdf = torch.exp(-nll)
print(f"Correct pdf  = exp(-NLL):    {correct_pdf.item():.6f}")

# Verify: buggy_pdf * correct_pdf should equal 1 (they are inverses)
product = buggy_pdf * correct_pdf
print(f"\nbuggy_pdf * correct_pdf = {product.item():.6f}  (should be 1.0 if they are inverses)")

# Sanity check: a density value > 100 or < 1e-6 is suspicious but possible;
# however the product being 1 proves they are exact inverses.
assert torch.allclose(product, torch.tensor(1.0), atol=1e-5), (
    "Bug confirmed: pdf() returns 1/p(y) instead of p(y)"
)
print("\nBug confirmed: pdf() and correct_pdf are inverses of each other.")
print("The fix: change `return torch.exp(self.forward(logits, y))`")
print("     to: `return torch.exp(-self.forward(logits, y))`")

@klemens-floege klemens-floege requested a review from a team as a code owner February 27, 2026 12:43
@klemens-floege klemens-floege requested review from priorjulien and removed request for a team February 27, 2026 12:43
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@priorjulien priorjulien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@klemens-floege klemens-floege added this pull request to the merge queue Feb 27, 2026
Merged via the queue into main with commit 56d35b4 Feb 27, 2026
13 checks passed
brendan-priorlabs pushed a commit that referenced this pull request Mar 19, 2026
ggprior pushed a commit that referenced this pull request Mar 26, 2026
ggprior pushed a commit that referenced this pull request Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants