Skip to content

Commit c108cd2

Browse files
committed
defer imports to save top level import time
reformat files
1 parent 77de218 commit c108cd2

File tree

2 files changed

+130
-114
lines changed

2 files changed

+130
-114
lines changed

autokoopman/observable/reweighted.py

+127-112
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,166 @@
11
from autokoopman.observable import SymbolicObservable, KoopmanObservable
22
import math
33
import numpy as np
4-
import sympy as sp
5-
from scipy.stats import cauchy, laplace
6-
from scipy.optimize import nnls
74

85

96
def make_gaussian_kernel(sigma=1.0):
10-
"""the baseline"""
11-
def kernel(x, xp):
12-
return np.exp(-np.linalg.norm(x-xp)**2.0 / (2.0*sigma**2.0))
13-
return kernel
7+
"""the baseline"""
8+
9+
def kernel(x, xp):
10+
return np.exp(-np.linalg.norm(x - xp) ** 2.0 / (2.0 * sigma**2.0))
11+
12+
return kernel
1413

1514

1615
def rff_reweighted_map(n, X, Y, wx, wy, sigma=1.0):
17-
"""build a RFF explicit feature map"""
18-
assert len(X) == len(Y)
19-
R = n
20-
D = X.shape[1]
21-
N = len(X)
22-
W = np.random.normal(loc=0, scale=(1.0/np.sqrt(sigma)), size=(R, D))
23-
b = np.random.uniform(-np.pi, np.pi, size = R)
24-
25-
# get ground truth kernel for training
26-
kernel = make_gaussian_kernel(sigma)
27-
28-
# solve NNLS problem
29-
M = np.zeros((N, R))
30-
bo = np.zeros((N,))
31-
for jdx, (xi, yi, wxi, wyi) in enumerate(zip(X, Y, wx, wy)):
32-
wi = np.sum(wxi) * np.sum(wyi)
33-
k = wi * kernel(xi, yi)
34-
if np.isclose(np.abs(wi), 0.0):
35-
continue
36-
bo[jdx] = k
37-
for idx, (omegai, bi) in enumerate(zip(W, b)):
38-
M[jdx, idx] = wi * np.cos(np.dot(omegai, xi) + bi) * np.cos(np.dot(omegai, yi) + bi)
39-
40-
a, _ = nnls(M, bo, maxiter=1000)
41-
42-
# get new values
43-
new_idxs = (np.abs(a) > 3E-5)
44-
W = W[new_idxs]
45-
b = b[new_idxs]
46-
a = a[new_idxs]
47-
48-
return a, W, b
16+
"""build a RFF explicit feature map"""
17+
from scipy.optimize import nnls
18+
19+
assert len(X) == len(Y)
20+
R = n
21+
D = X.shape[1]
22+
N = len(X)
23+
W = np.random.normal(loc=0, scale=(1.0 / np.sqrt(sigma)), size=(R, D))
24+
b = np.random.uniform(-np.pi, np.pi, size=R)
25+
26+
# get ground truth kernel for training
27+
kernel = make_gaussian_kernel(sigma)
28+
29+
# solve NNLS problem
30+
M = np.zeros((N, R))
31+
bo = np.zeros((N,))
32+
for jdx, (xi, yi, wxi, wyi) in enumerate(zip(X, Y, wx, wy)):
33+
wi = np.sum(wxi) * np.sum(wyi)
34+
k = wi * kernel(xi, yi)
35+
if np.isclose(np.abs(wi), 0.0):
36+
continue
37+
bo[jdx] = k
38+
for idx, (omegai, bi) in enumerate(zip(W, b)):
39+
M[jdx, idx] = (
40+
wi * np.cos(np.dot(omegai, xi) + bi) * np.cos(np.dot(omegai, yi) + bi)
41+
)
42+
43+
a, _ = nnls(M, bo, maxiter=1000)
44+
45+
# get new values
46+
new_idxs = np.abs(a) > 3e-5
47+
W = W[new_idxs]
48+
b = b[new_idxs]
49+
a = a[new_idxs]
50+
51+
return a, W, b
4952

5053

