Package: kramersmoyal
KramersMoyalkramersmoyalis a python package designed to obtain the Kramers–Moyal coefficients, or conditional moments, from stochastic data of any dimension. It employs kernel density estimations, instead of a histogram approach, to ensure better results for low number of points as well as allowing better fitting of the results.Thepaperis now officially published onJOSS. The paper is also availablehere, or you can find it in theArXiv.InstallationTo installkramersmoyal, just usepippip install kramersmoyalThen on your favourite editor just usefromkramersmoyalimportkmDependenciesThe library depends onnumpyandscipy.A one-dimensional stochastic processA Jupyter notebook with this example can be foundhereThe theoryTake, for example, the well-documented one-dimension Ornstein–Uhlenbeck process, also known as Vašíček process, seehere. This process is governed by two main parameters: the mean-reverting parameter θ and the diffusion parameter σwhich can be solved in various ways. For our purposes, recall that the drift coefficient, i.e., the first-order Kramers–Moyal coefficient, is given byand the second-order Kramers–Moyal coefficient is, i.e., the diffusion.Generate an exemplary Ornstein–Uhlenbeck process with your favourite integrator, e.g., theEuler–Maruyamaor with a more powerful tool fromJiTCSDEfound on GitHub.
For this example let's take θ=.3 and σ=.1, over a total time of 500 units, with a sampling of 1000 Hertz, and from the generated data series retrieve the two parameters, the drift -θy(t) and diffusion σ.Integrating an Ornstein–Uhlenbeck processHere is a short code on generating a Ornstein–Uhlenbeck stochastic trajectory with a simple Euler–Maruyama integration method# integration time and time samplingt_final=500delta_t=0.001# The parameters theta and sigmatheta=0.3sigma=0.1# The time array of the trajectorytime=np.arange(0,t_final,delta_t)# Initialise the array yy=np.zeros(time.size)# Generate a Wiener processdw=np.random.normal(loc=0,scale=np.sqrt(delta_t),size=time.size)# Integrate the processforiinrange(1,time.size):y[i]=y[i-1]-theta*y[i-1]*delta_t+sigma*dw[i]From here we have a plain example of an Ornstein–Uhlenbeck process, always drifting back to zero, due to the mean-reverting drift θ. The effect of the noise can be seen across the whole trajectory.UsingkramersmoyalTake the timeseriesyand let's study the Kramers–Moyal coefficients. For this let's look at the drift and diffusion coefficients of the process, i.e., the first and second Kramers–Moyal coefficients, with anepanechnikovkernel# The kmc holds the results, where edges holds the binning spacekmc,edges=km(y,powers=2)This results inNotice here that to obtain the Kramers–Moyal coefficients you need to dividekmcby the timestepdelta_t. This normalisation stems from the Taylor-like approximation, i.e., the Kramers–Moyal expansion (delta t→ 0).A two-dimensional diffusion processA Jupyter notebook with this example can be foundhereTheoryA two-dimensional diffusion process is a stochastic process that comprises twoand allows for a mixing of these noise terms across its two dimensions.where we will select a set of state-dependent parameters obeyingwithand.Choice of parametersAs an example, let's take the following set of parameters for the drift vector and diffusion matrix# integration time and time samplingt_final=2000delta_t=0.001# Define the drift vector NN=np.array([2.0,1.0])# Define the diffusion matrix gg=np.array([[0.5,0.0],[0.0,0.5]])# The time array of the trajectorytime=np.arange(0,t_final,delta_t)Integrating a 2-dimensional processIntegrating the previous stochastic trajectory with a simple Euler–Maruyama integration method# Initialise the array yy=np.zeros([time.size,2])# Generate two Wiener processes with a scale of np.sqrt(delta_t)dW=np.random.normal(loc=0,scale=np.sqrt(delta_t),size=[time.size,2])# Integrate the process (takes about 20 secs)foriinrange(1,time.size):y[i,0]=y[i-1,0]-N[0]*y[i-1,0]*delta_t+g[0,0]/(1+np.exp(y[i-1,0]**2))*dW[i,0]+g[0,1]*dW[i,1]y[i,1]=y[i-1,1]-N[1]*y[i-1,1]*delta_t+g[1,0]*dW[i,0]+g[1,1]/(1+np.exp(y[i-1,1]**2))*dW[i,1]The stochastic trajectory in 2 dimensions for10time units (10000data points)Back tokramersmoyaland the Kramers–Moyal coefficientsFirst notice that all the results now will be two-dimensional surfaces, so we will need to plot them as such# Choose the size of your target space in two dimensionsbins=[100,100]# Introduce the desired orders to calculate, but in 2 dimensionspowers=np.array([[0,0],[1,0],[0,1],[1,1],[2,0],[0,2],[2,2]])# insert into kmc:   0      1      2      3      4      5      6# Notice that the first entry in [,] is for the first dimension, the# second for the second dimension...# Choose a desired bandwidth bwbw=0.1# Calculate the Kramers−Moyal coefficientskmc,edges=km(y,bw=bw,bins=bins,powers=powers)# The K−M coefficients are stacked along the first dim of the# kmc array, so kmc[1,...] is the first K−M coefficient, kmc[2,...]# is the second. These will be 2-dimensional matricesNow one can visualise the Kramers–Moyal coefficients (surfaces) in green and the respective theoretical surfaces in black. (Don't forget to normalise:kmc / delta_t).ContributionsWe welcome reviews and ideas from everyone. If you want to share your ideas or report a bug, open anissuehere on GitHub, or contact us directly.
If you need help with the code, the theory, or the implementation, do not hesitate to contact us, we are here to help.
We abide to aConduct of Fairness.TODOsNext on the list isInclude more kernelsWork through the documentation carefullyChangelogVersion 0.4.1 - Changing CI. Correctingkmc[0,:]normalisation. Various Simplifications. Bins as ints, powers as ints.Version 0.4.0 - Added the documentation, first testers, and the Conduct of FairnessVersion 0.3.2 - Adding 2 kernels:triagularandquarticand extending the documentation and examples.Version 0.3.1 - Corrections to the fft triming after convolution.Version 0.3.0 - The major breakthrough: Calculates the Kramers–Moyal coefficients for data of any dimension.Version 0.2.0 - Introducing convolutions andgaussiananduniformkernels. Major speed up in the calculations.Version 0.1.0 - One and two dimensional Kramers–Moyal coefficients with anepanechnikovkernel.Literature and SupportLiteratureThe study of stochastic processes from a data-driven approach is grounded in extensive mathematical work. From the applied perspective there are several references to understand stochastic processes, the Fokker–Planck equations, and the Kramers–Moyal expansionTabar, M. R. R. (2019).Analysis and Data-Based Reconstruction of Complex Nonlinear Dynamical Systems.Springer, International PublishingRisken, H. (1989).The Fokker–Planck equation.Springer, Berlin, Heidelberg.Gardiner, C.W. (1985).Handbook of Stochastic Methods.Springer, Berlin.You can find and extensive review on the subjecthere1HistoryThis project was started in 2017 at theneurophysikby Leonardo Rydin Gorjão, Jan Heysel, Klaus Lehnertz, and M. Reza Rahimi Tabar. Francisco Meirinhos later devised the hard coding to python. The project is now supported by Dirk Witthaut and theInstitute of Energy and Climate Research Systems Analysis and Technology Evaluation.FundingHelmholtz Association InitiativeEnergy System 2050 - A Contribution of the Research Field Energyand the grant No. VH-NG-1025 andSTORM - Stochastics for Time-Space Risk Modelsproject of the Research Council of Norway (RCN) No. 274410.1Friedrich, R., Peinke, J., Sahimi, M., Tabar, M. R. R.Approaching complexity by stochastic methods: From biological systems to turbulence,Phys. Rep. 506, 87–162 (2011).