def cp_apr(X, R, Minit, outputfile, tol=1e-4, maxiters=150, maxinner=10, epsilon=1e-10, kappatol=1e-10, kappa=1e-2): N = X.ndims() nInnerIters = np.zeros(maxiters); ## Initialize M and Phi for iterations M = Minit prevM = ktensor.copyTensor(M) M.normalize(1) Phi = [[] for i in range(N)] kktModeViolations = np.zeros(N) kktViolations = -np.ones(maxiters) nViolations = np.zeros(maxiters) ## statistics cpStats = np.zeros(7) fmsStats = np.zeros(3) for iter in range(maxiters): startIter = time.time() isConverged = True; for n in range(N): startMode = time.time() ## Make adjustments to M[n] entries that violate complementary slackness if iter > 0: V = np.logical_and(Phi[n] > 1, M.U[n] < kappatol) if np.count_nonzero(V) > 0: nViolations[iter] = nViolations[iter] + 1 M.U[n][V > 0] = M.U[n][V > 0] + kappa # solve the inner problem M, Phi[n], inner, kktModeViolations[n], isConverged = __solveSubproblem(X, M, R, n, N, maxinner, epsilon, tol) nInnerIters[iter] = nInnerIters[iter]+(inner+1) elapsed = time.time()-startMode # only write the outer iterations for now cpStats = np.vstack((cpStats, np.array([iter, n, inner, __lsqr_fit(X,M), __loglikelihood(X,M), kktModeViolations[n], elapsed]))) kktViolations[iter] = np.max(kktModeViolations); elapsed = time.time()-startIter #cpStats = np.vstack((cpStats, np.array([iter, -1, -1, kktViolations[iter], __loglikelihood(X,M), elapsed]))) print("Iteration {0}: Inner Its={1} with KKT violation={2}, nViolations={3}, and elapsed time={4}".format(iter, nInnerIters[iter], kktViolations[iter], nViolations[iter], elapsed)); __writeDBFile(M, outputfile.format(iter), iter) fmsStats = np.vstack((fmsStats, np.array([iter, M.top_fms(prevM), M.greedy_fms(prevM)]))) prevM = ktensor.copyTensor(M) if isConverged: break; cpStats = np.delete(cpStats, (0), axis=0) # delete the first row fmsStats = np.delete(fmsStats, (0), axis=0) # delete the first row ## print out the statistics fit = __lsqr_fit(X,M) ll = __loglikelihood(X,M) print("Number of iterations = {0}".format(iter)) print("Final least squares fit = {0}".format(fit)); print("Final log-likelihood = {0}".format(ll)); print("Final KKT Violation = {0}".format(kktViolations[iter])) print("Total inner iterations = {0}".format(np.sum(nInnerIters))); modelStats = {"Iters" : iter, "LS" : fit, "LL" : ll, "KKT" : kktViolations[iter]} return M, cpStats, fmsStats, modelStats;
def projectData(self, XHat, n, maxiters=10, maxinner=10): ## store off the old ones origM = {REG_LOCATION: ktensor.copyTensor(self.M[REG_LOCATION]), AUG_LOCATION: ktensor.copyTensor(self.M[AUG_LOCATION])} origX = self.X self.X = XHat ## randomize the nth self.M[REG_LOCATION].U[n] = np.random.rand(self.X.shape[n], self.R) self.M[REG_LOCATION].lmbda = np.ones(self.R) self.M[AUG_LOCATION].U[n] = np.random.rand(self.X.shape[n], 1) self.M[AUG_LOCATION].lmbda = np.ones(1) ## renormalize self.M[REG_LOCATION].normalize(1) self.normalizeAugTensor() lastLL = tensorTools.loglikelihood(self.X,self.M) for iteration in range(maxiters): xsubs = self.X.subs[:,n] B, Pi, inI1, kktModeViolation1 = self.__solveSignalTensor(xsubs, self.M[AUG_LOCATION].U[n], n) inI2, kktModeViolation2 = self.__solveAugmentedTensor(xsubs, B, Pi, n) ll = tensorTools.loglikelihood(self.X,self.M) if np.abs(lastLL - ll) < self.dlTol: break lastLL = ll ## scale by summing across the rows totWeight = np.sum(self.M[REG_LOCATION].U[n], axis=1) zeroIdx = np.where(totWeight < 1e-100)[0] if len(zeroIdx) > 0: evenDist = 1.0 / self.M[REG_LOCATION].R self.M[REG_LOCATION].U[n][zeroIdx, :] = np.tile(evenDist, (len(zeroIdx), self.M[REG_LOCATION].R)) totWeight = np.sum(self.M[REG_LOCATION].U[n], axis=1) twMat = np.repeat(totWeight, self.M[REG_LOCATION].R).reshape(self.X.shape[n], self.M[REG_LOCATION].R) projMat = self.M[REG_LOCATION].U[n] / twMat biasMat = self.M[AUG_LOCATION].U[n] self.M = origM self.X = origX return projMat, biasMat
def __loglikelihood(X,MF): """ Computes the log-likelihood of model M given data X. Specifically, ll = -(sum_i m_i - x_i * log_i) where i is a multiindex across all tensor dimensions Parameters ---------- X - input tensor of the class tensor or sptensor MF - ktensor Returns ------- out : log likelihood value """ N = X.ndims(); # make a copy of the tensor so absorbing won't affect it M = ktensor.copyTensor(MF) M.normalize_absorb(0, 1); ll = 0; if X.__class__ == sptensor.sptensor: xsubs = X.subs; A = M.U[0][xsubs[:,0], :]; for n in range(1, N): A = np.multiply(A, M.U[n][xsubs[:,n],:]); ll = np.sum(np.multiply(X.vals.flatten(), np.log(np.sum(A, axis=1)))) - np.sum(M.U[0]); else: ## fill in what to do when it's not sparse tensor ll = -np.sum(M.U[0]); return ll;
def __init__(self, M, R): ## make a copy of the original basis self.basis = [ktensor.copyTensor(m) for m in M] self.R = R