在Python

时间:2015-10-29 19:06:41

标签: python pca decomposition

我的形状(n_samples, n_steps, n_features)中有一个 tensor 。我想将其分解为形状(n_samples, n_components)的张量。

我需要一种具有.fit(...)的分解方法,以便我可以将相同的分解应用于新批次的样本。我一直在关注Tucker DecompositionPARAFAC Decomposition,但它们都没有那个至关重要的.fit(...).transform(...)功能。 (或者至少我认为他们没有?)

我可以使用PCA并在代表性样本上训练它,然后在剩余的样本上调用.transform(...),但我宁愿进行某种张量分解,它可以同时处理所有样本,从而更好地了解每个样本之间的差异。

这就是我所说的“张量”:

  

事实上,张量只是标量和向量的推广;标量是零秩张量,矢量是第一级张量。张量的等级(或顺序)由描述它所需的方向数(以及因此数组的维数)定义。

如果您有任何疑问,请询问,如果需要,我会尽力澄清我的问题。

编辑:最好的解决方案是某种类型的内核,但我还没有找到可以处理n级张量而不仅仅是2D数据的内核

1 个答案:

答案 0 :(得分:0)

您可以使用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)

这里的换位相当于逆,因为因子是正交的。

最后,关于术语的说明:一般来说,即使有时完成,最好不要使用交替的顺序和张量等级。张量的阶数就是它的维数,而张量的阶数通常是一个更复杂的概念,你可以把它看作是矩阵秩概念的推广。