コード例 #1
0
ファイル: cp.py プロジェクト: FrossoPap/thesis
def als(X, rank, **kwargs):
    """
    Alternating least-sqaures algorithm to compute the CP decomposition.

    Parameters
    ----------
    X : tensor_mixin
        The tensor to be decomposed.
    rank : int
        Tensor rank of the decomposition.
    init : {'random', 'nvecs'}, optional
        The initialization method to use.
            - random : Factor matrices are initialized randomly.
            - nvecs : Factor matrices are initialzed via HOSVD.
        (default 'nvecs')
    max_iter : int, optional
        Maximium number of iterations of the ALS algorithm.
        (default 500)
    fit_method : {'full', None}
        The method to compute the fit of the factorization
            - 'full' : Compute least-squares fit of the dense approximation of.
                       X and X.
            - None : Do not compute the fit of the factorization, but iterate
                     until ``max_iter`` (Useful for large-scale tensors).
        (default 'full')
    conv : float
        Convergence tolerance on difference of fit between iterations
        (default 1e-5)

    Returns
    -------
    P : ktensor
        Rank ``rank`` factorization of X. ``P.U[i]`` corresponds to the factor
        matrix for the i-th mode. ``P.lambda[i]`` corresponds to the weight
        of the i-th mode.
    fit : float
        Fit of the factorization compared to ``X``
    itr : int
        Number of iterations that were needed until convergence
    exectimes : ndarray of floats
        Time needed for each single iteration

    Examples
    --------
    Create random dense tensor

    >>> from sktensor import dtensor, ktensor
    >>> U = [np.random.rand(i,3) for i in (20, 10, 14)]
    >>> T = dtensor(ktensor(U).toarray())

    Compute rank-3 CP decomposition of ``T`` with ALS

    >>> P, fit, itr, _ = als(T, 3)

    Result is a decomposed tensor stored as a Kruskal operator

    >>> type(P)
    <class 'sktensor.ktensor.ktensor'>

    Factorization should be close to original data

    >>> np.allclose(T, P.totensor())
    True

    References
    ----------
    .. [1] Kolda, T. G. & Bader, B. W.
           Tensor Decompositions and Applications.
           SIAM Rev. 51, 455–500 (2009).
    .. [2] Harshman, R. A.
           Foundations of the PARAFAC procedure: models and conditions for an 'explanatory' multimodal factor analysis.
           UCLA Working Papers in Phonetics 16, (1970).
    .. [3] Carroll, J. D.,  Chang, J. J.
           Analysis of individual differences in multidimensional scaling via an N-way generalization of 'Eckart-Young' decomposition.
           Psychometrika 35, 283–319 (1970).
    """

    # init options
    ainit = kwargs.pop('init', _DEF_INIT)
    maxiter = kwargs.pop('max_iter', _DEF_MAXITER)
    fit_method = kwargs.pop('fit_method', _DEF_FIT_METHOD)
    conv = kwargs.pop('conv', _DEF_CONV)
    dtype = kwargs.pop('dtype', _DEF_TYPE)
    if not len(kwargs) == 0:
        raise ValueError('Unknown keywords (%s)' % (kwargs.keys()))

    N = X.ndim
    normX = norm(X)

    U = _init(ainit, X, N, rank, dtype)
    fit = 0
    exectimes = []
    for itr in range(maxiter):
        tic = time.clock()
        fitold = fit

        for n in range(N):
            Unew = X.uttkrp(U, n)
            Y = ones((rank, rank), dtype=dtype)
            for i in (list(range(n)) + list(range(n + 1, N))):
                Y = Y * dot(U[i].T, U[i])
            Unew = Unew.dot(pinv(Y))
            # Normalize
            if itr == 0:
                lmbda = sqrt((Unew**2).sum(axis=0))
            else:
                lmbda = Unew.max(axis=0)
                lmbda[lmbda < 1] = 1
            U[n] = Unew / lmbda

        P = ktensor(U, lmbda)
        if fit_method == 'full':
            normresidual = normX**2 + P.norm()**2 - 2 * P.innerprod(X)
            fit = 1 - (normresidual / normX**2)
        else:
            fit = itr
        fitchange = abs(fitold - fit)
        exectimes.append(time.clock() - tic)
        #print('fitchange:', fitchange)
        _log.debug('[%3d] fit: %.5f | delta: %7.1e | secs: %.5f' %
                   (itr, fit, fitchange, exectimes[-1]))
        if itr > 0 and fitchange < conv:
            break

    return P, fit, itr, array(exectimes)
