-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Future option: Express mass/normalization of densities #8
Comments
Hm, I wonder if something like this could go into Distributions? |
The real use case of this IMHO is the query "is something a probability density". But that should then be available to PPLs too, since there we have all kinds of densities that we know are not normalized. So if this is deemed a good idea, I'd rather have it here. |
What do you think about my proposal at the (current) end of #5 regarding adding |
I wouldn't think that makes a difference; being a measure doesn't tell you anything about normalization (or being a probability measure). A third approach, where you only have to define hasnormalizingconstant(d) = normalizingconstant(d) isa Nothing
normalizingconstant(d) = nothing
normalizingconstant(d::SomeDensity) = ...
isnormalized(d) = normalizingconstant(d) == 1 |
We could call it |
Having a |
I think I like that idea. It seemed to me that it would be nice also be able to express "infinite norms" (as there is a semantic difference between "finite but unknown constant", as in posteriors, and "known to be non-normalizable"). With your approach, it would work out, right? logdensitynorm(d) = missing
logdensitynorm(d::Distribution) = 1
densitynorm(d) = exp(logdensitynorm(d)) will propagate the densitynorm(d::Lebesgue) = Inf
# default: logdensitynorm(d::Lebesgue) = missing with somewhat consistent behaviour. So it seems nice on the first glance, but I'm not confident enough to judge downstream effects. |
Yes, I think so. But maybe the name Then, for Bayesian inference, we'd have |
Hm, maybe using |
Yeah, I really wouldn't use |
What could we call it so that it would also make sense for densities (as the integral of the density function over it's support)? |
What is the norm of |
"Norm" and "normalize" are very overloaded, which is why we went with |
I like those. I think defining those as abstract function in DensityInterface could be very handy. We often do use the term "norm of a density", we say the "PDF is normalized" and so on. So it's not just useful for MeasureBase, it's also useful for densities (density functions). We do of course mean the integral in respect to an implied base measure - but that's the same as using an implied base measure in `[log]densityof], so it would fit in quite neatly. What do you think about this, @devmotion ? |
Here's some more context: For a trait-based approach, I can see a few situations we'd want to distinguish:
|
Do we have a good package for static numbers that can represent infinity? Then All of those results could be dispatched upon, giving you that trait-based approach. |
I think I'd go with Static.jl and Infinities.jl, so |
Nice! We wouldn't need these as dependencies for DensityInterface, even - we would just define function logmass(object)
if densitykind(object) <: IsOrHasDensity
missing
else
throw(ArgumentArror("object is not and does not have a density")
end
end Implementations of densities and measures can then return a real number or a static something as fits the case. |
When the user gives a function and says "treat this as a density", they need to be able to specify which of these cases we're in:
Otherwise we'll end up wasting lots of cycles on quadrature. |
Maybe this goes a bit for things "that are a density or a measure", though? This may be better situated in MeasureBase. |
So things defined outside of MeasureBase will just be treated as completely unknown, and always use quadrature to get an approximate mass? That seems very limiting. |
Well, there's isn't that much, right now: Other densitiy types can have a mass, too, of course - but the best place to take care of that it is the the package that provides that density type, I would say. Fully generic and automatic quadrature is hard to provide anyhow - there are many different algorithms and not all suit every situation. If the mass has to be estimated numerically, this won't work without involving the users in higher-dimensional cases, I would say. |
Ok, so we need to be able to specify these things somewhere. It sounds like that will need to go into MeasureBase, and users of |
I thought we can maybe add something like
to DensityInterface (though the function name The more detailed stuff I would propose to leave to MeasureBase. |
How about
I don't see how this would work. The type produced by |
Yes,
No, indeed - |
Of course @cscherrer has already put thought into this before us 😀 I like Of the five possibilities Chad mentioned, all except (3) are simple to handle: values of either (3), however, is an outlier -- a set-like restriction of the above ("any finite real number") and harder to represent by types. I can see why it's very useful, though. I suppose an additional type like
You mean StaticValues.jl? And what is |
I would say infinite as well, since |
Oh, right... for whatever reason I have assumed that |
No worries. :-) |
Oh, I'm using "probability measure" as "the mass is known to be 1", and would only use it as a contingent notion. Are you referring to usages such as "unnormalized probability measure"? Of course, if you understand it that way, the four properties are overdetermined. |
Right, things get a lot easier if |
Yes, but then I don't get your point about the "overdetermined system". We can have Or we have Are you talking about the interpretation of "
But I don't see such a conflict arising. If an density If that's not what you're talking about, please give me a counterexample :D |
I suspect (but am not sure) that our misunderstanding arises because I for now think about the density objects first, with the base measure just being additional information telling us about "support" (really just "PMF or PDF?"), while you are always starting from measures first and most importantly, and the RD-derivative resulting as a consequent therefrom. But that is because I try to put myself into the head of the possible measure-theoretically unaware end user. |
Yes, cached results could be useful to handle "properties" of things that can be expensive to calculate while still keeping things immutable (semantically). |
Ah, but posteriors are measures, not densities. So they have a mass that doesn't depend on the choice of a base measre. So they should implement the MeasureBase interface, like Distributions hopefully will, soon. Correct, @cscherrer ? |
Thanks @phipsgabler . I agree with most of this, but a couple of pieces are very confusing.
Those are very different things
No, it's easy to define a measure without knowing what it integrates to.
This sounds right to me. Let's step back for a second. If a user gives a density |
But if I can do that, I've kind of turned my density into a measure already, right? After all, to normalize it I have to "measure" it. |
@phipsgabler I guess the question is, are there use cases where we would want to do something like integrate a likelihood (without the prior). |
Even before that! If you (implicitly) assume Lebesgue base measure, then the density already determines a measure. |
Right, that's what I meant. It's definitely a useful concept get the "default" density of a measure (or we wouldn't have DensityInterface provides a way to get log/non-log density functions for both density objects and measure objects (the latter using an implied base measure). One typical use case is the (not uncommon, in practice) formulation of Bayes theorem that use density functions for likelihood, prior and posterior (with an unconsciously implied common base measure like Lebesgue). DensityInterface also provides a way to construct density object from a log/non-log density function. This allows users to define (just as an example) a likelihood, a representation of a (density) function that can be passed around without having to track if it's defined via a log- or non-log-function. The question is, I think: Should DensityInterface provide a way to construct a measure object from a log/non-log density function (using an implied base measure). Maybe no, because taking a measure (in |
Hm, maybe two thought experiments:
But the thing is - given just a plain density function, I can assume a sensible base measure and integrate it. But - have I created a measure or a physical object? Given just a function, there's no context to build it, and DensityInterface doesn't have the type(s) to represent it. |
Yeah, but they always have densities, right? Because that's how we use them -- evaluating their densities at points. The measure always exists in a theoretical sense, but often, we can't automatically construct it, for technical reasons (it requires static analysis of a probabilistic program etc.). But you could, e.g., have the user explicitely add the base measures they intend (which will be Lebesgue and counting for contininuous and discrete parameters, right?).
Ah, yeah, sure -- sorry for being sloppy again... what I mean is of course "in the context of MT, where
That's exactly what I'm thinking of, yes! Except that if the Now, for the following I fear we stray into fundamental discussions again, but let me answer one point...
I see what you mean there, but I think that's the line we should not cross in DensityInterface. IMHO it is good to set up things so that the "implicitly existing base measure" view is always sane and can be justified, but not to actually do (and thereby "force" unto users) the measure theoretic notions. When you want to get the "real measure" from the density object, do it using MeasureTheory. Also, by just saying that we talk about masses doesn't force us to commit to a full interface for integration. Also that should, IMHO, be left to either MeasureTheory proper, or the packages doing the actual integration (which may then depend only on the density object and their own extra information, like base measure or support.) That being said -- my naive idea was to just define the
If that is not a reasonable idea -- what, for example, is the current design of MeasureTheory's |
Thanks @phipsgabler . Normalization will be really important for MeasureTheory, so I want to be sure the interface is MT-friendly. We haven't implemented When a user builds a new measure, they can either specify the mass or leave it to be determined. In some cases the code should be able to prove some things about this. For example, if you start with a finite measure, restricting it will result in another finite measure. That kind of thing. This is the idea behind the different "classes" I proposed, and why I think a trait representation could make sense. If the user doesn't specify a mass, but asks one, we need to be able to represent that. But we don't want to implement quadrature, or impose a specific method, or depend on every package we know about. So the result here would probably be a new The user should also be able to ask for a normalization of a given finite measure. Here again, we'd probably have a first-class representation like a An important aspect of this is that individual evaluations of log-densities include the indeterminacy, but taking differences of these must allow it to be canceled out. In this way it feels a little bit like the provenance tracking done in Measurements, that allows making sure that There's a lot to this, which is part of why we haven't gotten to it yet. |
@cscherrer , so you have something in mind like That may be very user friendly. And if it that would accept a DensityInterface-compatible object as But: If there can be @phipsgabler , maybe we should explore the concept of |
Interesting, I hadn't thought of that. So here
Mass is a characteristic of a measure. Once you have a measure, the (base measure, density) pairs are just different ways of expressing it. Or to put it another way... Given a density, the base measure is only relevant for determining the measure. So "the mass of a function" doesn't really make sense, you need a base measure. But the reason you need it is so the measure itself is determined, which in turn makes the mass well-defined. |
I think that's a reasonable approach, if the ultimate goal of generalizability to DensityInterface and "implicit base measure densities" is always kept in mind (to avoid a situation like the retrofittting of |
@cscherrer about the possible return values -- would that then be
? |
This sounds at least pretty close. The completely unknown case could still be represented as an integral to be passed to outside quadrature routines. Then we still need to distinguish the "I only know this is finite" case. There are lots of different types here. Should everything be under a hierarchy? There are some tradeoffs, but it could be useful for dispatch. Maybe something like abstract type AbstractMass end
struct UnknownMassOf{T}
measure :: T
end
struct UnknownFiniteMassOf{T}
measure :: T
end
struct KnownFiniteMass{T}
mass :: T
end This is a rough sketch, but in the unknown cases we would need to refer to a fully-determined measure (Maybe density function over Lebesgue, but "density function over unknown base measure" isn't enough). If the mass is known, I think there's no need to keep the reference to its origin. |
Yes, I maybe a "decorator" approach is more composable/flexible here. So
I guess a lazy value could be returned in that case (so that integration is only run if needed)? I think we have packages for lazy values, but I haven't looked into that area for a while. There's still the question of algorithm choice. Maybe it would be better to return a trait that says "it has a norm, but the value is unknown, you need to integrate". Then the user can integrate with a suitable algorithm, and create an new measure object that includes the mass information, e.g. via |
Any updates here? I think we should commit to this being in MeasureBase or MeasureInterface. We've already complicated things there to conform with DensityInterface, and it will quickly get out of hand and be hard to reason about if we push that farther. |
Yes, having it in the measure theory ecosystem will be easiest for now. If we see a need and a path to move it to DensityInterface later on (one the dust around Distributions and MeasureBase has settled) we can still reopen this. Ok with you, @phipsgabler ? |
I agree for now. But in the long term, I'd absolutely want to get this working for measure-oblivious applications. |
Let's keep this open as a reminder for the future then. |
I've been previously thinking about whether and how a density interface should include the possibility to require or check for normalization, so I'm just posing this for discussion here.
Options that come to my mind:
Or maybe include a whole machinery for dealing with normalization constants?
The text was updated successfully, but these errors were encountered: