张量分解


张量的 CP 分解(CANDECOMP/PARAFAC 分解)是将一个高阶张量表示为若干个秩一张量(rank-one tensor)的和,是张量分解中最常用的一种方法,类似于矩阵的 SVD 分解。下面是详细的步骤和基本概念。


💡 CP 分解简介

对一个 $N$ 阶张量 $\mathcal{X} \in \mathbb{R}^{I_1 \times I_2 \times \dots \times I_N}$,CP 分解的目标是找到 $R$ 个秩一张量,使得:

$
\mathcal{X} \approx \sum_{r=1}^R \lambda_r \cdot a^{(1)}_r \circ a^{(2)}_r \circ \cdots \circ a^{(N)}_r
$

其中:

  • $a^{(n)}_r \in \mathbb{R}^{I_n}$ 是第 $n$ 模的因子向量(component)。
  • “$\circ$” 表示外积。
  • $\lambda_r$ 是第 $r$ 个秩一张量的权重(有时省略)。

最终得到的因子矩阵为:

  • $A^{(1)} \in \mathbb{R}^{I_1 \times R}$
  • $A^{(2)} \in \mathbb{R}^{I_2 \times R}$
  • $A^{(N)} \in \mathbb{R}^{I_N \times R}$

🚀 CP 分解的实现方法

1. 基于 ALS(交替最小二乘法)

最常用的算法是 Alternating Least Squares (ALS),基本思想是固定其它模,只优化一个模,交替更新。

步骤如下:

  1. 初始化每个模的因子矩阵(通常是随机或基于 SVD)。
  2. 选择一个模 $n$,固定其它模,最小化误差:
    $
    \min_{A^{(n)}} \left| \mathcal{X}_{(n)} - A^{(n)} \left( A^{(N)} \odot \cdots \odot A^{(n+1)} \odot A^{(n-1)} \odot \cdots \odot A^{(1)} \right)^T \right|_F^2
    $
    • 这里 $\mathcal{X}_{(n)}$ 是张量沿第 $n$ 维的展开(矩阵化)
    • $\odot$ 是 Khatri-Rao 积(列式 Kronecker 积)
  3. 重复对每个模更新,直到收敛(如误差变化小于阈值)。

🧪 Python 示例(使用 tensorly 库)

import tensorly as tl
from tensorly.decomposition import parafac
import numpy as np

# 创建一个随机三阶张量
tensor = tl.tensor(np.random.random((30, 40, 50)))

# 设定分解秩 R
rank = 5

# 进行 CP 分解
factors = parafac(tensor, rank=rank)

# 输出分解得到的因子矩阵
for i, factor in enumerate(factors.factors):
    print(f"Factor matrix {i+1}: shape = {factor.shape}")

📌 注意事项

  • 选择合适的秩 $R$ 很关键,太小表示能力不足,太大容易过拟合。
  • 可以使用 explained variance残差分析 来选取秩。
  • CP 分解不唯一:可能存在多个局部最优解。
  • 对稀疏张量可使用稀疏优化版本。

如果你有具体数据、模型或者想应用在某种实际问题(如推荐系统、信号处理等),我可以帮你更具体地实现。需要的话也可以帮你用中文详细讲解各个步骤。你有想要应用 CP 分解的具体场景吗?


文章作者: 赵阳
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 赵阳 !
  目录