コード例 #2
0
ファイル: classcpb.py プロジェクト: FrossoPap/thesis
def als(X, Yl, rank, **kwargs):
    """
    Alternating least-sqaures algorithm to compute the CP decomposition taking into 
    consideration the labels of the set
    Yl -> lx1
    X -> pxuxu
    """

    # init options
    ainit = kwargs.pop('init', _DEF_INIT)
    maxiter = kwargs.pop('max_iter', _DEF_MAXITER)
    fit_method = kwargs.pop('fit_method', _DEF_FIT_METHOD)
    conv = kwargs.pop('conv', _DEF_CONV)
    dtype = kwargs.pop('dtype', _DEF_TYPE)
    if not len(kwargs) == 0:
        raise ValueError('Unknown keywords (%s)' % (kwargs.keys()))

    N = X.ndim
    normX = norm(X)

    Yl = np.asarray(Yl)
    Yl = np.reshape(Yl, (-1, 1))
    normYl = np.linalg.norm(Yl)

    U = _init(ainit, X, N, rank, dtype)
    fit = 0

    vecX = np.reshape(X, (np.product(X.shape), ))

    W = ones((rank, 1), dtype=dtype)

    l = Yl.shape[0]
    p = 182
    D = np.zeros((l, p))
    for i in range(l):
        for j in range(l):
            if i == j:
                D[i, j] = 1

    for itr in range(maxiter):
        fitold = fit
        for n in range(N):
            Unew = X.uttkrp(U, n)
            # Y is ZtZ
            Y = ones((rank, rank), dtype=dtype)
            for i in (list(range(n)) + list(range(n + 1, N))):
                Y = Y * dot(U[i].T, U[i])
            if n != 1:
                # Updates remain the same for U0,U2
                Unew = Unew.dot(pinv(Y))
            else:
                Ip = np.identity(p)
                IptIp = dot(Ip.T, Ip)
                GtG = np.kron(Y, IptIp)
                vecA = np.reshape(U[1], (np.product(U[1].shape), 1))
                GtvecX1 = dot(GtG, vecA)

                L = np.kron(W.T, D)
                LtL = dot(L.T, L)

                Sum1 = inv(GtG + LtL)
                dot0 = dot(L.T, Yl)
                Sum2 = GtvecX1 + dot0
                vecA = dot(Sum1, Sum2)

                Unew = np.reshape(vecA, (p, rank))

            # Normalize
            if itr == 0:
                lmbda = sqrt((Unew**2).sum(axis=0))
            else:
                lmbda = Unew.max(axis=0)
                lmbda[lmbda < 1] = 1

            U[n] = Unew / lmbda

        # update W
        AtDt = dot(U[1].T, D.T)
        DA = dot(D, U[1])
        inv1 = inv(dot(AtDt, DA))
        #print('ok inv')
        dot2 = dot(AtDt, Yl)
        W = dot(inv1, dot2)

        P = ktensor(U, lmbda)
        A = U[1]
        Ai = A[146:]

        ypred = dot(Ai, W)
        ypred[abs(ypred) > 0.5] = 1
        ypred[abs(ypred) < 0.5] = 0

        DAW = dot(DA, W)
        normDAW = np.linalg.norm(DAW)

        if fit_method == 'full':
            normresidual1 = normX**2 + P.norm()**2 - 2 * P.innerprod(X)
            normresidual2 = normYl**2 + normDAW**2 - 2 * dot(Yl.T, DAW)
            normresidual = normresidual1 + normresidual2
            #fit = 1 - (normresidual / normX ** 2)
            fit = normresidual
        else:
            fit = itr

        fitchange = abs(fitold - fit) / fitold
        #print('fitchange:',fitchange)

        if itr > 0 and fitchange < conv:
            #print(ypred)
            break

    #print(ypred)
    ypred[abs(ypred) > 0.5] = 1
    ypred[abs(ypred) < 0.5] = 0
    #print(ypred)

    return P, ypred, fit, itr
