查看原文
其他

通俗理解张量并设计推荐系统算法(Python)

王海华 模型视角 2023-09-03

在大数据时代,我们每天都与成吨的数据打交道——从社交媒体帖子、电影推荐,到复杂的医学图像。但是,如何从这些海量的数据中捕捉深层次的结构和模式,进而为用户提供更精确的推荐或更深入的分析呢?答案可能隐藏在一种神奇的数学工具中,即张量分解。今天,我将带你走进张量分解的世界,探索其魅力所在,并揭示它如何改变我们看待数据的方式。

张量概念

张量 (Tensor) 是数学和物理学中的一个概念,广泛应用于线性代数、微分几何、物理学、 以及近年来非常受欢迎的深度学习领域。简单地说,张量是一个可以表示在多个维度上的数据的数学对象。可以将其视为标量、向 量、矩阵的高维推广

  1. 标量 (Scalar): 0 维张量。例如:
  2. 向量 (Vector): 1 维张量。例如:1,2,3。
  3. 矩阵 (Matrix): 2维张量。例如:
  1. 三维张量: 可以想象为一个数据立方体,其在 3 个方向上都有数据。
  2. 更高维张量: 虽然难以直观想象,但在数学和计算中很常见。

在深度学习中,张量经常被用作存储和处理数据,例如图像、语音和文本数据。现代深度学 习框架,如TensorFlow和PyTorch,都是围绕张量操作设计的,它们提供了一系列工具来创 建、操作和计算张量。 例如,彩色图像可以表示为一个3维张量。其中的三个维度分别是高度、宽度和颜色通道 (红、绿、蓝) 。所以,一个256x256 的彩色图像就是一个形状为 的张量。 视频可以看作是一系列的图像帧,因此它可以表示为形状为 张量,其中 是帧数。

你可以想象张量是一个多层的容器或盒子。这个盒子可以有很多层,每层都能存放数据。

对于张量,我们可以有以下基本操作:

加法: 两个形状相同的张量可以按元素进行加法。 如果 都是 的矩阵,则它们的和 是一个 的矩阵,其中

数乘: 张量每个元表都与一个标量相乘。 如果 是一个标量, 是一个 的矩阵,则 也是一个 的矩阵, 其中

张量乘法:对于矩阵(2维张量),我们有矩阵乘法。但是,对于更高维的张量,定义可能 会变得更为复杂。

张量在多个领域都有广泛的应用:

物理学: 在广义相对论中,度规、克里斯托弗符号和黎曼曲率张量都是关键概念。

计算机视觉: 图像可以被视为2D张量 (灰度图像) 或3D张量 (彩色图像)。视频则可以被 视为 张量,其中时间是第四个维度。

自然语言处理: 文本数据经常被编码为高维张量, 尤其是在深度学习模型中。

深度学习: 张量是深度学习的核心。神经网络的输入、输出、权重和偏置通常都是张量。框架如TensorFlow和PyTorch提供了处理张量的工具。

医学成像:MRI、CT等扫描图像可以被视为高维张量,其中每个维度都代表不同的扫描属性或时间点。

张量分解

在数据分析和降维中,张量分解是一个关键工具。例如,矩阵分解 (如奇异值分解) 可以视 为张量分解的一个特例。矩阵分解,也被称为矩阵因子分解,是一种将矩阵分解为多个矩阵乘积的技术。它在多种应 用中都非常有用,包括信号处理、数据压缩、以及我们之前讨论过的推荐系统。下面是矩阵分解的几种常见方法:

  1. 奇异值分解 (SVD): 奇异值分解是最广泛使用的矩阵分解方法之一。给定一个矩阵 , SVD 可以将其表示为三个 矩阵的乘积: 其中 都是正交矩阵,而 是一个对角矩阵,其对角线上的元素称为奇异值。
  2. 主成分分析 (PCA): PCA 通常用于降维和数据可视化。它通过找到数据的主要变化方向来工作。PCA 可以使用 SVD 来实现。
  3. QR 分解: 将矩阵 分解为一个正交矩阵 和一个上三角矩阵 的乘积。形式上,
  4. LU 分解: 将矩阵 分解为一个下三角矩阵 和一个上三角矩阵 的乘积。形式上,
  5. Cholesky 分解: 用于对称正定矩阵,将矩阵 分解为一个下三角矩阵 和其转置 的乘积。形式上,
  6. 非负矩阵分解 (NMF): 将非负矩阵分解为两个非负矩阵的乘积。它在图像分析和文本按掘中特别有用。

更一般地,对于一个三维张量 ,其CP分解 (CANDECOMP/PARAFAC分解) 可以表示为多个矩阵和向量的乘积。CP分解 (CANDECOMP/PARAFAC分解) 是一种对高维张量进行因子分解的方法。对于一个三维张量,CP分解试图将其分解为一系列向量的外积。 具体地说,对于一个三维张量 ,其CP分解可以表示为:

