Skip to content
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

[Help] Identify PDE by svd #434

Open
Junang-Wang opened this issue Nov 30, 2023 · 5 comments
Open

[Help] Identify PDE by svd #434

Junang-Wang opened this issue Nov 30, 2023 · 5 comments

Comments

@Junang-Wang
Copy link

Hi there. I am a beginner for PySindy. I am currently working on identifying a nonlinear partial differential equation (PDE). The state vector x contains 10 physical variables in a 1D spatial grid with 40 discrete points. Since the number of variables is large, I am using singular value decomposition (SVD) to capture the first 6 modes as basis vectors for my new coordinate system. By converting my data to this new basis, I aim to solve the equation. However, when I plot the Pareto curve, I observe that the error decreases as the threshold lambda increases. Moreover, the error becomes significantly large. Does anyone have any suggestions on how to solve these problems?

Thanks in advance.

@Junang-Wang
Copy link
Author

The following is my code snapshot:

load data and svd

x = x.transpose([0,2,1]).reshape(n_elemn_var,tsize) # state vectors: origin shape (n_elem, tsize, n_var) shape: n_elemn_var, tsize
U, S, V = scipy.linalg.svd(x)
u = u[0] # shape tsize, control_features

change to new basis

r = 6 # Truncate the first 6 modes
Ur = U[:,:r] # each col is the mode we focused on
New_var = (Ur.T @ x).T # shape: (tsize,r) # variables in new basis

train_time = 3000
V_train = New_var[:train_time,:]
V_test = New_var[train_time:,:]
t_test = tspan[:tsize-train_time]
u_train = u[:train_time]
u_test = u[:tsize-train_time]
poly_order = 5
threshold_scan = np.linspace(0, 100, 10)
coefs = []

plot pareto curve

poly_library = ps.PolynomialLibrary(degree=poly_order)

for i, threshold in enumerate(threshold_scan):
sparse_regression_optimizer = ps.STLSQ(threshold=threshold,normalize_columns=True)
model = ps.SINDy(feature_library=poly_library,
optimizer=sparse_regression_optimizer)
model.fit(V_train, t=dt, u= u_train, quiet=True)
coefs.append(model.coefficients())

plot_pareto(coefs, sparse_regression_optimizer, model,
threshold_scan, V_test, t_test, u_test)

image

@Jacob-Stevens-Haas
Copy link
Collaborator

Jacob-Stevens-Haas commented Nov 30, 2023

The only thing I notice about your code is that, when fitting an SVD, you should just use the right singular vectors. I.e. in
$$A = U S V^T$$

You want to fit $V^T$ with SINDy, not $U^T A = S V^T$. This keeps all your variables on the same scale.

I don't know what plot_pareto is doing, so I can't tell what's going wrong. All I can say is that $10^{15}$ is a big number

It generally helps to make sure your code works on a simple, known problem (like the heat equation) if something isn't working with custom data. This identifies if the problem is truly idiosyncratic to your data or just a coding error.

@Junang-Wang
Copy link
Author

Hi, @Jacob-Stevens-Haas

Thank you for your prompt response. I appreciate your suggestion to fix the code for a simple and well-known problem. Do you know any good examples, such as papers, codes, or tutorials, that demonstrate the use of SVD and addressing modes with SINDy?I really appreciate for your sharing.

Thank you so much for the help.

@Jacob-Stevens-Haas
Copy link
Collaborator

Try the examples folder here. Alternatively, you can simulate a 1D heat equation as an ODE by using the fourier transform. See an example in the tests of this repo

@Junang-Wang
Copy link
Author

@Jacob-Stevens-Haas. Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants