Skip to content

Commit 2e869dc

Browse files
authored
Merge pull request #91 from lucasb-eyer/ts-data
Add time-series data: Mackey-Glass, MSO and Lorentz.
2 parents dc867de + 9a750e6 commit 2e869dc

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

DeepFried2/datasets/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from . import cifar100
44
from . import sequence_sum
55
from . import stanfordbg
6+
from . import timeseries

DeepFried2/datasets/timeseries.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import numpy as np
2+
from collections import deque as _deque
3+
4+
from DeepFried2 import floatX
5+
6+
7+
def mackey_glass(T, N, tau=17, n=10, beta=0.2, gamma=0.1, dt=10, mila=False):
8+
'''Returns `N` different Mackey Glass time-series of length `T` with delay `tau`.
9+
`tau` is the delay of the system, higher values being more chaotic.
10+
The values are centered and squashed through a tanh.
11+
12+
dx/dt = beta * x_tau / (1 + x_tau ^ n) - gamma * x
13+
with x_tau = x(t - tau)
14+
15+
The return shape is (N, T, 1).
16+
17+
Origin of this function: https://github.com/mila-udem/summerschool2015
18+
but modified a slight bit (unless `mila` is True).
19+
'''
20+
X = np.empty((N, T, 1), floatX)
21+
x = 1.2 # Initial conditions for the history of the system
22+
23+
for i in range(N):
24+
# Note that this is slightly different than the MILA one.
25+
# They didn't re-init x to 1.2 for each i, instead re-using the last
26+
# one from the previous i, all the while re-initializing the history.
27+
# I think what they do is wrong, but probably doesn't matter much.
28+
history = _deque((1.2 if mila else x) + beta * (np.random.rand(tau * dt) - 0.5))
29+
# TODO: Is x above really x or just 1.2 which they used in MILA one?
30+
# TODO: 0.5 above must be constructed from others in some way?
31+
32+
for t in range(T):
33+
for _ in range(dt):
34+
# xtau is the value at the last timestep, dt ago.
35+
xtau = history.popleft()
36+
history.append(x)
37+
x += (beta * xtau / (1.0 + xtau**n) - gamma*x) / dt
38+
X[i,t,0] = x
39+
40+
# Squash timeseries through tanh
41+
return np.tanh(X - 1)
42+
43+
44+
def mso(T, N, freqs=[0.2, 0.311]):
45+
'''Returns `N` different sums of randomly phased sine-waves of
46+
frequencies `freqs`, each of length `T`.
47+
48+
The return shape is (N, T, 1).
49+
50+
Origin of this function: https://github.com/mila-udem/summerschool2015
51+
'''
52+
X = np.empty((N, T, 1), floatX)
53+
54+
for i in range(N):
55+
phase = np.random.rand()
56+
X[i,:,0] = sum(np.sin(f*np.arange(T) + phase) for f in freqs)
57+
58+
return X
59+
60+
61+
def lorentz(T=1000, N=5, dt=0.01, sigma=10, rho=28, beta=8./3., x0=[0, -0.01, 9]):
62+
"""Returns `N` independent Lorentz time-series of length `T` in (N,T,3).
63+
64+
- `dt` is the time between samples. Currently, only a scalar is supported,
65+
but the plan is to support varying `dt`s.
66+
67+
- All of `sigma`, `rho`, and `beta` can be either a single number shared
68+
across all `N` time-series, a 2-tuple meaning bounds of a uniform random
69+
interval, or an array of size `N`.
70+
71+
- `x0` are initial conditions. Either 3 values (x0,y0,z0) can be specified
72+
for shared initial conditions across all `N`, or an `(N,3)` array for
73+
individual initial conditions.
74+
75+
For any of `sigma`, `rho` and `beta`, a smaller value is "smoother" behaviour,
76+
but the difference from changing `x0` is much more dramatic then any of them.
77+
"""
78+
if isinstance(sigma, tuple) and len(sigma) == 2:
79+
sigma = np.random.uniform(*sigma, size=N).astype(floatX)
80+
81+
if isinstance(rho, tuple) and len(rho) == 2:
82+
rho = np.random.uniform(*rho, size=N).astype(floatX)
83+
84+
if isinstance(beta, tuple) and len(beta) == 2:
85+
beta = np.random.uniform(*beta, size=N).astype(floatX)
86+
87+
X = np.empty((N, T, 3), floatX)
88+
X[:,0] = x0 # Initial conditions taken from 'Chaos and Time Series Analysis', J. Sprott
89+
90+
for t in range(T-1):
91+
X[:,t+1,0] = X[:,t,0] + sigma * (X[:,t,1] - X[:,t,0]) * dt
92+
X[:,t+1,1] = X[:,t,1] + (X[:,t,0] * (rho - X[:,t,2]) - X[:,t,1]) * dt
93+
X[:,t+1,2] = X[:,t,2] + (X[:,t,0] * X[:,t,1] - beta * X[:,t,2]) * dt
94+
95+
return X

0 commit comments

Comments
 (0)