コード例 #3
0
ファイル: factorize.py プロジェクト: parthatalukdar/TFBA
def NN_Factorize(rank, Iters, odir, lambdas, FIT):


	gstart = datetime.datetime.now()

	Factors, G = Initialize(rank)

	print "Initialization Done\n" 

	I = X1.shape[0]
	J = X1.shape[1]
	K = X2.shape[1]

	print "*** Input Summary ***\n"
	print "X1 : "+ str(X1.shape)
	print "X2 : "+ str(X2.shape)
	print "X3 : "+ str(X3.shape)
	print "Factorization rank: "+str(rank)

	lambda_a = lambdas[0]
	lambda_b = lambdas[1]
	lambda_c = lambdas[2]
	
	
	odir = os.path.join(args.odir,"_"+str(rank[0])+"_"+str(rank[1])+"_"+str(rank[2])+"_"+str(lambda_a)+"_"+str(lambda_b)+"_"+str(lambda_c))
	ep = 1e-9
	conv = 1e-9

	Logs = os.path.join(odir,"Logs")
	
	if not os.path.exists(Logs):
		os.makedirs(Logs)

	
	normX1 = norm(X1)
	normX2 = norm(X2)
	normX3 = norm(X3)

	fit = np.zeros(3)
	avgFit = 0

	for iter in range(1,Iters+1):
		print "\n Starting Iteration: "+str(iter)+"\n"

		if iter%5 == 0:
			pickle.dump(Factors,open(os.path.join(Logs,"Factors_"+str(iter)),"wb"))
			pickle.dump(G,open(os.path.join(Logs,"Core_"+str(iter)),"wb"))

		start = datetime.datetime.now()

		FactorsT_T = [np.dot(M.T,M) for M in Factors]


		G_1 = dtensor(G[0])
		G_2 = dtensor(G[1])
		G_3 = dtensor(G[2])
		
		## Updating A

		GB = G_1.ttm(Factors[1], mode =1, transp=False)
		GB = GB.unfold(0)		
		GC = G_3.ttm(Factors[2], mode =1, transp=False)
		GC = GC.unfold(0)
		Num_A = X1.unfold(0,transp=False).tocsr()
		Num_A = Num_A.dot(GB.T)
		Num_A += X3.unfold(0,transp=False).tocsr().dot(GC.T)
		Denom_A = np.dot(GB, GB.T) + np.dot(GC, GC.T)
		Denom_A = np.dot(Factors[0], Denom_A)
		Denom_A += np.multiply(lambda_a, Factors[0])
		Denom_A += ep

		## updating B

		GA = G_1.ttm(Factors[0], mode =0, transp=False)
		GA = GA.unfold(1)
		GC = G_2.ttm(Factors[2], mode =1, transp=False)
		GC = GC.unfold(0)
		Num_B = X1.unfold(1,transp=False).tocsr()
		Num_B = Num_B.dot(GA.T)
		Num_B += X2.unfold(0,transp=False).tocsr().dot(GC.T)
		Denom_B = np.dot(GA, GA.T) + np.dot(GC, GC.T)  
		Denom_B = np.dot(Factors[1],Denom_B)
		Denom_B += np.multiply(lambda_b, Factors[1])
		Denom_B += ep

		## updating C

		GB = G_2.ttm(Factors[1], mode =0, transp=False)
		GB = GB.unfold(1)
		GA = G_3.ttm(Factors[0], mode =0, transp=False)
		GA = GA.unfold(1)
		Num_C = X2.unfold(1,transp=False).tocsr()
		Num_C = Num_C.dot(GB.T)
		Num_C += X3.unfold(1,transp=False).tocsr().dot(GA.T)
		Denom_C = np.dot(GA, GA.T) + np.dot(GB, GB.T)
		Denom_C = np.dot(Factors[2],Denom_C)
		Denom_C += np.multiply(lambda_c, Factors[2])
		Denom_C += ep

		## Updating Cores 

		Num = X1.ttm(Factors[0],mode = 0,transp=True)
		Num = Num.ttm(Factors[1], mode=1, transp=True)
		Denom = G_1.ttm(FactorsT_T[0],mode=0,transp=True)
		Denom = Denom.ttm(FactorsT_T[1], mode=1, transp=True)
		Denom += ep

		G[0] = np.multiply(G[0], np.divide(Num, Denom))


		Num = X2.ttm(Factors[1],mode = 0,transp=True)
		Num = Num.ttm(Factors[2], mode=1, transp=True)
		Denom = G_2.ttm(FactorsT_T[1],mode=0,transp=True)
		Denom = Denom.ttm(FactorsT_T[2], mode=1, transp=True)
		Denom += ep

		G[1] = np.multiply(G[1], np.divide(Num, Denom))

		Num = X3.ttm(Factors[0],mode = 0,transp=True)
		Num = Num.ttm(Factors[2], mode=1, transp=True)
		Denom = G_3.ttm(FactorsT_T[0],mode=0,transp=True)
		Denom = Denom.ttm(FactorsT_T[2], mode=1, transp=True)
		Denom += ep

		G[2] = np.multiply(G[2], np.divide(Num, Denom))


		Factors[0] = np.multiply(Factors[0], np.divide(Num_A, Denom_A))
		Factors[1] = np.multiply(Factors[1], np.divide(Num_B, Denom_B))
		Factors[2] = np.multiply(Factors[2], np.divide(Num_C, Denom_C))


		'''if FIT =='Y':

			G_1 = dtensor(G[0])
			G_2 = dtensor(G[1])
			G_3 = dtensor(G[2])

			
			normRes1 = sqrt(np.abs(normX1 ** 2 - norm(G[0]) ** 2))
			normRes2 = sqrt(np.abs(normX2 ** 2 - norm(G[1]) ** 2))
			normRes3 = sqrt(np.abs(normX3 ** 2 - norm(G[2]) ** 2))

			fit[0] = 1 - (normRes1/normX1)
			fit[1] = 1 - (normRes2/normX2)
			fit[2] = 1 - (normRes3/normX3)

			avgFit = sum(fit)/3

			print "\n Average Fit: "+str(avgFit)
			print "\n Fit: "+str(fit)

			if abs(avgFit-avgFitOld) < conv:
				break'''

		end = datetime.datetime.now()

		print "Time taken for Iteration: "+str(end-start)



	end = datetime.datetime.now()
	total_time = str(end-gstart)
	print "\n Total factorization time: "+total_time

	pickle.dump(Factors,open(os.path.join(odir,"Factors"),"wb"))
	pickle.dump(G,open(os.path.join(odir,"Core"),"wb"))



	## Writing Schemas
	dictIDS1 = {}
	dictIDS2 = {}
	dictIDS3 = {}
	idx = 0
	for i in range(rank[0]):
		for j in range(rank[1]):			
			dictIDS1[idx] = str(i)+","+str(j)
			idx += 1

	idx = 0
	for i in range(rank[1]):
		for j in range(rank[2]):			
			dictIDS2[idx] = str(i)+","+str(j)
			idx += 1

	idx = 0
	for i in range(rank[0]):
		for j in range(rank[2]):			
			dictIDS3[idx] = str(i)+","+str(j)
			idx += 1


	dictIDS={}
	dictIDS[0] = dictIDS1
	dictIDS[1] = dictIDS2
	dictIDS[2] = dictIDS3

	tops = 6
	Agents =[]
	Patients = []
	Instruments = []

	fp = open(os.path.join(odir,'Agents.txt'), 'w')
	for col in range(rank[0]):
		topIds = np.argsort(Factors[0][:,col])[::-1][:tops]
		fp.write("Topic-"+str(col)+":")
		l = []
		for id in topIds:
			fp.write("\t"+agents[id]+" ,"+str(Factors[0][id,col]))
			l.append(agents[id])

		Agents.append(l)

		fp.write("\n")

	fp.close()

	fp = open(os.path.join(odir,'Patients.txt'), 'w')
	for col in range(rank[1]):
		topIds = np.argsort(Factors[1][:,col])[::-1][:tops]
		fp.write("Topic-"+str(col)+":")
		l = []
		for id in topIds:
			fp.write("\t"+patnts[id]+" ,"+str(Factors[1][id,col]))
			l.append(patnts[id])

		Patients.append(l)
		fp.write("\n")

	fp.close()

	fp = open(os.path.join(odir,'Instruments.txt'), 'w')
	for col in range(rank[2]):
		topIds = np.argsort(Factors[2][:,col])[::-1][:tops]
		fp.write("Topic-"+str(col)+":")
		l = []
		for id in topIds:
			fp.write("\t"+instmnts[id]+" ,"+str(Factors[2][id,col]))
			l.append(instmnts[id])

		Instruments.append(l)

		fp.write("\n")

	fp.close()

	
	sp = open(os.path.join(odir, "Schemas.txt"),'w')
	for p in range(len(predicates)):
		sp.write(predicates[p]+":\n")
		ids1 = np.argsort(G[0][:,:,p], axis=None)[::-1][:8]
		ids2 = np.argsort(G[1][:,:,p], axis=None)[::-1][:8]
		ids3 = np.argsort(G[2][:,:,p], axis=None)[::-1][:8]

		idx1 = [dictIDS1[idx] for idx in ids1]
		idx2 = [dictIDS2[idx] for idx in ids2]
		idx3 = [dictIDS3[idx] for idx in ids3]

		schemas = getSchema(idx1[:3],idx2[:3],idx3[:3])

		if len(schemas) == 0:
			schemas = getSchema(idx1,idx2,idx3)

		h_schemas = mergeSchemas(schemas)
		if len(h_schemas)>0:
			for s in range(len(h_schemas)):
				schm = h_schemas[s]
				print schm
				sp.write(str(Agents[schm[0]])+"\n")
				sp.write(str(Patients[schm[1]])+"\n")
				sp.write(str(Instruments[schm[2]])+"\n")
				sp.write(str(Instruments[schm[3]])+"\n")
				sp.write("---------------------\n")


		if len(schemas)>0:
			for s  in range(len(schemas)):
				schm = schemas[s]
				print schm
				sp.write(str(Agents[schm[0]])+"\n")
				sp.write(str(Patients[schm[1]])+"\n")
				sp.write(str(Instruments[schm[2]])+"\n")
				sp.write("---------------------\n")

		sp.write("\n\n")

	sp.close()


	
	for g in range(len(G)):
		np_file = os.path.join(odir, "Schemas_"+str(g)+".txt")
		fp = open(np_file,'w')
		for p in range(len(predicates)):			
			ids = np.argsort(G[g][:,:,p], axis=None)[::-1][:5]
			fp.write(predicates[p]+":\n")
			fp.write(dictIDS[g][ids[0]]+"\t"+dictIDS[g][ids[1]]+"\t"+dictIDS[g][ids[2]]+"\t"+dictIDS[g][ids[3]]+"\t"+dictIDS[g][ids[4]]+"\n")

		fp.close()


	
	start = datetime.datetime.now()
	## Fit Computation
	
	if FIT == 'Y':
		print "Computing Fit ...\n"
		f = 0
		A = np.array(X1.subs)
		for p in range(len(predicates)):			
			sidx = np.where(A[2]==p)
			G_p = np.dot(Factors[0], np.dot(G[0][:,:,p], Factors[1].T))
			for idx in sidx:
				G_p[A[0,idx],A[1,idx]] = X1.vals[idx] - G_p[A[0,idx],A[1,idx]]
			
			
			f += np.linalg.norm(G_p)

		fit[0] = 1 - (f/normX1)


		f = 0
		A = np.array(X2.subs)		
		for p in range(len(predicates)):			
			sidx = np.where(A[2]==p)
			G_p = np.dot(Factors[1], np.dot(G[1][:,:,p], Factors[2].T))
			for idx in sidx:
				G_p[A[0,idx],A[1,idx]] = X2.vals[idx] - G_p[A[0,idx],A[1,idx]]
			
			
			f += np.linalg.norm(G_p)

		fit[1] = 1 - (f/normX2)

		f = 0		
		A = np.array(X3.subs)		
		for p in range(len(predicates)):			
			sidx = np.where(A[2]==p)
			G_p = np.dot(Factors[0], np.dot(G[2][:,:,p], Factors[2].T))
			for idx in sidx:
				G_p[A[0,idx],A[1,idx]] = X3.vals[idx] - G_p[A[0,idx],A[1,idx]]
			
			
			f += np.linalg.norm(G_p)

		fit[2] = 1 - (f/normX3)
		
				
		avgFit = sum(fit)/3

		fp = open(os.path.join(odir,"Fit.txt"),'w')
		fp.write("Fit:\t")
		fp.write(str(fit)+"\n")
		fp.write("Average Fit: "+str(avgFit))
		fp.close()

		end = datetime.datetime.now()
		print "Fit Computation Time: "+str(end-start)
