您可以使用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)
这里的转置等价于逆,因为因子是正交的。
最后,关于术语的注释:一般来说,即使有时这样做,最好不要互换使用张量的顺序和等级。张量的阶数只是它的维数,而张量的秩通常是一个更复杂的概念,您可以将其视为矩阵秩概念的推广。