def sample_factor_x(tau_sparse_tensor, tau_ind, U, V, X, beta0=1): """Sampling T-by-R factor matrix X and its hyperparameters.""" dim3, rank = X.shape var_mu_hyper = X[0, :] / (beta0 + 1) dx = X[1:, :] - X[:-1, :] var_V_hyper = inv( np.eye(rank) + dx.T @ dx + beta0 * np.outer(X[0, :], X[0, :]) / (beta0 + 1)) var_Lambda_hyper = wishart.rvs(df=dim3 + rank, scale=var_V_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (beta0 + 1) * var_Lambda_hyper) var1 = kr_prod(V, U).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_ind, 2).T).reshape([rank, rank, dim3]) var4 = var1 @ ten2mat(tau_sparse_tensor, 2).T for t in range(dim3): if t == 0: X[t, :] = mvnrnd_pre((X[t + 1, :] + var_mu_hyper) / 2, var3[:, :, t] + 2 * var_Lambda_hyper) elif t == dim3 - 1: temp1 = var4[:, t] + var_Lambda_hyper @ X[t - 1, :] temp2 = var3[:, :, t] + var_Lambda_hyper X[t, :] = mvnrnd_pre(solve(temp2, temp1), temp2) else: temp1 = var4[:, t] + var_Lambda_hyper @ (X[t - 1, :] + X[t + 1, :]) temp2 = var3[:, :, t] + 2 * var_Lambda_hyper X[t, :] = mvnrnd_pre(solve(temp2, temp1), temp2) return X
def CP_ALS(self,sparse_tensor_ori, rank=50, maxiter=1000): import numpy as np from numpy.linalg import inv as inv def kr_prod(a, b): return np.einsum('ir, jr -> ijr', a, b).reshape(a.shape[0] * b.shape[0], -1) def cp_combine(U, V, X): return np.einsum('is, js, ts -> ijt', U, V, X) def ten2mat(tensor, mode): return np.reshape(np.moveaxis(tensor, mode, 0), (tensor.shape[mode], -1), order='F') sparse_tensor = sparse_tensor_ori.copy() dim1, dim2, dim3 = sparse_tensor.shape dim = np.array([dim1, dim2, dim3]) U = 0.1 * np.random.rand(dim1, rank) V = 0.1 * np.random.rand(dim2, rank) X = 0.1 * np.random.rand(dim3, rank) if np.isnan(sparse_tensor).any(): sparse_tensor[np.isnan(sparse_tensor)] = 0 pos = np.where(sparse_tensor != 0) # pos = np.where(~np.isnan(sparse_tensor)) binary_tensor = np.zeros((dim1, dim2, dim3)) binary_tensor[pos] = 1 tensor_hat = np.zeros((dim1, dim2, dim3)) for iters in range(maxiter): for order in range(dim.shape[0]): if order == 0: var1 = kr_prod(X, V).T elif order == 1: var1 = kr_prod(X, U).T else: var1 = kr_prod(V, U).T var2 = kr_prod(var1, var1) var3 = np.matmul(var2, ten2mat(binary_tensor, order).T).reshape([rank, rank, dim[order]]) var4 = np.matmul(var1, ten2mat(sparse_tensor, order).T) for i in range(dim[order]): var_Lambda = var3[:, :, i] inv_var_Lambda = inv((var_Lambda + var_Lambda.T) / 2 + 10e-12 * np.eye(rank)) vec = np.matmul(inv_var_Lambda, var4[:, i]) if order == 0: U[i, :] = vec.copy() elif order == 1: V[i, :] = vec.copy() else: X[i, :] = vec.copy() tensor_hat = cp_combine(U, V, X) return tensor_hat
def sample_factor_x(tau_sparse_tensor, tau_ind, time_lags, U, V, X, theta, Lambda_x): """Sampling T-by-R factor matrix X.""" dim3, rank = X.shape tmax = np.max(time_lags) tmin = np.min(time_lags) d = time_lags.shape[0] A = np.zeros((d * rank, rank)) for k in range(d): A[k * rank:(k + 1) * rank, :] = np.diag(theta[k, :]) A0 = np.dstack([A] * d) for k in range(d): A0[k * rank:(k + 1) * rank, :, k] = 0 mat0 = Lambda_x @ A.T mat1 = np.einsum('kij, jt -> kit', A.reshape([d, rank, rank]), Lambda_x) mat2 = np.einsum('kit, kjt -> ij', mat1, A.reshape([d, rank, rank])) var1 = kr_prod(V, U).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_ind, 2).T).reshape([rank, rank, dim3 ]) + Lambda_x[:, :, None] var4 = var1 @ ten2mat(tau_sparse_tensor, 2).T for t in range(dim3): Mt = np.zeros((rank, rank)) Nt = np.zeros(rank) Qt = mat0 @ X[t - time_lags, :].reshape(rank * d) index = list(range(0, d)) if t >= dim3 - tmax and t < dim3 - tmin: index = list(np.where(t + time_lags < dim3))[0] elif t < tmax: Qt = np.zeros(rank) index = list(np.where(t + time_lags >= tmax))[0] if t < dim3 - tmin: Mt = mat2.copy() temp = np.zeros((rank * d, len(index))) n = 0 for k in index: temp[:, n] = X[t + time_lags[k] - time_lags, :].reshape(rank * d) n += 1 temp0 = X[t + time_lags[index], :].T - np.einsum( 'ijk, ik -> jk', A0[:, :, index], temp) Nt = np.einsum('kij, jk -> i', mat1[index, :, :], temp0) var3[:, :, t] = var3[:, :, t] + Mt if t < tmax: var3[:, :, t] = var3[:, :, t] - Lambda_x + np.eye(rank) X[t, :] = mvnrnd_pre(solve(var3[:, :, t], var4[:, t] + Nt + Qt), var3[:, :, t]) return X
def sample_factor_w(tau_sparse_mat, tau_ind, W, X, tau, beta0=1, vargin=0): """Sampling N-by-R factor matrix W and its hyperparameters (mu_w, Lambda_w).""" dim1, rank = W.shape W_bar = np.mean(W, axis=0) temp = dim1 / (dim1 + beta0) var_W_hyper = inv( np.eye(rank) + cov_mat(W, W_bar) + temp * beta0 * np.outer(W_bar, W_bar)) var_Lambda_hyper = wishart.rvs(df=dim1 + rank, scale=var_W_hyper) var_mu_hyper = mvnrnd_pre(temp * W_bar, (dim1 + beta0) * var_Lambda_hyper) if dim1 * rank**2 > 1e+8: vargin = 1 if vargin == 0: var1 = X.T var2 = kr_prod(var1, var1) var3 = (var2 @ tau_ind.T).reshape([rank, rank, dim1 ]) + var_Lambda_hyper[:, :, None] var4 = var1 @ tau_sparse_mat.T + ( var_Lambda_hyper @ var_mu_hyper)[:, None] for i in range(dim1): W[i, :] = mvnrnd_pre(solve(var3[:, :, i], var4[:, i]), var3[:, :, i]) elif vargin == 1: for i in range(dim1): pos0 = np.where(tau_sparse_mat[i, :] != 0) Xt = X[pos0[0], :] var_mu = tau[i] * Xt.T @ tau_sparse_mat[ i, pos0[0]] + var_Lambda_hyper @ var_mu_hyper var_Lambda = tau[i] * Xt.T @ Xt + var_Lambda_hyper W[i, :] = mvnrnd_pre(solve(var_Lambda, var_mu), var_Lambda) return W
def sample_factor(tau_sparse, factor, ind, dim, k, tau_eps, beta0=1): dim, rank = factor[k].shape dim = factor[k].shape[0] factor_bar = np.mean(factor[k], axis=0) temp = dim / (dim + beta0) var_mu_hyper = temp * factor_bar var_W_hyper = inv( np.eye(rank) + cov_mat(factor[k], factor_bar) + temp * beta0 * np.outer(factor_bar, factor_bar)) var_Lambda_hyper = wishart.rvs(df=dim + rank, scale=var_W_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (dim + beta0) * var_Lambda_hyper) idx = list(filter(lambda x: x != k, range(len(factor)))) var1 = kr_prod(factor[idx[1]], factor[idx[0]]).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_eps * ind, k).T).reshape([rank, rank, dim]) + var_Lambda_hyper[:, :, np.newaxis] var4 = var1 @ ten2mat(tau_sparse, k).T + (var_Lambda_hyper @ var_mu_hyper)[:, np.newaxis] for i in range(dim): factor[k][i, :] = mvnrnd_pre(solve(var3[:, :, i], var4[:, i]), var3[:, :, i]) return factor[k]
def sample_factor(tau_sparse_tensor, tau_ind, factor, k, beta0=1): dim, rank = factor[k].shape dim = factor[k].shape[0] factor_bar = np.mean(factor[k], axis=0) temp = dim / (dim + beta0) var_mu_hyper = temp * factor_bar # inv计算逆矩阵 var_W_hyper = inv( np.eye(rank) + cov_mat(factor[k], factor_bar) + temp * beta0 * np.outer(factor_bar, factor_bar)) # 从一个wishart分布中随机抽取样本,df为自由度,必须大于或等于尺度矩阵的维数,scale为对称正定比例矩阵的分布 var_Lambda_hyper = wishart.rvs(df=dim + rank, scale=var_W_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (dim + beta0) * var_Lambda_hyper) idx = list(filter(lambda x: x != k, range(len(factor)))) var1 = kr_prod(factor[idx[1]], factor[idx[0]]).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_ind, k).T).reshape([rank, rank, dim]) + var_Lambda_hyper[:, :, np.newaxis] var4 = var1 @ ten2mat(tau_sparse_tensor, k).T + (var_Lambda_hyper @ var_mu_hyper)[:, np.newaxis] for i in range(dim): # solve函数是已知A,B,求一个矩阵X,使得AX=B factor[k][i, :] = mvnrnd_pre(solve(var3[:, :, i], var4[:, i]), var3[:, :, i]) return factor[k]
def sample_factor_v(tau_sparse_tensor, tau_ind, U, V, X, beta0=1): """Sampling N-by-R factor matrix V and its hyperparameters (mu_v, Lambda_v).""" dim2, rank = V.shape V_bar = np.mean(V, axis=0) temp = dim2 / (dim2 + beta0) var_mu_hyper = temp * V_bar var_V_hyper = inv( np.eye(rank) + cov_mat(V, V_bar) + temp * beta0 * np.outer(V_bar, V_bar)) var_Lambda_hyper = wishart.rvs(df=dim2 + rank, scale=var_V_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (dim2 + beta0) * var_Lambda_hyper) var1 = kr_prod(X, U).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_ind, 1).T).reshape( [rank, rank, dim2]) + var_Lambda_hyper[:, :, None] var4 = var1 @ ten2mat(tau_sparse_tensor, 1).T + ( var_Lambda_hyper @ var_mu_hyper)[:, None] for j in range(dim2): V[j, :] = mvnrnd_pre(solve(var3[:, :, j], var4[:, j]), var3[:, :, j]) return V
def sample_factor_u(tau_sparse_tensor, tau_ind, U, V, X, beta0=1): """Sampling M-by-R factor matrix U and its hyperparameters (mu_u, Lambda_u).""" dim1, rank = U.shape U_bar = np.mean(U, axis=0) temp = dim1 / (dim1 + beta0) var_mu_hyper = temp * U_bar var_U_hyper = inv( np.eye(rank) + cov_mat(U, U_bar) + temp * beta0 * np.outer(U_bar, U_bar)) var_Lambda_hyper = wishart.rvs(df=dim1 + rank, scale=var_U_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (dim1 + beta0) * var_Lambda_hyper) var1 = kr_prod(X, V).T var2 = kr_prod(var1, var1) var3 = (var2 @ ten2mat(tau_ind, 0).T).reshape( [rank, rank, dim1]) + var_Lambda_hyper[:, :, None] var4 = var1 @ ten2mat(tau_sparse_tensor, 0).T + ( var_Lambda_hyper @ var_mu_hyper)[:, None] for i in range(dim1): U[i, :] = mvnrnd_pre(solve(var3[:, :, i], var4[:, i]), var3[:, :, i]) return U
def sample_factor_x(tau_sparse_mat, tau_ind, W, X, beta0=1): """Sampling T-by-R factor matrix X and its hyperparameters (mu_x, Lambda_x).""" dim2, rank = X.shape X_bar = np.mean(X, axis=0) temp = dim2 / (dim2 + beta0) var_mu_hyper = temp * X_bar var_X_hyper = inv(np.eye(rank) + cov_mat(X, X_bar) + temp * beta0 * np.outer(X_bar, X_bar)) var_Lambda_hyper = wishart.rvs(df=dim2 + rank, scale=var_X_hyper) var_mu_hyper = mvnrnd_pre(var_mu_hyper, (dim2 + beta0) * var_Lambda_hyper) var1 = W.T var2 = kr_prod(var1, var1) var3 = (var2 @ tau_ind).reshape([rank, rank, dim2]) + var_Lambda_hyper[:, :, np.newaxis] var4 = var1 @ tau_sparse_mat + (var_Lambda_hyper @ var_mu_hyper)[:, np.newaxis] for t in range(dim2): X[t, :] = mvnrnd_pre(solve(var3[:, :, t], var4[:, t]), var3[:, :, t]) return X