其中:

  • 是一个 -维向量,与第一模式 (通常是用户) 相关。
  • 是一个 -维向量,与第二模式 (例如物品或特性) 相关。
  • 是一个 -维向量,与第三模式 (例如时间或上下文) 相关。
  • ○表示外积。
  • 是分解的秩,即我们希望从分解中得到的成分数。 外积的结果是一个三维张量,因此整个公式表示的是多个这样的张量的和。 为了得到这三个因子矩阵 ,我们可以使用各种优化 技术,如交替最小二乘法(ALS)、梯度下降或张量功率法。 这些因子矩阵的列分别是向量

张量分解可以用于

  1. 模式发现:通过对上述张量进行分解,我们可以发现隐藏在数据中的模式。例如,某些用户 可能更喜欢在周末观看动作片,而在工作日观看纪录片。
  2. 缺失值的预测:对于那些用户尚末评分的电影,我们可以使用张量分解来预测他们可能给予 的评分。这可以帮助我们为用户推荐他们可能喜欢的电影。
  3. 降维: 原始的张量可能非常大并且稀疏。通过张量分解,我们可以获得一个更简洁的数据表 示,从而加速其他数据处理和机器学习任务。

简单应用:歌曲推荐

张量分解是将一个高维张量分解为多个低维张量的过程,这些低维张量的组合或乘积可以近 似地重构原始张量。它与矩阵分解类似,但是适用于更高维度的数据。 常见的张量分解技术包括: CP分解 (CANDECOMPIPARAFAC分解):将一个3维张量分解为三个矩阵的外积。 Tucker分解:将张量分解为一个核心张量和多个矩阵的乘积。 数学上,给定一个3维张量 分解可以表示为:

其中, 是分解得到的向量, 是分解的秩,而 表示外积。

假设我们有一个音乐推荐系统,它记录了用户在不同时间段对各种歌曲的评分。我们可以将 这些数据表示为一个3维张量,其中三个维度分别是用户 (U)、歌曲 (S) 和时间段 (T)。 例如,考虑以下小型数据集:

  • 用户: Alice, Bob
  • 歌曲: Song1, Song2
  • 时间段: Morning, Evening 我们可以有如下评分数据: 这个表格表示了一个形状为 的 3 维张量。 CP分解: 为了简化,我们假设我们想要将这个张量分解成一个秩为 1 的近似。CP分解表示为:

其中, 是与用户相关的向量, 是与歌曲相关的向量, 是与时间段相关的向量。 对于我们的例子,假设分解结果为:

则近似的张量可以通过这些向量的外积来构造。 通过张量分解,我们现在有了更简洁的表示形式来描述用户、歌曲和时间的交互。这些分解得到的向量可以用于预测缺失的评分,或者作为输入特征用于其他机器学习任务。

直观地,想象你有一个巨大的乐高玩具块堆。每个乐高块的位置代表一个数据点(在我们的例子中, 是用户对歌曲在某个时间段的评分),而乐高块的高度代表这个评分的值。 现在,你的任务是使用尽可能少的材料重建这个乐高堆,但仍然要屈量保持原始形状。一个 方法是使用大块的乐高片(或板)来近似乐高堆的某些部分

这就是张量分解所做的:它尝试使用较少的“乐高板”来近似原始的“乐高堆”。在数学上,这些 “乐高板"是由向量 形成的外积。 回到我们的例子:

  • : 代表每个用户对整体音乐的兴趣。比如,Alice可能更喜欢流行音乐,而Bob可能更喜欢 摇詮音乐。
  • : 代表每首歌曲的流派或风格。比如,Song1可能是流行音乐,而Song2可能是搖滚音 东。
  • :代表时间段对评分的影响。例如,早晨可能更适合轻松的音乐,而晩上可能更适合节秦 感强的音乐。

通过这三个向量的组合,我们可以为每个用户在每个时间段对每首歌的评分做出一个近似的 预测。张量分解就像是一种艺术,试图用尽量少的笔触来描留一个复杂的画面,而不失去太多的细节。

使用Python进行张量分解的一个流行的方法是使用 tensorly 库,它提供了各种张量运算和张量分解方法。下面,我将演示如何使用 tensorly 对一个简单的3D张量进行CP分解。

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

# 设置随机数种子以确保可重复性
np.random.seed(42)

# 创建一个简单的3D张量
tensor = np.array([
    [[12], [34]],
    [[56], [78]],
    [[910], [1112]]
])

# 使用CP分解进行张量分解
# 设置秩为2
factors = parafac(tensor, rank=2)

