-
Notifications
You must be signed in to change notification settings - Fork 6
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
example showing how to use update!(model, table) #34
Comments
See the tests here: We should probably document everything better some day. You cant set anything individually yet, because we are using Flatten.jl to just replace all the parameters at once. But we could write something to flatten the model, change a particular row, then rebuild it. I guess that would be useful. Like For now you can use Setfield.jl/Accessors.jl to vals = model[:val]
model[:val] = @set vals[7] = some_newal If you want to add methods to |
I almost submitted the same issue a few hours ago, but for the out-of-place Base.@kwdef struct MyParams{A, B, C}
a::A = Param(1.0, optimizable=true)
b::B = Param(2.0, optimizable=false)
c::C = Param(3.0, optimizable=true)
end
model = Model(MyParams())
update(model, rand(2), x -> x.optimizable) # does not work (trying to update only the "optimizable fields") Since this is so close to what I was thinking of, I thought I should just chime in here... |
Just throwing this a bit randomly as a follow-up on a discussion with @rafaqz: Thinking about a generic term to distinguish parameters that one may want to (As usual, disregard if stupid/useless comment 😅) |
Yep that will do it! We could make a bunch of For now you can just define those yourself until we settle on names: struct FreeParam{T,P<:NamedTuple} <: AbstractParam{T}
parent::P
end
FreeParam(nt::NT) where {NT<:NamedTuple} = begin
_checkhasval(nt)
FreeParam{typeof(nt.val),NT}(nt)
end
FreeParam(val; kwargs...) = FreeParam((; val=val, kwargs...))
FreeParam(; kwargs...) = FreeParam((; kwargs...)) Then the change we need to make is to the params(x; select=SELECT, ignore=IGNORE) = Flatten.flatten(x, select, ignore)
stripparams(x; select=SELECT, ignore=IGNORE) = hasparam(x) ? Flatten.reconstruct(x, withunits(x), select, ignore) : x Also add Only thing is it looks a bit funny in model[:val; select=FreeParam] And you should be able to do everything we talked about. I can put together a PR to do this properly, we could have a |
that looks nice. But, one needs to call first
|
Oof yes that's ugly. Lets wrap that. It will need some tweaks to work with ConstructionBase.jl (an embarrassing omission on my part) but you should just be able to do As I said to @briochemc I pretty much left this package in its initial state, waiting for some users with feedback like this as to how to improve it. So things will get better, just not that many people have cared enough yet or pointed out the flaws. |
Doing
|
Yeah that's what I mean... it should but doesn't. We can make it work by definining |
@lazarusA I'm still thinking about how best to update parameters by number as well as type here, I think we may as well have both? |
yeah probably, type will be very useful as well. Also I noticed that as it is now if you do the following
is not the same as
which does the intended. |
Works for me? You need to do: m = @set m.a.val = 2 Or use Setifield.jl returns a new object rather than updating the field, as its made for immutables. I would just drop the |
I kinda want to keep the mutable part. Not sure about the overhead of the reassignment when you do this thousands of times and the |
immutable is almost always faster |
I have another scenario where
in this case it will update the |
@rafaqz @briochemc As mentioned in #39, I would push back against using type matching to accomplish this. This has the (imho significant) disadvantage of hard-coding into your types what is effectively just a property, as demonstrated by @briochemc 's example. This means that, in order to change which parameters are "optimizable" (sticking with the same use-case), you would need to either go into your code and change I would be more interested in simply implementing the idea for TL;DR; I think the concept of selecting which |
It's also worth noting that any custom subtypes of |
That redundancy is common to all inheritance in julia. The additional constructors that do all the work can be generalised to struct FreeParam{T,P<:NamedTuple} <: AbstractParam{T}
parent::P
end But your other points are correct. It's not so great for selecting what is optimisable, (although we can just add The reason to use types is it's easy to plug in to essentially every function in the package, because that's what Flatten.jl does already. This solution is also easier to get type stable for getting/setting the subset of params quickly, as may be required when optimising. See the PR #39. |
I don't think so. That depends on how you use inheritance. I typically use inheritance to group related types together and to facilitate sharing of method dispatches. I really try to avoid this kind of inheritance where you make assumptions about the actual structure of the types and/or their constructors, as opposed to making assumptions about available method dispatches (e.g. Yeah, I guess a macro can help ameliorate this, but I think it's better to avoid introducing macros unless really necessary. They obscure the meaning of the code to an unfamiliar reader and add an additional cognitive hurdle to understanding how the package actually works. |
We already use a method for I get your gripe, bit it really is minor. This is very little boilerplate. An alternative is to add another free type parameter to The other option is the |
My gripe isn't really the boilerplate, I agree that this is minor. It is more that I think this is a misuse of inheritance, and it's not clear to me what the gain is versus using the flexibility |
Pretty sure this is not the correct way of doing this (because a lot goes over my head), but did you mean map(x -> x.val, filter(x -> x.optimizable, ModelParameters.params(model))) |
Sorry for the word salad coming below, but another thing maybe of interest would be to be able to change the type (with the out-of-place For example, take a model m = (
a=Param(1.0, optimizable=true),
b=Param(2.0, optimizable=false)
) where updated_m = (
a=Param(1.0 + 1.0ε, optimizable=true),
b=Param(2.0 + 0.0ε, optimizable=false) # note the "useless" dual value here
) This might then slow down calls to (I'm guessing this might be all completely unnecessary if one could memoize |
Yes, all fine, the implementation of
would have to assume that the given vector matches the length of the parameter subset induced by the predicate. It would internally map over the full There would be issues with making this type stable because obviously the length of the parameter subset is not known at compile time, but I think this might be solvable by creating a |
Yes, that's pretty close to what I meant. |
Sorry about that... hit the wrong button. |
Hi,
I was wondering if you be so kind to upload an example where a table is used to update the model parameters.
Also, not sure from the documentation: is possible to just update a few parameters? because let's say the table is incomplete or I just need to update some of them.
The text was updated successfully, but these errors were encountered: