KoopmanESNModel.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import reservoirpy as rpy
  2. import torch
  3. from numpy.linalg import eigvals
  4. from reservoirpy.nodes import Reservoir, Ridge
  5. import numpy as np
  6. from dataclasses import dataclass
  7. @dataclass
  8. class KoopmanESNConfig:
  9. units: int
  10. lr: float
  11. sr: float
  12. sp: float
  13. ridge: float
  14. train_start: int
  15. train_len: int
  16. train_warmup: int
  17. predict_warmup: int
  18. predict_len: int
  19. state_dim: int
  20. class KoopmanESN:
  21. def __init__(self, A, config: KoopmanESNConfig):
  22. super().__init__()
  23. self.esn_model = None
  24. self.config = config
  25. self.A = A/100
  26. def W_initial(self, A):
  27. W_koop = A
  28. W = W_koop
  29. # 5. 调整谱半径
  30. current_radius = np.max(np.abs(eigvals(W)))
  31. W = (self.config.sr / current_radius) * W
  32. return W
  33. def koopmanesn_train(self, data_train):
  34. rpy.verbosity(0)
  35. rpy.set_seed(42)
  36. W = self.W_initial(self.A)
  37. Win = np.eye(self.config.units, self.config.units)
  38. reservoir = Reservoir(
  39. units=self.config.units,
  40. lr=self.config.lr,
  41. sr=self.config.sr,
  42. W=W,
  43. input_scaling=1.0,
  44. Win=Win,
  45. activation='identity'
  46. )
  47. readout = Ridge(ridge=self.config.ridge)
  48. esn_model = reservoir >> readout
  49. data_train_in = data_train[:-1, :]
  50. data_train_out = data_train[1:, :]
  51. self.esn_model = esn_model.fit(
  52. data_train_in,
  53. data_train_out,
  54. warmup=self.config.train_warmup
  55. )
  56. def predict(self, data_warm):
  57. warmup_data = self.esn_model.run(data_warm, reset=True)
  58. x = warmup_data[-1, :].reshape(1, -1)
  59. data_pre = np.empty((self.config.predict_len, self.config.state_dim))
  60. for i in range(self.config.predict_len):
  61. data_pre[i, :] = x
  62. x = self.esn_model(x)
  63. return data_pre