コード例 #4
0
ファイル: foldin.py プロジェクト: FrossoPap/thesis
def fold_in(X, Uold, rank, **kwargs):

    # init options
    ainit = kwargs.pop('init', _DEF_INIT)
    maxiter = kwargs.pop('max_iter', _DEF_MAXITER)
    fit_method = kwargs.pop('fit_method', _DEF_FIT_METHOD)
    conv = kwargs.pop('conv', _DEF_CONV)
    dtype = kwargs.pop('dtype', _DEF_TYPE)

    if not len(kwargs) == 0:
        raise ValueError('Unknown keywords (%s)' % (kwargs.keys()))

    N = X.ndim
    normX = norm(X)

    U = _init(ainit, X, N, Uold, rank, dtype)
    fit = 0
    O = U[1]
    exectimes = []
    for itr in range(maxiter):
        #print(itr)
        tic = time.clock()
        fitold = fit
        n = 1  # Mode 1 is the array that changes
        Unew = X.uttkrp(U, n)
        '''       
        # Can't implement because of memory error
        n, p = U[0].shape
        m, pC = U[2].shape
        print('n -> U[0], m-> U[2] ROWS', n, m)
        C = np.einsum('ij, kj -> ikj', U[0], U[2]).reshape(m * n, p)
        nk, ni, nj = X.shape
        jk = nk * nj
        sess = tf.Session()
        with sess.as_default():
           Xnew = tf.reshape(X, [1,jk])
           Xnew = Xnew.eval()
        print('C shape:', C.shape)
        print('Xnew shape:', Xnew.shape)
        Z = Xnew.dot(pinv(C))
        Unew = (Unew.dot(Z)).dot(inv(Unew))
        '''
        Y = ones((rank, rank), dtype=dtype)
        for i in (list(range(n)) + list(range(n + 1, N))):
            Y = Y * dot(U[i].T, U[i])
        Unew = Unew.dot(pinv(Y))
        #O = O*Unew/(O.dot(Y))
        # Normalize

        if itr == 0:
            lmbda = sqrt((Unew**2).sum(axis=0))
        else:
            lmbda = Unew.max(axis=0)
            lmbda[lmbda < 1] = 1
        '''
        if itr == 0:
            lmbda = sqrt((O ** 2).sum(axis=0))
        else:
            lmbda = O.max(axis=0)
            lmbda[lmbda < 1] = 1
        '''
        U[1] = Unew / lmbda
        #U[1] = O / lmbda
        P = ktensor(U, lmbda)

        if fit_method == 'full':
            normresidual = normX**2 + P.norm()**2 - 2 * P.innerprod(X)
            #normresidual = normX ** 2 + np.linalg.norm(U[1]) ** 2 - 2 * (np.linalg.norm(U[1]))*(X)
            fit = 1 - (normresidual / normX**2)
        else:
            fit = itr

        fitchange = abs(fitold - fit)
        exectimes.append(time.clock() - tic)

        if itr > 0 and fitchange < conv:
            break

    return U[1], P
