emwamsgrad.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import numpy as np
  2. import time
  3. import matplotlib.pyplot as plt
  4. def emwamsgrad(data, G, F, r, Tmax):
  5. tol = 1e-5
  6. delta_measure = 1
  7. em_iter_max = round(Tmax / delta_measure) + 1 #
  8. T = np.empty(shape=(em_iter_max + 1))
  9. T.fill(np.nan)
  10. RMSE = np.empty(shape=(2, em_iter_max + 1))
  11. RMSE.fill(np.nan)
  12. # RRE = np.empty(shape=(em_iter_max + 1))
  13. # RRE.fill(np.nan)
  14. ITER_MAX = 100 # maximum inner iteration number (Default)
  15. ITER_MIN = 5 # minimum inner iteration number (Default)
  16. np.put(F, data.idxOF, data.sparsePhi_F)
  17. np.put(G, data.idxOG, data.sparsePhi_G)
  18. X = data.X + np.multiply(data.nW, np.dot(G, F))
  19. FXt = np.dot(F, X.T)
  20. FFt = np.dot(F, F.T)
  21. GtX = np.dot(G.T, X)
  22. GtG = np.dot(G.T, G)
  23. GradG = np.dot(G, FFt) - FXt.T
  24. GradF = np.dot(GtG, F) - GtX
  25. init_delta = stop_rule(np.hstack((G.T, F)), np.hstack((GradG.T, GradF)))
  26. tolF = tol * init_delta
  27. tolG = tolF # Stopping tolerance
  28. # Iterative updating
  29. G = G.T
  30. k = 0
  31. RMSE[:, k] = np.linalg.norm(F[:, 0:-1] - data.F[:, 0:-1], 2, axis=1) / np.sqrt(F.shape[1] - 1)
  32. T[k] = 0
  33. t = time.time()
  34. # Main loop
  35. while time.time() - t <= Tmax + delta_measure:
  36. # Estimation step
  37. X = data.X + np.multiply(data.nW, np.dot(G.T, F))
  38. # Maximisation step
  39. # Optimize F with fixed G
  40. np.put(F, data.idxOF, 0)
  41. F, iterF, _ = amsgrad(F, GtG, GtX - GtG.dot(data.Phi_F), ITER_MIN, ITER_MAX, tolF, data.idxOF, False)
  42. np.put(F, data.idxOF, data.sparsePhi_F)
  43. # print(F[:,0:5])
  44. if iterF <= ITER_MIN:
  45. tolF = tolF / 10
  46. # print('Tweaked F tolerance to '+str(tolF))
  47. FFt = np.dot(F, F.T)
  48. FXt = np.dot(F, X.T)
  49. # Optimize G with fixed F
  50. np.put(G.T, data.idxOG, 0)
  51. G, iterG, _ = amsgrad(G, FFt, FXt - FFt.dot(data.Phi_G.T), ITER_MIN, ITER_MAX, tolG, data.idxOG, True)
  52. np.put(G.T, data.idxOG, data.sparsePhi_G)
  53. if iterG <= ITER_MIN:
  54. tolG = tolG / 10
  55. # print('Tweaked G tolerance to '+str(tolG))
  56. GtG = np.dot(G, G.T)
  57. GtX = np.dot(G, X)
  58. if time.time() - t - k * delta_measure >= delta_measure:
  59. k = k + 1
  60. if k >= em_iter_max + 1:
  61. break
  62. RMSE[:, k] = np.linalg.norm(F[:, 0:-1] - data.F[:, 0:-1], 2, axis=1) / np.sqrt(F.shape[1] - 1)
  63. T[k] = time.time() - t
  64. # RRE[k] = nmf_norm_fro(data.Xtheo, G.T, F, data.W)
  65. # if k%100==0:
  66. # print(str(k)+' '+str(RMSE[0,k])+' '+str(RMSE[1,k]))
  67. # plt.semilogy(RRE)
  68. # plt.show()
  69. return {'RMSE': RMSE, 'T': T}
  70. def stop_rule(X, GradX):
  71. # Stopping Criterions
  72. pGrad = GradX[np.any(np.dstack((X > 0, GradX < 0)), 2)]
  73. return np.linalg.norm(pGrad, 2)
  74. def amsgrad(Z, GtG, GtX, iterMin, iterMax, tol, idxfixed, transposed):
  75. grad = np.dot(GtG, Z) - GtX # Gradient
  76. m = 0
  77. v = 0
  78. v_hat = 0
  79. alpha = 1e-3
  80. beta1 = 0.9
  81. beta2 = 0.999
  82. eps = 1e-8
  83. for iter in range(1, iterMax + 1):
  84. bias_correction1 = 1 - beta1 ** iter
  85. bias_correction2 = 1 - beta2 ** iter
  86. # bias_correction1 = 1 - beta1
  87. # bias_correction2 = 1 - beta2
  88. m = beta1 * m + (1 - beta1) * grad
  89. v = beta2 * v + (1 - beta2) * np.square(grad)
  90. v_hat = np.maximum(v_hat, v)
  91. denom = np.sqrt(v_hat)/np.sqrt(bias_correction2) + eps
  92. Z = Z - (alpha/bias_correction1) * m / denom
  93. if transposed: # If Z = G.T
  94. np.put(Z.T, idxfixed, 0)
  95. else: # If Z = F
  96. np.put(Z, idxfixed, 0)
  97. Z = np.maximum(Z, 0)
  98. # Stopping criteria
  99. if iter >= iterMin:
  100. # Lin's stopping criteria
  101. pgn = stop_rule(Z, grad)
  102. if pgn <= tol:
  103. break
  104. grad = np.dot(GtG, Z) - GtX
  105. return Z, iter, grad
  106. def nmf_norm_fro(X, G, F, *args):
  107. W = args
  108. if len(W) == 0:
  109. f = np.square(np.linalg.norm(X - np.dot(G, F), 'fro')) / np.square(np.linalg.norm(X, 'fro'))
  110. else:
  111. W = W[0]
  112. f = np.square(np.linalg.norm(X - np.multiply(W, np.dot(G, F)), 'fro')) / np.square(np.linalg.norm(X, 'fro'))
  113. return f