-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add support for symbolic initval using a singledispatch approach #4912
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
Conversation
I appreciate you looking into this too, @kc611, but I see several disadvantages of the singledispatch approach:
Unrelated to the concerns above, I will now cherry-pick some changes from #4867 to a separate PR so these diffs become easier to read. |
I agree. There is one advantage however. The method can be (re)-used in other places. For example I think the old |
0d84d49
to
c77f7a0
Compare
c77f7a0
to
8ecd0e8
Compare
What is this measure of "spread all over the place" and what makes it relevant? From what I can tell, this is putting the initial value computation logic within the types/classes to which it corresponds. Would you rather have all this logic implemented as a bunch of fixed If you add methods to If you're not aware, dispatching/generic functions like these are another approach to the same functionality that class methods provide—albeit with different forms of flexibility.
Is this "one" class method approach able to accomplish exactly the same things? It looks like these changes allow one to set the default initial values for
In what sense does it "act on If you're referring to how
We're trying to assign initial values to random variable/distribution types—both at a conceptual level and at the type-level; that's the objective, and that's what this approach is doing. How are you proposing it be done without associating initial value computations/choices with All these arguments are phrased as "cons", but I'm not seeing any real implementation or design issues being raised. If you don't like the approach used in this PR, that's fine, but stating so in this way isn't very helpful. If you don't understand what these changes are doing or why, asking questions is better. |
Just a note that I refactored (and broke) the code quite a lot after @michaelosthege comment above, so the discussion could be a bit misplaced. |
8ecd0e8
to
46940ae
Compare
It's not misplaced, since all the relevant comments are basically only about using a dispatch-based approach, and that hasn't changed. |
46940ae
to
ec9124e
Compare
Codecov Report
@@ Coverage Diff @@
## main #4912 +/- ##
=======================================
Coverage 74.13% 74.13%
=======================================
Files 86 86
Lines 13882 13898 +16
=======================================
+ Hits 10291 10303 +12
- Misses 3591 3595 +4
|
ec9124e
to
f6cb942
Compare
Re-running tests to check if failure is flaky. |
f6cb942
to
ba93578
Compare
@kc611, just a heads-up: yesterday @ricardoV94, @twiecki and I discussed about ongoing initival efforts and we found a way to disentangle and resolve some of the implementation difficulties we're having with different approaches. We came up with the idea to think of a singledispatch-based re-implementation as something independent from initial values. @ricardoV94 @twiecki please comment/edit if I mixed up something. |
Is this still required with #4942? If it is, we should probably change the naming here a bit like @michaelosthege advised above. |
Yeah you still need this (i.e. the "moment" thing, not the symbolic initval). For transformed unconstrained variables we can do like STAN [uniform -1, 1], but unlike STAN we also sample constrained variables, in which case we still need a way to specify a stable starting point for those distributions. |
ba93578
to
b3cfab8
Compare
pymc3/distributions/distribution.py
Outdated
Parameters are the same as for the `.dist()` method. | ||
""" | ||
|
||
return _representative_point(rv.owner.op, rv, *rv.owner.inputs[2:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually size in input[1]
, input[2]
is dtype,
cfdfc5e
to
e4f03e5
Compare
pymc3/tests/test_initvals.py
Outdated
class TestMoment: | ||
def test_basic(self): | ||
rv = pm.Flat.dist() | ||
assert get_moment(rv).eval() == np.zeros(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A random draw from a scalar RV has a shape == ()
. Shouldn't the moment have the same scalar shape?
@kc611 do you know what's up with the unit tests here? |
Ah, these failures are due to #4961 (comment), rebasing should fix them, Infact this PR should be marked ready to merge. (If the |
@kc611 want to rebase then? |
fee76c1
to
e89684f
Compare
Asking the unpleasant question: Which moment will (Or will there be a mechanism where this can be configured in some way?) Also please check my comment from above - Don't know if you fixed it, but IIRC I saw something looking like a shape problem around the corner. |
Yeah there will be some other mechanism according to #4912 (comment) , this PR just implments the
Just saw it. The shape problem seems to be something of a limitation caused by |
e89684f
to
65b0680
Compare
Turns out it doesn't :-P Looks like the And I was wondering why I (mentally) put a green check on this in the first place. Turns out the newly added tests pass without the Meanwhile we can use this PR to plan and implement the new functionality that was being planned in #4942 |
I could not quite figure out what was the point of multiple moments. I think it was more a question of having at least one good moment for each distribution, and perhaps having a discrete alternative for continuous distributions. For the latter, it should be enough to just round the output if a discrete initval from a continuous variable is needed. |
My point is kinda that I don't want to make that decision. In If the |
I don't think the multiple moments were there for the user convenience. They were not even advertised on the docs. |
dbf6c18
to
46cb30a
Compare
Thanks @kc611! |
def get_moment(rv: TensorVariable) -> TensorVariable: | ||
"""Fallback method for creating an initial value for a random variable. | ||
|
||
Parameters are the same as for the `.dist()` method. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this was merged already, but this part of the docstrings is wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, we should fix that then. CC @kc611
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes I missed that, those docstrings were supposed to be removed.
I'm not sure what (docstring) will go in it's place though. Maybe I should just remove them for now ? We can add a proper explanation when we give the get_moment
a proper entry point in the initval
framework (if that's being planned)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, then just remove them for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did it in #4979
This PR was built upon #4867 as an simpler
singledispatch
based alternative.Also Fixes: #4911
cc @ricardoV94 @michaelosthege