コード例 #5
0
def orth_als(X, rank, **kwargs):
    """
    Orthogonalized Alternating least-sqaures algorithm to compute the CP decomposition.
    
    Orth-ALS is a variant of standard ALS where the factor estimates are
    orthogonalized before the ALS step. The orthogonalization may be continued till the end, or
    up to a fixed number of iterations. 

    For more details about Orth-ALS, see reference [4].

    Parameters
    ----------
    X : tensor_mixin
        The tensor to be decomposed.
    rank : int
        Tensor rank of the decomposition.
    init : {'random', 'nvecs'}, optional
        The initialization method to use.
            - random : Factor matrices are initialized randomly.
            - nvecs :  Factor matrices are initialzed via HOSVD.
        (default 'nvecs')
    max_iter : int, optional
        Maximium number of iterations of the ALS algorithm.
        (default 500)
    stop_orth: int, optional
        Number of iterations till which orthogonalization is to be continued
        (default 5)
    fit_method : {'full', None}
        The method to compute the fit of the factorization
            - 'full' : Compute least-squares fit of the dense approximation of.
                       X and X.
            - None : Do not compute the fit of the factorization, but iterate
                     until ``max_iter`` (Useful for large-scale tensors).
        (default 'full')
    conv : float
        Convergence tolerance on difference of fit between iterations
        (default 1e-5)

    Returns
    -------
    P : ktensor
        Rank ``rank`` factorization of X. ``P.U[i]`` corresponds to the factor
        matrix for the i-th mode. ``P.lambda[i]`` corresponds to the weight
        of the i-th mode.
    fit : float
        Fit of the factorization compared to ``X``
    itr : int
        Number of iterations that were needed until convergence
    exectimes : ndarray of floats
        Time needed for each single iteration

    Examples
    --------
    Create random dense tensor

    >>> from sktensor import dtensor, ktensor
    >>> U = [np.random.rand(i,3) for i in (20, 10, 14)]
    >>> T = dtensor(ktensor(U).toarray())

    Compute rank-3 CP decomposition of ``T`` with Orth-ALS/ Hybrid-ALS

    >>> P, fit, itr, _ = als(T, 3)

    Result is a decomposed tensor stored as a Kruskal operator

    >>> type(P)
    <class 'sktensor.ktensor.ktensor'>

    Factorization should be close to original data

    >>> np.allclose(T, P.totensor())
    True

    References
    ----------
    .. [1] Kolda, T. G. & Bader, B. W.
           Tensor Decompositions and Applications.
           SIAM Rev. 51, 455–500 (2009).
    .. [2] Harshman, R. A.
           Foundations of the PARAFAC procedure: models and conditions for an 'explanatory' multimodal factor analysis.
           UCLA Working Papers in Phonetics 16, (1970).
    .. [3] Carroll, J. D.,  Chang, J. J.
           Analysis of individual differences in multidimensional scaling 
           via an N-way generalization of 'Eckart-Young' decomposition.
           Psychometrika 35, 283–319 (1970).
    .. [4] V. Sharan, G. Valiant
           Orthogonalized ALS: A Theoretically Principled Tensor Decomposition Algorithm for Practical Use 
           arXiv:1703.01804, 2017
    """

    # init options
    ainit = kwargs.pop('init', _DEF_INIT)
    maxiter = kwargs.pop('max_iter', _DEF_MAXITER)
    fit_method = kwargs.pop('fit_method', _DEF_FIT_METHOD)
    conv = kwargs.pop('conv', _DEF_CONV)
    stop_orth = kwargs.pop('stop_orth', _DEF_STOP_ORTH)
    dtype = kwargs.pop('dtype', _DEF_TYPE)
    if not len(kwargs) == 0:
        raise ValueError('Unknown keywords (%s)' % (kwargs.keys()))

    N = X.ndim
    normX = norm(X)

    logging.info('')
    U = _init(ainit, X, N, rank, dtype)
    logging.info('')
    fit = 0
    exectimes = []
    for itr in range(maxiter):
        tic = time.clock()
        fitold = fit

        if itr != 0 and itr < stop_orth:

            t = U[0].shape
            dim_max = t[0] - 1
            for n in range(N):
                t = U[n].shape
                if (t[0] - 1) < dim_max:
                    dim_max = t[0] - 1

            for n in range(N):

                Q = U[n]
                t = Q.shape
                J = t[1]
                count = 0
                for i in range(J):

                    if LA.norm(Q[:, i] == 0):
                        count += 1
                        # _log.debug(
                        # 'Zero norm, mode %d' % (n)
                        # )
                        Q[:, i] = rand(t[0])
                        Q[:, i] = Q[:, i] / LA.norm(Q[:, i])
                    else:
                        Q[:, i] = Q[:, i] / LA.norm(Q[:, i])
                    if i <= dim_max:
                        for j in range(i + 1, J):
                            Q[:, j] = Q[:, j] - 1 * np.inner(Q[:, j],
                                                             Q[:, i]) * Q[:, i]
                U[n] = Q

                _log.debug('Zero norm, mode %d, count %d' % (n, count))

        for n in range(N):
            Unew = X.uttkrp(U, n)
            Y = ones((rank, rank), dtype=dtype)
            for i in (list(range(n)) + list(range(n + 1, N))):
                Y = Y * dot(U[i].T, U[i])
            Unew = Unew.dot(pinv(Y))
            # Normalize
            if itr == 0:
                lmbda = sqrt((Unew**2).sum(axis=0))
            else:
                lmbda = Unew.max(axis=0)
                lmbda[lmbda < 1] = 1
            U[n] = Unew / lmbda

        P = ktensor(U, lmbda)
        if fit_method == 'full':
            normresidual = normX**2 + P.norm()**2 - 2 * P.innerprod(X)
            fit = 1 - (normresidual / normX**2)
        else:
            fit = itr
        fitchange = abs(fitold - fit)
        exectimes.append(time.clock() - tic)
        _log.debug('[%3d] fit: %.5f | delta: %7.1e | secs: %.5f' %
                   (itr, fit, fitchange, exectimes[-1]))
        if itr > 0 and fitchange < conv:
            break

    return P, fit, itr, array(exectimes)
