Khatri matrix product using np.tensordot

I am trying to decompose the tensor (m, n, o) into the matrices A (m, r), B (n, r) and C (k, r). This is known as PARAFAC decomposition. Tensorly already performs this kind of decomposition.

An important step is to multiply A, B, and C to get the tensor of the form (m, n, o).

Tessno does it as follows:

def kt_to_tensor(A, B, C):
    factors = [A, B, C]
    for r in range(factors[0].shape[1]):
        vecs = np.ix_(*[u[:, r] for u in factors])
        if r:
            res += reduce(np.multiply, vecs)
        else:
            res = reduce(np.multiply, vecs)
    return res

However, the package I'm using (Autograd) does not support operations np.ix_. Thus, I wrote a simpler definition as follows:

def new_kt_to_tensor(A, B, C):
    m, n, o = A.shape[0], B.shape[0], C.shape[0]
    out = np.zeros((m, n, o))
    k_max = A.shape[1]
    for alpha in range(0, m):
        for beta in range(0, n):
            for delta in range(0, o):
                for k in range(0, k_max):
                    out[alpha, beta, delta]=out[alpha, beta, delta]+ A[alpha, k]*B[beta, k]*C[delta, k]
    return out

However, it turns out that this implementation also has some aspects that the city does not support. However, autograph support np.tensordot.

, np.tensordot . , Tensorflow tf.tensordot .

:

def tensordot_multplication(A, B, C):
    """
    use np.tensordot
    """
+4
2

, np.tensordot , , , , . , tensordot .

: broadcasting, np.einsum.

№1: broadcasting -

(A[:,None,None,:]*B[:,None,:]*C).sum(-1)

:

  • A 4D, axis=(1,2) None/np.newaxis.

  • B 3D, axis=(1).

  • C , 4D.

  • , 4D.

-

A        : m        r
B        :    n     r
C        :       k  r

=> A*B*C : m  n  k  r
=> out   : m  n  k    # (sum-reduction along last axis)

# 2: np.einsum -

np.einsum('il,jl,kl->ijk',A,B,C)

, broadcasting, , .

broadcasting, , tensorflow, expand dimensions, np.einsum, , .

+3

, , , TensorLy , , .

, TensorLy, :

def kruskal_to_tensor(factors):
    shape = [factor.shape[0] for factor in factors]
    full_tensor = np.dot(factors[0], khatri_rao(factors[1:]).T)
    return fold(full_tensor, 0, shape)

khatri_rao numpy.einsum , , .

+1

Source: https://habr.com/ru/post/1674194/


All Articles