-
Notifications
You must be signed in to change notification settings - Fork 15
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
Composable scalar transforms #128
base: master
Are you sure you want to change the base?
Conversation
I've added some scalar consistency tests now, which pass, with this new API. If there are some other obvious tests, I am open to suggestions. Still missing is any treatment of non- New questions
|
Some other ideas I had but which haven't tried out yet (note to self as much as anything else)
|
I decided to add a I haven't thought deeply about what this current implementation will do with real number types, e.g. As far as using this to introduce Unitful support, I see two main options:
In case 1, new number types each need their own extension. In case 2, inverse transforms will not yield original types. |
I think this is shaping up nicely, thanks for the work! Sorry I have been very busy with a project and failed to provide any feedback so far, I will try to make up for it now.
Chaining just multiplies the Jacobians, so abs(log(...)) Jacobians are just added up. It should be something like
I think that is OK, I think we should just clarify the API for |
I went ahead and tried out replacing the
|
I guess if we take this approach and have a |
Okay, tried widening types, etc. to accomodate Unitful types. For now, that means that A quick check suggests that Should that be explicitly documented as not working for dimensional quantities? Is there a different way to treat the log-Jacobian? |
I don't think it makes sense, so it should error. Specifically, we should document that |
Okay, I've implemented it that way and added a note to the docs. I have With that, I'm not thinking of anything else that's missing from this implementation. Is there anything still on your list? Does it need more documentation or anything? Should we delete the |
…or; add new scalar show tests
I went ahead and added an alias I've reworked the scalar show behavior so that all the old show tests still work. With that, I don't think we're breaking any API, just adding new features. I think everything on my list is working at this point. Anything else you want to see in this? |
(Remaining question: should we delete the |
Sorry, I had computer issues and I am still catching up with FOSS work, will try to review the whole thing ASAP. |
…r than alias for composition operator
This PR already makes |
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.
Thanks for all the fixes, this is shaping up nicely so just minor comments. If benchmarks show no regression, this is good to go.
Sorry, I take it back, I forgot that we never exported If the benchmarks show no regression, I think this is good to go. |
Pretty simple benchmark, let me know if this is incomplete (first time really investigating something like this): using TransformVariables
using BenchmarkTools
const TV = TransformVariables
btrans(t) = inverse(t, transform(t, rand()))
blogjac(t) = transform_and_logjac(t, rand()) t1 = TV.ShiftedExp(true, 4.0)
t2 = as(Real, 4.0, ∞)
@benchmark btrans(t1)
@benchmark btrans(t2)
The other benchmarks @benchmark blogjac(t1)
@benchmark blogjac(t2)
t3 = TV.ShiftedExp(false, 4.0)
t4 = as(Real, -∞, 4.0)
@benchmark btrans(t3)
@benchmark btrans(t4)
t5 = TV.ScaledShiftedLogistic(2.0, 2.0)
t6 = as(Real, 2.0, 4.0)
@benchmark btrans(t5)
@benchmark btrans(t6) all look basically the same, the finite interval takes slightly longer than an exp (as expected) but the two implementations are indistinguishable. While I'm thinking about performance, it bears mentioning that, in the test suite, the tests where I compose lots of arbitrary transforms take a lot of time to compile. For example, @time begin
all_transforms = [TVShift(3.0), TVScale(2.0), TVExp(), TVLogistic(), TVNeg(),
TV.ScaledShiftedLogistic(2.0, 1.0), TV.ShiftedExp(true, -5), TV.ShiftedExp(false, 4.5)]
for t1 in all_transforms, t2 in all_transforms, t3 in all_transforms
t = t1 ∘ t2 ∘ t3
t isa TransformVariables.CompositeScalarTransform{Tuple{typeof(t1), typeof(t2), typeof(t3)}}
end
end takes 5 seconds to compile the first time, then something like a millisecond to actually run. I don't know if that's a quirk in how I constructed the test. The tests still only take a couple minutes to run. |
This is very much still WIP, but took a stab at constructing something like discussed in #95 and #126 . As of yet, I haven't even tested that this runs, much less correctly; will come back when I have more time.
One major question: for things like mapping to negative reals, I am imagining
Scale(-1) ∘ Exp()
. In this case, should the log-Jacobian ofScale
belog(abs(scale))
?