# 打印分解得到的因子
for factor in factors:
    print(factor)

在上面的代码中,我们首先导入了必要的库,并创建了一个简单的3D张量。然后,我们使用 parafac 方法对张量进行CP分解,并打印分解得到的因子。

factors 是一个列表,其中包含每个维度的因子矩阵。你可以将这些因子矩阵乘在一起(使用外积)来重构原始张量。

使用 tensorly 进行张量分解是非常直接的,它提供了许多其他张量运算和分解方法,使得在Python中处理张量变得非常简单。

进阶:电影推荐

考虑一个电影推荐系统,该系统需要处理以下信息:

  1. 用户信息:这可能包括用户的基本资料、过去的观影历史、评分等。
  2. 电影信息:这包括电影的类型、导演、演员、上映年份等属性。
  3. 时间和上下文: 用户可能在周末或工作日、白天或晩上、单独或与月月友一起观看电影,这些都可能影响他们的评分。

给定这些信息,我们可以创建一个三维张量,其中:

  • 第一个维度代表用户。
  • 第二个维度代表电影。
  • 第三个维度代表上下文 (例如,周末的夜晩)。

每个张量的元素代表一个用户在特定上下文中对某部电影的评分。

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

# 假设我们有100名用户,50部电影,和5种上下文
tensor_shape = (100505)

# 为简单起见,我们可以生成一个随机张量来模拟数据
tensor = np.random.rand(*tensor_shape)

# 使用CP分解进行张量分解
factors = parafac(tensor, rank=5)

# 打印分解得到的因子
for factor in factors:
    print(factor)

在上述示例中,我们对一个模拟的三维张量进行了CP分解。这个张量代表了用户在不同上下文中对电影的评分。分解的结果是三个因子矩阵,每个矩阵对应于原始张量的一个维度。

这三个因子矩阵的解释如下:

第一个因子矩阵:这个矩阵的每一行对应于一个用户的潜在特征或"兴趣向量"。例如,某个行向量可能表示用户对不同电影类型的偏好程度,或者他们在不同上下文下的观影行为。

第二个因子矩阵:这个矩阵的每一行对应于一部电影的潜在特征或"属性向量"。这可能涉及到电影的类型、导演、演员等特点,以及它如何与不同的用户和上下文互动。

第三个因子矩阵:这个矩阵的每一行代表一个上下文的潜在特征或"情境向量"。它可以捕获不同上下文(如工作日的夜晚或周末的早晨)对观影行为的影响。

通过张量分解,我们可以将一个大型、复杂的三维张量近似为这三个因子矩阵的组合。这不仅可以简化数据表示,还可以揭示潜在的模式和关系。

如何使用这些因子?可以预测缺失值:如果你想预测一个用户在特定上下文中对某部电影的评分,你可以通过组合相应的行向量来做到这一点。或者对用户或电影的聚类:你可以使用因子矩阵中的向量作为输入,对用户或电影进行聚类,从而找出具有相似兴趣或属性的用户或电影。也可以用于推荐:给定一个用户,你可以查找他的兴趣向量与每部电影的属性向量之间最匹配的电影,然后将这些电影推荐给他。

假设我们想要预测第 个用户在第 个上下文中对第 部电影的评分。为了进行这个预测, 我们可以使用以下步骤:

  1. 从第一个因子矩阵中取出第 行,称为用户向量
  2. 从第二个因子矩阵中取出第 行,称为电影向量
  3. 从第三个因子矩阵中取出第 行,称为上下文向量
  4. 计算这三个向量的点积以获得预测值。
# 使用CP分解
rank = 5
factors = parafac(tensor, rank=rank)

# 定义预测函数
def predict_rating(user_index, movie_index, context_index, factors):
    user_vector = factors.factors[0][user_index, :]
    movie_vector = factors.factors[1][movie_index, :]
    context_vector = factors.factors[2][context_index, :]
    
    predicted_rating = np.dot(user_vector, np.dot(movie_vector, context_vector))
    return predicted_rating

# 为第0个用户在第0个上下文中对第0部电影的评分进行预测
predicted_value = predict_rating(000, factors)
print(predicted_value)
# [ 0.30587962  0.0138001   0.01130173 -0.01562052  0.00445964]

这个预测值表示我们模型估计的第1个用户在第1个上下文中对第1部电影的评分。我们可以使用这种方法为任意用户、电影和上下文组合预测评分。

结语

张量分解是一种高级数学工具,用于捕捉大数据中的深层结构和模式。在这篇文章中,我们深入探讨了张量分解的核心概念,特别是CP分解,以及它如何在推荐系统、数据压缩和填充缺失数据中发挥作用。通过这种方法,我们可以更有效地理解和利用数据,为用户提供更精确的推荐和分析。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存