emwnenmf_updateinsideNNLS.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import numpy as np
  2. import time
  3. def emwnenmf(data,G,F,r,Tmax):
  4. MinIter = 10
  5. tol = 1e-5
  6. em_iter_max = round(Tmax/0.05)+1 #
  7. T = np.empty(shape=(em_iter_max+1))
  8. T.fill(np.nan)
  9. RMSE = np.empty(shape=(2,em_iter_max+1))
  10. RMSE.fill(np.nan)
  11. ITER_MAX=100 # maximum inner iteration number (Default)
  12. ITER_MIN=10 # minimum inner iteration number (Default)
  13. np.put(F,data.idxOF,data.sparsePhi_F)
  14. np.put(G,data.idxOG,data.sparsePhi_G)
  15. Xcomp = data.X + np.multiply(data.nW,np.dot(G,F))
  16. FXt = np.dot(F,Xcomp.T)
  17. FFt = np.dot(F,F.T)
  18. GtX = np.dot(G.T,Xcomp)
  19. GtG = np.dot(G.T,G)
  20. GradG = np.dot(G,FFt)-FXt.T
  21. GradF = np.dot(GtG,F)-GtX
  22. init_delta = stop_rule(np.hstack((G.T,F)),np.hstack((GradG.T,GradF)))
  23. tolF = max(tol,1e-3)*init_delta
  24. tolG = tolF # Stopping tolerance
  25. # Iterative updating
  26. G = G.T
  27. k = 0
  28. RMSE[:,k] = np.linalg.norm(F[:,0:-1]-data.F[:,0:-1],2,axis=1)/np.sqrt(F.shape[1]-1)
  29. T[k] = 0
  30. t = time.time()
  31. # Main loop
  32. while time.time()-t <= Tmax+0.05:
  33. # Estimation step
  34. Xcomp = data.X + np.multiply(data.nW,np.dot(G.T,F))
  35. # Compress left and right
  36. L,R = RSI_compression(Xcomp,r)
  37. X_L = np.dot(L,Xcomp)
  38. X_R = np.dot(Xcomp,R)
  39. # Maximisation step
  40. # Optimize F with fixed G
  41. F,iterF,_ = NNLS(F,GtG,GtX,ITER_MIN,ITER_MAX,tolF,data.idxOF,data.sparsePhi_F,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. F_comp = np.dot(F,R)
  48. FFt = np.dot(F_comp,F_comp.T)
  49. FXt = np.dot(F_comp,X_R.T)
  50. # Optimize G with fixed F
  51. G,iterG,GradG = NNLS(G,FFt,FXt,ITER_MIN,ITER_MAX,tolG,data.idxOG,data.sparsePhi_G,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. G_comp = np.dot(G,L.T)
  57. GtG = np.dot(G_comp,G_comp.T)
  58. GtX = np.dot(G_comp,X_L)
  59. GradF = np.dot(GtG,F) - GtX
  60. # Stopping condition
  61. # delta = stop_rule(np.hstack((G,F)),np.hstack((GradG,GradF)))
  62. # if (delta<=tol*init_delta and k>=MinIter):
  63. # print('break before Tmax')
  64. # break
  65. if time.time()-t - k*0.05 >= 0.05:
  66. k = k+1
  67. RMSE[:,k] = np.linalg.norm(F[:,0:-1]-data.F[:,0:-1],2,axis=1)/np.sqrt(F.shape[1]-1)
  68. T[k] = time.time()-t
  69. if k%100==0:
  70. print(str(k)+' '+str(RMSE[0,k])+' '+str(RMSE[1,k])+' '+str(nmf_norm_fro(Xcomp,G.T,F)))
  71. # return {'G' : G.T, 'F' : F, 'RMSE' : RMSE, 'T': T, 'RMSEb' : RMSEb}
  72. return {'G' : G.T, 'F' : F, 'RMSE' : RMSE, 'T': T}
  73. def stop_rule(X,GradX):
  74. # Stopping Criterions
  75. pGrad = GradX[np.any(np.dstack((X>0,GradX<0)),2)]
  76. return np.linalg.norm(pGrad,2)
  77. def NNLS(Z,GtG,GtX,iterMin,iterMax,tol,idxfixed,fixed,transposed):
  78. L = np.linalg.norm(GtG,2) # Lipschitz constant
  79. H = Z # Initialization
  80. Grad = np.dot(GtG,Z)-GtX #Gradient
  81. alpha1 = 1
  82. for iter in range(1,iterMax+1):
  83. H0 = H
  84. H = np.maximum(Z-Grad/L,0) # Calculate squence 'Y'
  85. if transposed: # If Z = G.T
  86. np.put(H.T,idxfixed,fixed)
  87. else: # If Z = F
  88. np.put(H,idxfixed,fixed)
  89. alpha2 = 0.5*(1+np.sqrt(1+4*alpha1**2))
  90. Z = H + ((alpha1-1)/alpha2)*(H-H0)
  91. alpha1 = alpha2
  92. Grad=np.dot(GtG,Z)-GtX
  93. # Stopping criteria
  94. if iter>=iterMin:
  95. # Lin's stopping criteria
  96. pgn = stop_rule(Z,Grad)
  97. if pgn <= tol:
  98. break
  99. return H,iter,Grad
  100. def nmf_norm_fro(X,G,F,*args):
  101. W = args
  102. if len(W)==0:
  103. f = np.square(np.linalg.norm(X-np.dot(G,F),'fro'))/np.square(np.linalg.norm(X,'fro'))
  104. else:
  105. W=W[0]
  106. f = np.square(np.linalg.norm(X-np.multiply(W,np.dot(G,F)),'fro'))/np.square(np.linalg.norm(X,'fro'))
  107. return f
  108. def RSI_compression(X,r):
  109. compressionLevel = 20
  110. m,n = X.shape
  111. l = min(n,max(compressionLevel,r+10))
  112. OmegaL = np.random.randn(n,l)
  113. Y = np.dot(X,OmegaL)
  114. for _ in range(4):
  115. Y = np.linalg.qr(Y,mode='reduced')[0]
  116. S = np.dot(X.T,Y)
  117. Z = np.linalg.qr(S,mode='reduced')[0]
  118. Y = np.dot(X,Z)
  119. L = np.linalg.qr(Y,mode='reduced')[0].T
  120. OmegaR = np.random.randn(l,m)
  121. Y = np.dot(OmegaR,X)
  122. for _ in range(4):
  123. Y = np.linalg.qr(Y.T,mode='reduced')[0]
  124. S = np.dot(X,Y)
  125. Z = np.linalg.qr(S,mode='reduced')[0]
  126. Y = np.dot(Z.T,X)
  127. R = np.linalg.qr(Y.T,mode='reduced')[0]
  128. return L,R