Generalize TransferOperator#434
Conversation
|
is there any paper in the literature that has generalized the transfer operator like this? Among other outcome spaces? if not, perhaps you can consider making this a paper. |
At least I am not aware of any such paper. Would be a cool contribution for sure! |
|
@rusandris Thanks for the PR! I am super busy at the moment, so I'm not able to review this in detail yet. I'll try to get to it within the next couple of weeks.
I'll have to do a thorough review dig deeper to understand this issue. I'll ping you when I've tested this out a bit, @rusandris. |
Just to be clear: i have no capacity to be involved in such a paper, but it is worth discussing with your supervisor Andras. |
I looked inside julia> probabilities(TransferOperator(),op,x;N=5,tolerance=1e-12)
distribution = [0.28892942757860407 0.7110705724213959]
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
distribution = [0.28892942757860407 0.7110705724213959]
distance = 0.7778172853930047
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
distribution = [0.28892942757860407 0.7110705724213959]
distance = 0.7778172853930047
distribution = [0.7110705724213959 0.28892942757860407]
distance = 0.7778172853930047
Probabilities{Float64,1} over 2 outcomes
Outcome(1) 0.7110705724213959
Outcome(2) 0.28892942757860407reveals of course that it works as it should. Since the transition matrix looks like this to.transfermatrix
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
⋅ 1.0
1.0 ⋅ the iterative method keeps flipping the initial random values inside the distribution. This wouldn't converge, unless the initial distribution is already given as probabilities(RelativeAmount(),op,x)
Probabilities{Float64,1} over 2 outcomes
Outcome(1) 0.5
Outcome(2) 0.5 |
|
I've seeen some new commits here, but it's been more than a year since i've looked at this and have forgotten many things, let me know if there is something in particular you'd like help with, or to discuss, and I'll bring myself back up to speed! |
|
Thanks, great to hear! I'm still working on it, but in short logistic_rule(x, p, n) = SVector{1}(p[1] * x[1] * (1.0 - x[1]))
p = [r]
ds = DeterministicIteratedMap(logistic_rule, [0.4], p)
x, t = trajectory(ds, 10^3; Ttr=10^4)
b = ValueBinning(FixedRectangularBinning(range(0,1;length=11)))
probabilities(TransferOperator(),b,x)through The eigenvector method can be better for example when the time series is periodic: ds = DeterministicIteratedMap(logistic_rule, [0.4], [3.84])
x, t = trajectory(ds, 10^3; Ttr=10^4)
probabilities(TransferOperator(),b,x;method=:iterate)
Probabilities{Float64,1} over 3 outcomes
2 0.09340928604503983
5 0.23372777459244914
10 0.6728629393625111
probabilities(TransferOperator(),b,x;method=:eigen)
Probabilities{Float64,1} over 3 outcomes
2 0.33333333333333337
5 0.3333333333333334
10 0.33333333333333326Let me know how this looks for you. |
|
@rusandris, great stuff! 🤘Super nice that the eigenvector approach works well for periodic time series. This is a major improvement which may have advantages in e.g. reducing false negatives in settings where e.g. extensive pseudoperiodic surrogate testing is done for some statistic. For that reason I vote for keeping the dependency. One comment though: following the convention from the test of the packaged: any keywords that controls the probabilities estimation should be part of the discretization type ('TransferOperator'), not as a keyword to the 'probabilities' function. |
My thinking was the following (and I'm sure there are some workarounds/better ways to do this): the seemed too verbose and difficult. These types are supposed to be internal and are only used once which is what you mean, right? |
|
@rusandris Thanks again for your great work! I'll do a thorough review of this in the coming days. In order to not give conflicting feedback here, I want to familiarize myself properly with the changes before I respond in detail. But in short: Breaking changesI see that there is a breaking change (converting Internal dispatch
Something like that! For consistency with the rest of the code base, I think the following would work: probabilities(probest::TransferOperatorApproximation(::ApproximationMethod), o::OutcomeSpace, x)where probabilities(::TransferOperatorApproximationIterative,outcome_space,x)
probabilities(::TransferOperatorApproximationEigen,outcome_space,x)I just need to see how it relates to the manual extraction of the transfer matrix in your suggested code. Why we don't want extra keywords in the functionWe want the base functions like If we were to break with this convention for the transfer operator, then there would be hundreds of possible ways to discretize and estimate probabilities from data using one unified syntax, EXCEPT for the transfer operator approximation, which has an extra keyword for We set reasonable, well-documented default behaviours, but leave the user the option to be as granular as they want. |
|
Thanks for the suggestions! Now it's starting to shape up nicely, I would say. x = rand(10000)
op = OrdinalPatterns{3}()
probabilities(TransferOperatorEstimator(),op,x)where an probabilities(TransferOperatorEstimator(ApproximationIterative()),op,x)
Probabilities{Float64,1} over 6 outcomes
3 0.16324623547971576
2 0.1591237693781441
6 0.16384218566116265
5 0.17197826172205205
4 0.16785579628202602
1 0.17395375147689937
probabilities(TransferOperatorEstimator(ApproximationEigen()),op,x)
Probabilities{Float64,1} over 6 outcomes
3 0.16324623516644013
2 0.15912376937533454
6 0.16384218587939298
5 0.17197826206173342
4 0.1678557962706277
1 0.17395375124647128
Still work in progress though, it needs to be moved to |
|
Now the tests pass, finally. |
|
All right so here is a quick summary of the changes: Basic usage goes like: x = rand(10000)
op = OrdinalPatterns{3}()
probabilities(TransferOperator(),op,x)where TransferOperator, with 2 fields:
approximation_method = ApproximationIterative(200, 1.0e-8, 1.0e-8, Random.TaskLocalRNG())
boundary_condition = none
The approximation method can be of two types ( probabilities(TransferOperator(ApproximationIterative()),op,x)
Probabilities{Float64,1} over 6 outcomes
3 0.16324623547971576
2 0.1591237693781441
6 0.16384218566116265
5 0.17197826172205205
4 0.16785579628202602
1 0.17395375147689937
probabilities(TransferOperator(ApproximationEigen()),op,x)
Probabilities{Float64,1} over 6 outcomes
3 0.16324623516644013
2 0.15912376937533454
6 0.16384218587939298
5 0.17197826206173342
4 0.1678557962706277
1 0.17395375124647128
Under the hood, the method transferoperator(o::OutcomeSpace,x; boundary_condition = :none,
approximation_method=ApproximationIterative())creates a TransferOperatorApproximation{OC<:OutcomeSpace,AM<:ApproximationMethod}from the time series approximation_method
outcome_space
outcomes
transfermatrixThis is passed onto I'm sure I missed some things, but that's the essence of it. A more general Transition probabilites can be useful in Markov chain based estimator methods as well (see here for example ). I probably left some type annotations out from some constructors here and there but those can be corrected later. We also need to check if this breaks something in other packages (I'm thinking of Associations.jl). |
|
hi @rusandris , this looks fantastic. Thank you for putting in the work to finish this. We are very close to the finish line, but as you pointed out already, documentation is crucial before attempting to do the final review and merge. Please tag me here once you have added documentation (this includes both docstrings and a new usage example in the examples as this is a substantial new feature). |
|
Oh, also: do we need to do anything for backwards compatibility in this PR? This way we won't have to worry about breaking stuff. You can likely still extend the old methods that only use binning in the |
So far the old methods x = rand(1000)
b = RectangularBinning(4)
est = TransferOperator(b)
transferoperator(x, b)are added in |
|
probably worth adding in the deprecations a method that where |
|
@Datseris I have finally managed to put together a working version of the code and the docs. I disabled link checking in the docs for now (some of the references are not found apparently), so it can build. |
Datseris
left a comment
There was a problem hiding this comment.
Thanks a lot Andras, this is amazing. This is a really big contribution. I am wondering, how hard would it be to turn this into a paper...? I'm happy to support any way I can if you need help. But a generic transfer operator sounds like something that hasn't been done before.
| # While the corrections of [`BayesianRegularization`](@ref) are small in this case, they are | ||
| # nevertheless measurable. | ||
| # | ||
| # What are the most probable outcomes the system can transition to, given its current state? |
There was a problem hiding this comment.
This comes a bit out of nowhere when compared to the above section; it is probably worth adding a subheading ### Transfer operator here.
There was a problem hiding this comment.
Looking below this section it is also an abrupt change. So overall I think this section here does not feel into the flow of the tutorial. We need to move it somewhere else. Or, I think it is easier to simply make a dedicated example in the examples page? This way you can highlight the bulk of your work, allowing the TE to work with any outcome space.
There was a problem hiding this comment.
Good idea, I'll move it to the Examples page and add some more to it
|
Also don't worry about the link check, it is unrelated to this PR, I'll take care of it later. |
Code-wise a general transfer operator might be a first, although I'm not sure. In terms of papers, transition matrices constructed from symbols other than phase space partitions (like ordinal patterns) have been used before. I need to check if there were some comparative studies which look at some metric calculated using transition matrices of different symbolization types. Do you have a context in mind in which this could count as novelty? |
|
I guess some sort of comparison type of study would be useful, when one uses the TE with various different outcome spaces and shows which ones are more useful for which content. Like get 3-4 type of examples, and apply all possible TE at them and then somehow show something...? I don't know, I have to admit I am not familiar with the literature, you can have a better call at that than me! |
First draft PR. I tried to follow the design ideas mentioned here #424 .
TransferOperatorbecomes aProbabilitiesEstimator.First results:
which returns a
TransferOperatorApproximation <: ProbabilitiesEstimator.OP example:
Most important field is the
transfermatrixprobabilitiesfunction does work formally in that it gives an output:but for some reason, for this particular example, the iterative method used in
invariant_measuredoes not converge.the correct probabs of course would be
[0.5,0.5]as the eigenvector corresponding to eigenvalue 1 is[1,1]. This might be a separate issue though.Let me know what you think.