Я пытаюсь разработать тест, чтобы убедиться, что функция partial_tucker
из тензорно работает так, как я ожидаю, что она будет работать. Другими словами, я хочу спроектировать вход для функции partial_tucker
вместе с соответствующим ожидаемым выходным сигналом.
Итак, что я попытался сделать, это взять начальный случайный тензор A
(порядка 4) вычислите его разложение «низшего ранга» вручную, затем восстановите тензор той же формы, что и исходный тензор, скажем A_tilde
. Я думаю, что тензор A_tilde
является тогда «приближением низкого ранга» начального тензора A
. Правильно ли я?
Тогда я хотел бы получить нам partial_tucker
функцию для этого тензора A_tilde
, и я ожидаю, что результат будет таким же, как и разложение Такера, которое я вычислил вручную. Это не тот случай, поэтому я полагаю, что мое разложение ручной работы неверно. Если да, то почему?
import tensorly
import numpy as np
h, w, c, f = 3, 3, 64, 128
c_prim, f_prim = 16, 32
base_tensor = np.random.rand(h, w, c, f)
# compute tucker decomposition by hand using higher order svd describred here: https://www.alexejgossmann.com/tensor_decomposition_tucker/.
lst_fac = []
for k in [2, 3]:
mod_k_unfold = tensorly.base.unfold(base_tensor, k)
U, _, _ = np.linalg.svd(mod_k_unfold)
lst_fac.append(U)
real_in_fac, real_out_fac = lst_fac[0], lst_fac[1]
real_core = multi_mode_dot(base_tensor, [real_in_fac.T, real_out_fac.T], modes=(2,3))
del base_tensor # no need of it anymore
# what i call the "low rank tucker decomposition"
real_core = real_core[:,:,:c_prim,:f_prim]
real_in_fac = real_in_fac[:, :c_prim]
real_out_fac = real_out_fac[:, :f_prim]
# low rank approximation
base_tensor_low_rank = multi_mode_dot(real_core, [real_in_fac, real_out_fac], modes=(2,3))
in_rank, out_rank = c_prim, f_prim
core_tilde, (in_fac_tilde, out_fac_tilde) = partial_tucker(base_tensor_low_rank, modes=(2, 3), ranks=(in_rank, out_rank), init='svd')
base_tensor_tilde = multi_mode_dot(core_tilde, [in_fac_tilde, out_fac_tilde], modes=(2,3))
assert np.allclose(base_tensor_tilde, base_tensor_low_rank) # this is OK
assert np.allclose(in_fac_tilde, real_in_fac) # this fails
Обратите внимание, что я попытался вычислить in_fac_tilde.T @ real_in_fac
, чтобы увидеть, было ли это тождество или что-то в этом роде, и я заметил, что только первый столбец был коллинеарным в обеих матрицах, и ортогональны всем остальным.