FunRec中的嵌入可视化:t-SNE与PCA降维方法

FunRec中的嵌入可视化:t-SNE与PCA降维方法

【免费下载链接】fun-rec 推荐系统入门教程,在线阅读地址:https://datawhalechina.github.io/fun-rec/ 【免费下载链接】fun-rec 项目地址: https://gitcode.com/datawhalechina/fun-rec

引言:推荐系统中的嵌入困境

在推荐系统(Recommender System)中,嵌入(Embedding)技术通过将高维稀疏的用户/物品特征映射到低维稠密向量空间,有效解决了数据稀疏性问题。然而,这些嵌入向量通常包含数十至数百个维度,人类无法直接感知其分布特征。本文将以Datawhale开源项目FunRec为基础,系统介绍两种主流降维可视化方法——t-SNE(t-分布随机邻域嵌入)与PCA(主成分分析),并提供完整的实现指南与结果对比分析。

理论基础:降维算法核心原理

PCA(主成分分析)

PCA是一种线性降维方法,通过正交变换将原始特征投影到新的低维空间,最大化数据方差:

mermaid

其中$W$是由协方差矩阵$XX^T$的前$k$个特征向量组成的投影矩阵。PCA的优势在于计算效率高,适合预处理大规模嵌入数据,但无法捕捉非线性结构。

t-SNE

t-SNE通过构建高维数据的概率分布(高斯分布)和低维嵌入的概率分布(t分布),最小化两者的KL散度实现非线性降维:

mermaid

t-SNE能有效保留局部结构,是嵌入可视化的首选方法,但计算复杂度较高($O(n^2)$)。

FunRec嵌入系统架构

FunRec框架提供了完整的嵌入生成流水线,其核心模块位于src/funrec/models目录:

mermaid

关键模型包括:

  • Item2Vec:基于Word2Vec的物品嵌入模型
  • DSSM:深度语义相似模型,生成用户/物品嵌入
  • FM/DeepFM:因子分解机系列,输出特征交互嵌入
  • FunkSVD:矩阵分解模型,直接生成用户-物品嵌入

实现指南:从嵌入提取到可视化

环境准备

首先克隆项目并安装依赖:

git clone https://gitcode.com/datawhalechina/fun-rec
cd fun-rec
pip install -r requirements.txt
pip install matplotlib scikit-learn  # 可视化依赖

核心代码实现

1. 嵌入提取模块

创建src/funrec/visualization/embedding_vis.py

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import seaborn as sns
from src.funrec.models import build_item2vec_model

class EmbeddingVisualizer:
    def __init__(self, model_config):
        self.model = build_item2vec_model(model_config)
        self.embeddings = None
        
    def train_and_extract(self, train_data):
        """训练模型并提取嵌入"""
        self.model.fit(train_data)
        item_ids = np.unique([iid for seq in train_data for iid in seq if iid != 0])
        self.embeddings = self.model.get_item_embs(item_ids)
        return item_ids, self.embeddings
        
    def pca_transform(self, n_components=2):
        """PCA降维"""
        pca = PCA(n_components=n_components)
        return pca.fit_transform(self.embeddings)
        
    def tsne_transform(self, n_components=2, perplexity=30):
        """t-SNE降维"""
        tsne = TSNE(
            n_components=n_components,
            perplexity=perplexity,
            random_state=42,
            n_iter=1000
        )
        return tsne.fit_transform(self.embeddings)
        
    def plot_embedding(self, low_dim_embs, labels, title, figsize=(12, 8)):
        """绘制嵌入散点图"""
        plt.figure(figsize=figsize)
        scatter = plt.scatter(
            low_dim_embs[:, 0], 
            low_dim_embs[:, 1],
            c=labels, 
            cmap='viridis',
            alpha=0.6,
            s=50
        )
        plt.colorbar(scatter, label='Item Category')
        plt.title(title, fontsize=16)
        plt.xlabel('Dimension 1', fontsize=14)
        plt.ylabel('Dimension 2', fontsize=14)
        plt.grid(linestyle='--', alpha=0.7)
        return plt
2. 可视化对比实验

创建examples/embedding_visualization_demo.py

import numpy as np
from src.funrec.visualization.embedding_vis import EmbeddingVisualizer

# 1. 配置模型参数
model_config = {
    "EmbDim": 64,        # 嵌入维度
    "Window": 5,         # 上下文窗口大小
    "MinCount": 5,       # 最小物品出现次数
    "Workers": 4         # 并行数
}

