Вы можете сделать это с помощью развития (мастер) версия TensorLy. В частности, вы можете использовать новую функцию partial_tucker
(она еще не обновлена в документации ...).
Отметим, что следующее решение сохраняет структуру тензора, то есть тензор формы (n_samples, n_steps, n_features)
разлагается на (меньший) тензор формы (n_samples, n_components_1, n_components_2)
.
Код
Короткий ответ: это очень простой класс, который делает то, что вы хотите (и это будет работать на тензоры произвольного порядка).
import tensorly as tl
from tensorly.decomposition._tucker import partial_tucker
class TensorPCA:
def __init__(self, ranks, modes):
self.ranks = ranks
self.modes = modes
def fit(self, tensor):
self.core, self.factors = partial_tucker(tensor, modes=self.modes, ranks=self.ranks)
return self
def transform(self, tensor):
return tl.tenalg.multi_mode_dot(tensor, self.factors, modes=self.modes, transpose=True)
Использование
Учитывая тензор входа, вы можете использовать предыдущий класс, первое инстанцирование его с желаемыми рядами (размера тензора ядра) и режимов, на которых можно выполнить разложение (в 3D случай, 1 и 2, так как индексация начинается с нуля):
tpca = TensorPCA(ranks=[4, 5], modes=[1, 2])
tpca.fit(tensor)
Учитывая новый тензор, первоначально названный new_tensor
, вы можете проецировать его с помощью transform
метода:
tpca.transform(new_tensor)
Объяснение
Давайте пройдемся по коду на примере: сначала давайте импортировать необходимые биты:
import numpy as np
import tensorly as tl
from tensorly.decomposition._tucker import partial_tucker
Мы сгенерируйте случайный тензор:
tensor = np.random.random((10, 11, 12))
Следующий шаг состоит в том, чтобы разложить его по его второму и третьему размерам или режимам (поскольку первый размер соответствует образцам):
core, factors = partial_tucker(tensor, modes=[1, 2], ranks=[4, 5])
Ядро соответствует преобразованному входному тензору, в то время как factors
представляет собой список из двух матриц проектирования, один для второго режима и один для третьего режима. Учитывая новый тензор, вы можете проецировать его на то же подпространство (метод transform
) путем проецирования каждого из своих последних двух измерений:
tl.tenalg.multi_mode_dot(tensor, factors, modes=[1, 2], transpose=True)
Перестановки здесь эквивалентна обратный, так как факторы ортогональны.
Наконец, примечание к терминологии: в целом, хотя иногда это делается, вероятно, лучше не использовать взаимозаменяемый порядок и ранг тензора. Порядок тензора - это просто его размерность, а ранг тензора обычно представляет собой гораздо более сложное понятие, которое можно было бы рассматривать как обобщение понятия матричного ранга.