コード例 #6
0
def hooi(X, rank=0, **kwargs):
    """
    Compute Tucker decomposition of a tensor using Higher-Order Orthogonal
    Iterations.

    Parameters
    ----------
    X : tensor_mixin
        The tensor to be decomposed
    rank : array_like
        The rank of the decomposition for each mode of the tensor.
        The length of ``rank`` must match the number of modes of ``X``.
    init : {'random', 'nvecs'}, optional
        The initialization method to use.
            - random : Factor matrices are initialized randomly.
            - nvecs : Factor matrices are initialzed via HOSVD.
        default : 'nvecs'

    Examples
    --------
    Create dense tensor

    >>> T = np.zeros((3, 4, 2))
    >>> T[:, :, 0] = [[ 1,  4,  7, 10], [ 2,  5,  8, 11], [3,  6,  9, 12]]
    >>> T[:, :, 1] = [[13, 16, 19, 22], [14, 17, 20, 23], [15, 18, 21, 24]]
    >>> T = dtensor(T)

    Compute Tucker decomposition of ``T`` with n-rank [2, 3, 1] via higher-order
    orthogonal iterations

    >>> Y = hooi(T, [2, 3, 1], init='nvecs')

    Shape of the core tensor matches n-rank of the decomposition.

    >>> Y['core'].shape
    (2, 3, 1)
    >>> Y['U'][1].shape
    (3, 2)

    References
    ----------
    .. [1] L. De Lathauwer, B. De Moor, J. Vandewalle: On the best rank-1 and
           rank-(R_1, R_2, \ldots, R_N) approximation of higher order tensors;
           IEEE Trans. Signal Process. 49 (2001), pp. 2262-2271
    """
    # init options
    ainit = kwargs.pop('init', __DEF_INIT)
    maxIter = kwargs.pop('maxIter', __DEF_MAXITER)
    conv = kwargs.pop('conv', __DEF_CONV)
    dtype = kwargs.pop('dtype', X.dtype)
    if not len(kwargs) == 0:
        raise ValueError('Unknown keywords (%s)' % (list(kwargs.keys())))

    use_full_svd = False

    ndims = X.ndim
    if is_number(rank):
        if rank == 0:
            use_full_svd = True
        else:
            rank = rank * ones(ndims)

    if use_full_svd:
        core = X
        U = []
        for dimension in np.arange(ndims):
            # from tensor_hosvd.m of MATLAB tensor_toolkit (MTT) for rank 0 for all dimensions
            # http://www.sandia.gov/~tgkolda/TensorToolbox/
            M = tenmat(X, dimension).as_ndarray()
            U_dim, S, Vh = np.linalg.svd(M)
            U.append(U_dim)
            core = ttm(core, U_dim.T, dimension, transp=True)

    else:
        normX = norm(X)

        U = __init(ainit, X, ndims, rank, dtype)
        fit = 0
        exectimes = []
        for itr in range(maxIter):
            tic = time.clock()
            fitold = fit

            for n in range(ndims):
                Utilde = ttm(X, U, n, transp=True, without=True)
                U[n] = nvecs(Utilde, n, rank[n])

            # compute core tensor to get fit
            core = ttm(Utilde, U, n, transp=True)

            # since factors are orthonormal, compute fit on core tensor
            normresidual = sqrt(normX**2 - norm(core)**2)

            # fraction explained by model
            fit = 1 - (normresidual / normX)
            fitchange = abs(fitold - fit)
            exectimes.append(time.clock() - tic)

            _log.debug('[%3d] fit: %.5f | delta: %7.1e | secs: %.5f' %
                       (itr, fit, fitchange, exectimes[-1]))
            if itr > 1 and fitchange < conv:
                break
    return core, U