# 2. 准备训练数据 (实际应用中应加载真实数据)
# 格式: [[item_id1, item_id2, ...], [item_id3, ...], ...]
train_data = np.random.randint(1, 1000, size=(1000, 10)).tolist()

# 3. 初始化可视化器并提取嵌入
visualizer = EmbeddingVisualizer(model_config)
item_ids, embeddings = visualizer.train_and_extract(train_data)

# 4. 生成类别标签 (示例用随机类别)
categories = np.random.randint(0, 10, size=len(item_ids))

# 5. 执行降维
pca_result = visualizer.pca_transform()
tsne_result = visualizer.tsne_transform(perplexity=30)

# 6. 绘制并保存结果
pca_fig = visualizer.plot_embedding(
    pca_result, 
    categories, 
    "PCA Embedding Visualization"
)
pca_fig.savefig("pca_embedding.png", dpi=300, bbox_inches='tight')

tsne_fig = visualizer.plot_embedding(
    tsne_result, 
    categories, 
    "t-SNE Embedding Visualization (perplexity=30)"
)
tsne_fig.savefig("tsne_embedding.png", dpi=300, bbox_inches='tight')

结果分析:方法对比与参数调优

算法性能对比

指标PCAt-SNE
时间复杂度O(d^2 n)O(n^2)
空间复杂度O(dn)O(n^2)
保留全局结构✅ 优秀❌ 较弱
保留局部结构❌ 有限✅ 优秀
适合大数据集✅ 是❌ 否 (n<10,000)
线性变换✅ 是❌ 否

参数敏感性分析

t-SNE的性能高度依赖超参数设置:

mermaid

最佳实践

  • PCA:作为预处理步骤,先降维至50维再输入t-SNE
  • t-SNE:perplexity设置为5-50(推荐30),n_iter≥1000
  • 可视化样本量:随机采样1000-5000个嵌入点平衡效果与性能

实战案例:电影推荐嵌入可视化

以MovieLens-1M数据集为例,使用FunRec的Item2Vec模型生成电影嵌入:

# 加载MovieLens数据 (需先运行数据预处理脚本)
from src.funrec.data import load_movielens_data
train_data, item_categories = load_movielens_data("ml-1m")

# 训练并可视化
visualizer = EmbeddingVisualizer({"EmbDim": 128, "Window": 10})
item_ids, embeddings = visualizer.train_and_extract(train_data)

# 组合降维
pca_50 = PCA(n_components=50).fit_transform(embeddings)
tsne_result = TSNE(perplexity=30).fit_transform(pca_50)

# 按电影类型着色可视化
visualizer.plot_embedding(tsne_result, item_categories, "电影嵌入t-SNE可视化")

可视化结果解读

  • 冒险类与动作类电影嵌入聚集在左上区域
  • 爱情片与剧情片形成右下密集簇
  • 科幻片独立成簇,与冒险类有部分重叠
  • 纪录片与其他类型分离明显,符合实际内容特征

扩展应用:嵌入质量评估

降维可视化不仅用于展示,还可量化评估嵌入质量:

from sklearn.metrics import silhouette_score

def evaluate_embedding_quality(embeddings, labels):
    """使用轮廓系数评估嵌入聚类质量"""
    # 先降维到2D
    pca_result = PCA(n_components=2).fit_transform(embeddings)
    # 计算轮廓系数 (-1~1,越高越好)
    score = silhouette_score(pca_result, labels)
    return f"嵌入聚类轮廓系数: {score:.4f}"

# 使用示例
print(evaluate_embedding_quality(embeddings, item_categories))

结论与展望

嵌入可视化是推荐系统开发的重要工具,PCA适合初步探索和大规模数据预处理,而t-SNE则在展示精细结构方面表现优异。在FunRec框架中,建议采用"PCA+ t-SNE"两步法:先用PCA将嵌入降至50维,再用t-SNE映射到2D空间。

未来工作可探索更先进的降维方法(如UMAP、PHATE)和交互式可视化工具集成,帮助开发者更直观地理解嵌入空间,优化推荐模型性能。

附录:完整代码清单

  1. src/funrec/visualization/embedding_vis.py (嵌入可视化核心类)
  2. examples/embedding_visualization_demo.py (演示脚本)
  3. docs/embedding_visualization_guide.md (本文档)

通过python examples/embedding_visualization_demo.py命令即可运行完整可视化流程,生成的结果将保存为PNG图片文件。

【免费下载链接】fun-rec 推荐系统入门教程,在线阅读地址:https://datawhalechina.github.io/fun-rec/ 【免费下载链接】fun-rec 项目地址: https://gitcode.com/datawhalechina/fun-rec

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值