-
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
Parameter-by-parameter continuation using featurizing #69
Conversation
…function; not the featurizing mapper in basins_fractions extracts attractors in all cases, this will be useful in continuation
…ough featurizing_find_and_match
Codecov Report
@@ Coverage Diff @@
## main #69 +/- ##
==========================================
- Coverage 68.47% 66.52% -1.95%
==========================================
Files 21 22 +1
Lines 1126 1180 +54
==========================================
+ Hits 771 785 +14
- Misses 355 395 +40
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
…gh featurizing; I realized that the ics cannot be re-generated consistently from the sampler if the ics are originally generated in a threaded loop - the uncertain order of the threads makes the access to the sampler unpredictable, and so impossible to re-generate
Part of the code in this PR was offering support for extracting attractors in the Featurizing case when But I just realized that this can't be done when the feature extraction is parallelized: the initial conditions can't be re-generated from the sampler function if they are originally generated in a threaded loop. The uncertain order of the thread accesses makes the access to the sampler unpredictable, and so impossible to re-generate. Simple parallelizing is in general much more useful than saving up memory, I am deleting these attempts. Therefore, the continuation needs to be done by giving a Dataset with the pre-generated initial conditions, so that the attractors can be regenerated. This is working fine on the tests I'm doing. |
fs, _ = basins_fractions(mapper, ics; | ||
show_progress = false, N = samples_per_parameter, additional_ics | ||
) | ||
current_attractors = mapper.attractors |
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.
We have the extract_attractors
backend. The method dispatch on the mapper type.
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'll change it!
# If there are any attractors, | ||
# match with previous attractors before storing anything! | ||
rmap = match_attractor_ids!( | ||
current_attractors, prev_attractors; distance, threshold |
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.
In this method you compare de distance between trajectories that spans the attractors. Can we compute the distance between each clusters of points in the feature space? Is it more reliable than matching trajectories?
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.
So matching by comparing distances between the features, instead of attractors? It's a nice idea. As I understand, this could be done by the user via the distance
function, right? Receive the attractor, extract the feature and compute the distance.
One advantage of matching directly by the features is that one wouldn't need to reconstruct the attractors, and so could still use ics
as a sampler function. But I think the generality of having the attractors (generated by having ìcsas a dataset) outweights the memory savings of having
ics` as a function. What do you think?
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.
So matching by comparing distances between the features, instead of attractors? It's a nice idea. As
@KalelR that's what I was trying to tell you in-person in Portland... That you convert the clusters into StateSpaceSet
and then call the match_attractor_ids!
function on the clusters themselves. The function doesn't know what an attractor is; it could be an actual attractor or any StateSpaceSet
.
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.
With this matching process, you completely alleviate the need to re-construct the attractors and to store/find an initial condition to go to each attravtcort. Yet you still keep the slice-by-slice continuation in featurizing that you want.
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.
You can match a subset of the cluster to avoid a memory bottleneck.
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.
point is that, if you reconstruct the attractors, you can still do that (just extract the features again) but also much more (simple example being Euclidean distance).
Yes, I understand this. What I am not sure is whether there is benefit in mixing the two approaches in this way. The benefit of the recurrence approach is the rigorousness that you have a guarantee that you find an attractor, while for featurizing cluster != attractor.
do you guys think that this is not worth it? That if the attractors have been identified by clusterizing the features, then they also should be matched by comparing the features?
I am suggesting that, however I would like first to see results of matching directly on the feature space before converting to attractors. I think this is the best option. But I could be wrong, and what you prpose, to go for feature space to attractor space, then match, and then go back again, could be a better approach. It is much more complicated though both logically and in terms of code. So I would still argue with should first try parameter-by-parameter matching directly on the feature space, simply by considering each cluster / group-of-features as a StateSpaceSet and then literally calling the match_attractor_ids!
function.
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.
p.s.: Sorry for the late reply.
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.
Is there a metric to measure how good is the matching between two clusters of features? For example distance correlation would be an example.
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.
good idea!
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, I'm not sure because this measure is invariant w.r.t. absolute position of the clusters. While for us this is crucial. If one cluster is identical to the other but shifted by 10 in each dimension, these should be totally different clusters / attractors.
bump @KalelR |
1 similar comment
bump @KalelR |
Hey, yes! I'll work on this and the other related projects this weekend/next week. Will update this soon :) |
Hey guys, sorry for taking so long to come back to this. I still have some questions I'd like to understand your point of view about before proceeding. I'm asking these questions because I'm thinking of my use-cases, but maybe there are others I haven't considered. To recap, the continuation should:
The matching can be done in 3 ways:
My main question is: what is the point of doing the matching 1 (via clouds of features)? The arguments as I see are
Further, say we choose to the cloud of features. As Alex said, using all of them might use too be much memory, or be too slow. Then we would need to select a few. How do we this in an objective way? |
Hey, sorry for taking long to reply! So, here is how I see things:
Heh, but here is where I see things differently. This is one way to get "one feature per attractor". But another one is to get the centroid of the features. Which is a natural usage of the That is why, all the way from the start, I was arguing in favor of matching directly on the cloud of points. Maybe i wasn't making myself clear, but thankfully you reached the same conclusion. So here is how I see it going:
That's it. You have to write very little source code with this approach. (Hence, I would argue, if you go with this approach, please start a new pull request). What remains to be discussed is if we believe there is any gain in the functionality of this PR, that "extracts" attractors from the grouping_featurizing method. I am not sure about that. At the moment, what does the function |
Using the |
bump @KalelR |
1 similar comment
bump @KalelR |
(also probably better to start a clean PR) |
See |
So far the only continuation method using featurizing is the global pool version, based on MCBB. But there's no reason why we can't do a parameter-by-parameter continuation like with the recurrences method. This pull request implements this method, based heavily on the code for the recurrences. There are very few changes needed to do this. The idea is that:
basins_fractions
usingAttractorsViaFeaturizing
. Then you extract the attractors from this by re-integrating attractors from one initial condition belonging to each cluster you found.ics
from previous attractors and use them as additional seeds for the subsequent parameter value. This is the biggest difference to the recurrences version. For featurizing, theseadditional_ics
need to be put together with the normally sampledics
and clustered together. What I did was to add anadditional_ics
keyword tobasins_fractions
, which receives these ics, extracts their features, and adds these additional features to the normal features Dataset. This was the least disruptive way I found. Note that, to ensure that theic
from each attractor will be characterized as an attractor, it is repeated amin_neighbors
number of times.What I did was:
extract_attractors
function for whenics
are a sampler function. For this, thesampler
function is deepcopied, then one copy is sent to extract features, and another sent to regenerate the attractors.seeds_from_attractor
function for the featurizingFeaturizingFindAndMatch
and a newcontinuation
function in thecontinuation_featurizing_findandmatch
file.Note that the changes are small enough that we can unify both methods in the same function, reducing the duplication. I'm opening the pull request to let you know about this and hear your insights. The code design can still be improved for sure!
I have tested this for lorenz and it seems to have worked, but I'd still like to test more become merging.