5154
def subsampled_dense_grid(d, D, gamma, deg=8):
52-
"""sparse grid gaussian quadrature"""
53-
points, weights = np.polynomial.hermite.hermgauss(deg)
54-
points *= 2 * math.sqrt(gamma)
55-
weights /= math.sqrt(math.pi)
56-
# Now @weights must sum to 1.0, as the kernel value at 0 is 1.0
57-
subsampled_points = np.random.choice(points, size=(D, d), replace=True, p=weights)
58-
subsampled_weights = np.ones(D) / math.sqrt(D)
59-
return subsampled_points, subsampled_weights
55+
"""sparse grid gaussian quadrature"""
56+
points, weights = np.polynomial.hermite.hermgauss(deg)
57+
points *= 2 * math.sqrt(gamma)
58+
weights /= math.sqrt(math.pi)
59+
# Now @weights must sum to 1.0, as the kernel value at 0 is 1.0
60+
subsampled_points = np.random.choice(points, size=(D, d), replace=True, p=weights)
61+
subsampled_weights = np.ones(D) / math.sqrt(D)
62+
return subsampled_points, subsampled_weights
6063

6164

6265
def dense_grid(d, D, gamma, deg=8):
63-
"""dense grid gaussian quadrature"""
64-
points, weights = np.polynomial.hermite.hermgauss(deg)
65-
points *= 2 * math.sqrt(gamma)
66-
weights /= math.sqrt(math.pi)
67-
points = np.atleast_2d(points).T
68-
return points, weights
66+
"""dense grid gaussian quadrature"""
67+
points, weights = np.polynomial.hermite.hermgauss(deg)
68+
points *= 2 * math.sqrt(gamma)
69+
weights /= math.sqrt(math.pi)
70+
points = np.atleast_2d(points).T
71+
return points, weights
6972

7073

7174
def sparse_grid_map(n, d, sigma=1.0):
72-
"""sparse GQ explicit map"""
73-
d, D = d, n
74-
gamma = 1/(2*sigma*sigma)
75-
points, weights = subsampled_dense_grid(d, D, gamma=gamma)
76-
def inner(x):
77-
prod = x @ points.T
78-
return np.hstack((weights * np.cos(prod), weights * np.sin(prod)))
79-
return inner
75+
"""sparse GQ explicit map"""
76+
d, D = d, n
77+
gamma = 1 / (2 * sigma * sigma)
78+
points, weights = subsampled_dense_grid(d, D, gamma=gamma)
79+
80+
def inner(x):
81+
prod = x @ points.T
82+
return np.hstack((weights * np.cos(prod), weights * np.sin(prod)))
83+
84+
return inner
8085

8186

8287
def dense_grid_map(n, d, sigma=1.0):
83-
"""dense GQ explicit map"""
84-
d, D = d, n
85-
gamma = 1/(2*sigma*sigma)
86-
points, weights = dense_grid(d, D, gamma=gamma)
87-
def inner(x):
88-
prod = x @ points.T
89-
return np.hstack((weights * np.cos(prod), weights * np.sin(prod)))
90-
return inner
88+
"""dense GQ explicit map"""
89+
d, D = d, n
90+
gamma = 1 / (2 * sigma * sigma)
91+
points, weights = dense_grid(d, D, gamma=gamma)
92+
93+
def inner(x):
94+
prod = x @ points.T
95+
return np.hstack((weights * np.cos(prod), weights * np.sin(prod)))
96+
97+
return inner
9198

9299

93100
def quad_reweighted_map(n, X, Y, wx, wy, sigma=1.0):
94-
"""build a RFF explicit feature map"""
95-
assert len(X) == len(Y)
96-
R = int(n / 2.0)
97-
D = X.shape[1]
98-
N = len(X)
99-
W, a = subsampled_dense_grid(D, R, gamma=1/(2*sigma*sigma))
100-
#W = np.random.normal(loc=0, scale=(1.0/np.sqrt(sigma)), size=(R, D))
101-
b = np.random.uniform(-np.pi, np.pi, size = R)
102-
#print(X.shape, W.shape)
103-
#b = np.arccos(-np.sqrt(np.cos(2*X.T.dot(W)) + 1)/np.sqrt(2.0))
104-
#print(b)
105-
106-
# get ground truth kernel for training
107-
kernel = make_gaussian_kernel(sigma)
108-
109-
# solve NNLS problem
110-
M = np.zeros((N, R))
111-
bo = np.zeros((N,))
112-
for jdx, (xi, yi, wxi, wyi) in enumerate(zip(X, Y, wx, wy)):
113-
k = kernel(xi, yi)
114-
bo[jdx] = k
115-
for idx, (omegai, ai, bi) in enumerate(zip(W, a, b)):
116-
M[jdx, idx] = np.cos(np.dot(omegai, xi - yi))
117-
118-
a, _ = nnls(M, bo, maxiter=1000)
119-
120-
# get new values
121-
new_idxs = (np.abs(a) > 1E-7)
122-
W = W[new_idxs]
123-
b = b[new_idxs]
124-
a = a[new_idxs]
125-
126-
return a, W, b
101+
"""build a RFF explicit feature map"""
102+
from scipy.optimize import nnls
103+
104+
assert len(X) == len(Y)
105+
R = int(n / 2.0)
106+
D = X.shape[1]
107+
N = len(X)
108+
W, a = subsampled_dense_grid(D, R, gamma=1 / (2 * sigma * sigma))
109+
# W = np.random.normal(loc=0, scale=(1.0/np.sqrt(sigma)), size=(R, D))
110+
b = np.random.uniform(-np.pi, np.pi, size=R)
111+
# print(X.shape, W.shape)
112+
# b = np.arccos(-np.sqrt(np.cos(2*X.T.dot(W)) + 1)/np.sqrt(2.0))
113+
# print(b)
114+
115+
# get ground truth kernel for training
116+
kernel = make_gaussian_kernel(sigma)
117+
118+
# solve NNLS problem
119+
M = np.zeros((N, R))
120+
bo = np.zeros((N,))
121+
for jdx, (xi, yi, wxi, wyi) in enumerate(zip(X, Y, wx, wy)):
122+
k = kernel(xi, yi)
123+
bo[jdx] = k
124+
for idx, (omegai, ai, bi) in enumerate(zip(W, a, b)):
125+
M[jdx, idx] = np.cos(np.dot(omegai, xi - yi))
126+
127+
a, _ = nnls(M, bo, maxiter=1000)
128+
129+
# get new values
130+
new_idxs = np.abs(a) > 1e-7
131+
W = W[new_idxs]
132+
b = b[new_idxs]
133+
a = a[new_idxs]
134+
135+
return a, W, b
127136

