|
a |
|
b/inst/scAImodel_py.py |
|
|
1 |
|
|
|
2 |
# python implementation of scAI optimization model |
|
|
3 |
# import packages |
|
|
4 |
import numpy as np |
|
|
5 |
from numpy import linalg as LA |
|
|
6 |
from numpy import matrix |
|
|
7 |
|
|
|
8 |
|
|
|
9 |
def scAImodel_py(X1,X2,K,S=0.25,Alpha=1,Lambda=10000,Gamma=1,Maxiter = 500,Stop_rule=1,Seed=1,W1=None,W2=None,H=None,Z=None,R=None): |
|
|
10 |
# parameters |
|
|
11 |
d1 = X1.shape |
|
|
12 |
d2 = X2.shape |
|
|
13 |
p = d1[0] |
|
|
14 |
n = d1[1] |
|
|
15 |
q = d2[0] |
|
|
16 |
np.random.seed(Seed) |
|
|
17 |
if W1 is None: |
|
|
18 |
W1 = np.random.rand(p,K) |
|
|
19 |
|
|
|
20 |
if W2 is None: |
|
|
21 |
W2 = np.random.rand(q,K) |
|
|
22 |
|
|
|
23 |
if H is None: |
|
|
24 |
H = np.random.rand(K,n) |
|
|
25 |
|
|
|
26 |
if Z is None: |
|
|
27 |
Z = np.random.rand(n,n) |
|
|
28 |
|
|
|
29 |
if R is None: |
|
|
30 |
R = np.random.binomial(1,S,size=(n,n)) |
|
|
31 |
# main function |
|
|
32 |
XtX2 = np.dot(np.transpose(X2),X2) |
|
|
33 |
obj_old = 1 |
|
|
34 |
# W1 = np.asarray(W1) |
|
|
35 |
# W2 = np.asarray(W2) |
|
|
36 |
# Z = np.asarray(Z) |
|
|
37 |
# R = np.asarray(R) |
|
|
38 |
for iter in range(1,Maxiter+1): |
|
|
39 |
# print(iter) |
|
|
40 |
# normalize H |
|
|
41 |
# H = matrix(H) |
|
|
42 |
# lib = np.sum(H,axis = 1) |
|
|
43 |
# H = H/np.tile(lib,(1,n)) |
|
|
44 |
# H = np.asarray(H) |
|
|
45 |
H = H/H.sum(axis=1,keepdims=1) |
|
|
46 |
# update W1 |
|
|
47 |
HHt = np.dot(H,np.transpose(H)) |
|
|
48 |
X1Ht = np.dot(X1,np.transpose(H)) |
|
|
49 |
W1HHt = np.dot(W1,HHt) |
|
|
50 |
W1 = W1*X1Ht/(W1HHt+np.spacing(1)) |
|
|
51 |
# update W2 |
|
|
52 |
ZR = Z*R |
|
|
53 |
ZRHt = np.dot(ZR,np.transpose(H)) |
|
|
54 |
X2ZRHt = np.dot(X2,ZRHt) |
|
|
55 |
W2HHt = np.dot(W2,HHt) |
|
|
56 |
W2 = W2*X2ZRHt/(W2HHt+np.spacing(1)) |
|
|
57 |
# update H |
|
|
58 |
W1tX1 = np.dot(np.transpose(W1),X1) |
|
|
59 |
W2tX2 = np.dot(np.transpose(W2),X2) |
|
|
60 |
W2tX2ZR = np.dot(W2tX2,ZR) |
|
|
61 |
HZZt = np.dot(H,(Z+np.transpose(Z))) |
|
|
62 |
W1tW1 = np.dot(np.transpose(W1),W1) |
|
|
63 |
W2tW2 = np.dot(np.transpose(W2),W2) |
|
|
64 |
H = H*(Alpha*W1tX1+W2tX2ZR+Lambda*HZZt)/(np.dot(Alpha*W1tW1+W2tW2+2*Lambda*HHt+Gamma*np.ones([K,K]),H)+np.spacing(1)) |
|
|
65 |
# update Z |
|
|
66 |
HtH = np.dot(np.transpose(H),H) |
|
|
67 |
X2tW2H = np.dot(np.transpose(W2tX2),H) |
|
|
68 |
RX2tW2H = R*X2tW2H |
|
|
69 |
XtX2ZR = np.dot(XtX2,ZR) |
|
|
70 |
XtX2ZRR = XtX2ZR*R |
|
|
71 |
Z = Z*(RX2tW2H+Lambda*HtH)/(XtX2ZRR+Lambda*Z+np.spacing(1)) |
|
|
72 |
if Stop_rule == 2: |
|
|
73 |
obj = Alpha*pow(LA.norm(X1-np.dot(W1,H),ord = 'fro'),2)+pow(LA.norm(np.dot(X2,ZR)-np.dot(W2,H),ord = 'fro'),2)+Lambda*pow(LA.norm(Z-np.dot(np.transpose(H),H),ord = 'fro'),2)+Gamma*pow(LA.norm(np.dot(np.ones([1,K]),H),ord = 'fro'),2) |
|
|
74 |
if (obj_old-obj)/obj_old < 1e-6 and iter > 1: |
|
|
75 |
break |
|
|
76 |
iter = iter+1 |
|
|
77 |
|
|
|
78 |
# print ("\n") |
|
|
79 |
# print ("## Running scAI with seed %d ##" % Seed) |
|
|
80 |
# print ("\n") |
|
|
81 |
|
|
|
82 |
return W1, W2, H, Z, R |
|
|
83 |
|