VARModels.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. def cov(X, p):
  2. """vector autocovariance up to order p
  3. Parameters
  4. ----------
  5. X : ndarray, shape (N, n)
  6. The N time series of length n
  7. Returns
  8. -------
  9. R : ndarray, shape (p + 1, N, N)
  10. The autocovariance up to order p
  11. """
  12. import numpy as np
  13. N, n = X.shape
  14. R = np.zeros((p + 1, N, N))
  15. for k in range(p + 1):
  16. R[k] = (1. / float(n - k)) * np.dot(X[:, :n - k], X[:, k:].T)
  17. return R
  18. def mvar_fit(X, p):
  19. """Fit MVAR model of order p using Yule Walker
  20. Parameters
  21. ----------
  22. X : ndarray, shape (N, n)
  23. The N time series of length n
  24. n_fft : int
  25. The length of the FFT
  26. Returns
  27. -------
  28. A : ndarray, shape (p, N, N)
  29. The AR coefficients where N is the number of signals
  30. and p the order of the model.
  31. sigma : array, shape (N,)
  32. The noise for each time series
  33. """
  34. import numpy as np
  35. N, n = X.shape
  36. gamma = cov(X, p) # gamma(r,i,j) cov between X_i(0) et X_j(r)
  37. G = np.zeros((p * N, p * N))
  38. gamma2 = np.concatenate(gamma, axis=0)
  39. gamma2[:N, :N] /= 2.
  40. for i in range(p):
  41. G[N * i:, N * i:N * (i + 1)] = gamma2[:N * (p - i)]
  42. G = G + G.T # big block matrix
  43. gamma4 = np.concatenate(gamma[1:], axis=0)
  44. phi = np.linalg.solve(G, gamma4) # solve Yule Walker
  45. tmp = np.dot(gamma4[:N * p].T, phi)
  46. sigma = gamma[0] - tmp - tmp.T + np.dot(phi.T, np.dot(G, phi))
  47. phi = np.reshape(phi, (p, N, N))
  48. for k in range(p):
  49. phi[k] = phi[k].T
  50. return phi, sigma
  51. def compute_order_wrapper(X, p_max):
  52. """Estimate AR order with BIC
  53. Parameters
  54. ----------
  55. X : ndarray, shape (N, n)
  56. The N time series of length n
  57. p_max : int
  58. The maximum model order to test
  59. Returns
  60. -------
  61. p : int
  62. Estimated order
  63. bic : ndarray, shape (p_max + 1,)
  64. The BIC for the orders from 0 to p_max.
  65. """
  66. import numpy as np
  67. import multiprocessing as mp
  68. num_cores = mp.cpu_count()
  69. pool = mp.Pool(num_cores)
  70. args = [(X, p) for p in range(1, p_max + 1)]
  71. bic = pool.starmap(compute_order, args)
  72. pool.close()
  73. bic = np.insert(bic, 0, np.nan)
  74. p = np.nanargmin(bic)
  75. return p
  76. def compute_order(X, p):
  77. """Estimate AR order with BIC
  78. Parameters
  79. ----------
  80. X : ndarray, shape (N, n)
  81. The N time series of length n
  82. p_max : int
  83. The maximum model order to test
  84. Returns
  85. -------
  86. p : int
  87. Estimated order
  88. bic : ndarray, shape (p_max + 1,)
  89. The BIC for the orders from 0 to p_max.
  90. """
  91. from numpy import linalg
  92. import numpy as np
  93. import math
  94. import warnings
  95. with warnings.catch_warnings():
  96. warnings.simplefilter("ignore")
  97. N, n = X.shape
  98. Y = X.T
  99. bic_p = np.nan
  100. try:
  101. A, sigma = mvar_fit(X, p)
  102. A_2d = np.concatenate(A, axis=1)
  103. n_samples = n - p
  104. bic_p = n_samples * N * math.log(2. * math.pi)
  105. bic_p += (n_samples * np.log(linalg.det(sigma)))
  106. bic_p += p * (N ** 2) * math.log(n_samples)
  107. sigma_inv = linalg.inv(sigma)
  108. S = 0.
  109. for i in range(p, n):
  110. res = Y[i] - np.dot(A_2d, Y[i - p:i][::-1, :].ravel())
  111. S += np.dot(res, sigma_inv.dot(res))
  112. bic_p += S
  113. except:
  114. pass
  115. return bic_p