128137

129138
class ReweightedRFFObservable(SymbolicObservable):
130-
def __init__(self, dimension, num_features, gamma, X, Y, wx, wy, feat_type='rff'):
139+
def __init__(self, dimension, num_features, gamma, X, Y, wx, wy, feat_type="rff"):
140+
import sympy as sp
141+
131142
self.dimension, self.num_features = dimension, num_features
132143
n = num_features
133-
if feat_type == 'quad':
134-
self.a, self.W, self.b = quad_reweighted_map(n, X, Y, wx, wy, np.sqrt(1/(2*gamma)))
135-
elif feat_type == 'rff':
136-
self.a, self.W, self.b = rff_reweighted_map(n, X, Y, wx, wy, np.sqrt(1/(2*gamma)))
144+
if feat_type == "quad":
145+
self.a, self.W, self.b = quad_reweighted_map(
146+
n, X, Y, wx, wy, np.sqrt(1 / (2 * gamma))
147+
)
148+
elif feat_type == "rff":
149+
self.a, self.W, self.b = rff_reweighted_map(
150+
n, X, Y, wx, wy, np.sqrt(1 / (2 * gamma))
151+
)
137152
else:
138-
raise ValueError('feat_type must be quad or rff')
139-
153+
raise ValueError("feat_type must be quad or rff")
154+
140155
# make sympy variables for each of the state dimensions
141-
self.variables = [f'x{i}' for i in range(self.dimension)]
156+
self.variables = [f"x{i}" for i in range(self.dimension)]
142157
self._observables = sp.symbols(self.variables)
143158
X = sp.Matrix(self._observables)
144-
159+
145160
# build observables sympy expressions from self.weights from self.weights, x.T @ points
146161
self.expressions = []
147162
for ai, wi, bi in zip(self.a, self.W, self.b):
148163
self.expressions.append(np.sqrt(ai) * sp.cos(X.dot(wi)))
149164
self.expressions.append(np.sqrt(ai) * sp.sin(X.dot(wi)))
150165

151-
super(ReweightedRFFObservable, self).__init__(self.variables, self.expressions)
166+
super(ReweightedRFFObservable, self).__init__(self.variables, self.expressions)

autokoopman/observable/rff.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import numpy as np
2-
from scipy.stats import cauchy, laplace
32

43
from .observables import KoopmanObservable
54

65

76
class RFFObservable(KoopmanObservable):
87
def __init__(self, dimension, num_features, gamma, metric="rbf"):
8+
from scipy.stats import cauchy, laplace
9+
910
super(RFFObservable, self).__init__()
1011
self.gamma = gamma
1112
self.dimension = dimension
@@ -49,4 +50,4 @@ def obs_grad(self, X: np.ndarray) -> np.ndarray:
4950
def compute_kernel(self, X: np.ndarray) -> np.ndarray:
5051
Z = self.transform(X)
5152
K = Z.dot(Z.T)
52-
return K
53+
return K

0 commit comments

Comments
 (0)