news 2026/6/11 21:50:23

从社交网络到推荐系统:手把手用PyTorch+GCN构建你的第一个图神经网络模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从社交网络到推荐系统:手把手用PyTorch+GCN构建你的第一个图神经网络模型

从社交网络到推荐系统:手把手用PyTorch+GCN构建你的第一个图神经网络模型

当你在电商平台浏览商品时,那些"猜你喜欢"的推荐从何而来?当社交网络为你推荐可能认识的人,背后又是什么算法在运作?这些场景的核心技术之一就是图卷积网络(GCN)。与传统的卷积神经网络不同,GCN专门用于处理图结构数据——这种数据在我们的数字生活中无处不在,从社交关系到商品购买,从知识图谱到交通网络。

本文将带你从零开始,构建一个基于PyTorch和切比雪夫多项式的GCN推荐系统。不同于大多数教程只关注理论推导,我们将聚焦于实际应用,教你如何将抽象的图卷积概念转化为可运行的代码,最终打造一个能处理用户-商品交互数据的推荐模型。无论你是想提升现有推荐系统的效果,还是希望掌握图神经网络这一前沿技术,本文都能提供实用的指导。

1. 图神经网络基础与推荐系统场景

图神经网络之所以在推荐系统中表现出色,是因为它能够自然地建模用户和商品之间的复杂交互。想象一下,在电商平台上:

  • 每个用户和商品都是图中的一个节点
  • 用户购买商品、浏览商品、将商品加入购物车等行为构成了图中的边
  • 用户之间的社交关系也可以作为边加入图中

传统推荐系统通常将用户和商品视为独立的个体,而GCN则能够捕捉它们之间的高阶连接关系。例如,通过分析"用户A→商品1←用户B→商品2"这样的路径,模型可以推断出用户A可能也对商品2感兴趣。

为什么选择切比雪夫多项式?

切比雪夫多项式在图卷积中的应用有三大优势:

  1. 计算高效:避免了直接计算拉普拉斯矩阵的特征分解
  2. 局部性:K阶多项式只考虑K跳邻居,适合大规模图数据
  3. 灵活性:可以通过调整K值控制感受野大小

下面是一个简单的用户-商品交互矩阵示例:

用户\商品商品1商品2商品3
用户A101
用户B110
用户C011

这个矩阵可以转化为图的邻接矩阵,其中用户和商品都是节点,交互行为是边。

2. 环境搭建与数据准备

2.1 PyTorch环境配置

推荐使用Python 3.8+和PyTorch 1.10+环境。可以通过以下命令安装所需库:

pip install torch torch-geometric numpy pandas scikit-learn

注意:torch-geometric是PyTorch的图神经网络扩展库,安装时需选择与PyTorch和CUDA版本兼容的版本。

2.2 构建推荐系统图数据集

我们将使用一个模拟的用户-商品交互数据集来演示。实际应用中,你可以替换为自己的业务数据。

import numpy as np import torch from torch_geometric.data import Data # 模拟数据:3个用户,4个商品 num_users = 3 num_items = 4 # 用户-商品交互边(用户0购买商品0和1,用户1购买商品1和2,等等) edge_index = torch.tensor([ [0, 0, 1, 1, 2, 2, 2], # 用户节点 [3, 4, 4, 5, 3, 5, 6] # 商品节点(编号从num_users开始) ], dtype=torch.long) # 节点特征:用户年龄和性别(0/1),商品类别和价格 x = torch.tensor([ [25, 0], # 用户0 [30, 1], # 用户1 [22, 1], # 用户2 [1, 29], # 商品3 [2, 39], # 商品4 [1, 19], # 商品5 [3, 49] # 商品6 ], dtype=torch.float) # 创建PyTorch Geometric的Data对象 data = Data(x=x, edge_index=edge_index) print(data)

这个数据集包含:

  • 7个节点(3用户+4商品)
  • 7条边(交互记录)
  • 每个节点有2个特征

3. 切比雪夫GCN模型实现

3.1 切比雪夫多项式基础

切比雪夫多项式是一组正交多项式,在图卷积中用于近似图傅里叶变换。其递归定义为:

T₀(x) = 1 T₁(x) = x Tₖ(x) = 2xTₖ₋₁(x) - Tₖ₋₂(x) (k ≥ 2)

在GCN中,我们用切比雪夫多项式来近似图拉普拉斯矩阵的函数:

gθ = ∑ θₖTₖ(L̃)

其中L̃是缩放后的拉普拉斯矩阵。

3.2 实现切比雪夫卷积层

import torch.nn as nn import torch.nn.functional as F class ChebConv(nn.Module): def __init__(self, in_channels, out_channels, K): super(ChebConv, self).__init__() self.K = K self.weights = nn.Parameter(torch.Tensor(K+1, in_channels, out_channels)) self.reset_parameters() def reset_parameters(self): nn.init.xavier_uniform_(self.weights) def forward(self, x, L): """ x: 节点特征矩阵 [num_nodes, in_channels] L: 缩放后的拉普拉斯矩阵 [num_nodes, num_nodes] 返回: 卷积后的特征 [num_nodes, out_channels] """ # 计算切比雪夫多项式 Tx = [x] # T₀(L̃)x = x if self.K > 0: Tx.append(torch.sparse.mm(L, x)) # T₁(L̃)x = L̃x for k in range(2, self.K+1): Tx.append(2 * torch.sparse.mm(L, Tx[-1]) - Tx[-2]) # Tₖ(L̃)x = 2L̃Tₖ₋₁(L̃)x - Tₖ₋₂(L̃)x # 加权求和 out = torch.zeros_like(Tx[0]) for k in range(self.K+1): out += torch.mm(Tx[k], self.weights[k]) return out

3.3 构建完整推荐模型

现在我们将切比雪夫卷积层整合到一个完整的推荐模型中:

class GCNRecommender(nn.Module): def __init__(self, num_users, num_items, user_feats, item_feats, hidden_size, K): super(GCNRecommender, self).__init__() self.user_embedding = nn.Embedding(num_users, user_feats) self.item_embedding = nn.Embedding(num_items, item_feats) self.conv1 = ChebConv(user_feats + item_feats, hidden_size, K) self.conv2 = ChebConv(hidden_size, hidden_size, K) self.predict = nn.Linear(hidden_size, 1) def forward(self, user_idx, item_idx, L): # 获取用户和商品的嵌入 user_emb = self.user_embedding(user_idx) item_emb = self.item_embedding(item_idx) # 拼接所有节点特征 x = torch.cat([user_emb, item_emb], dim=0) # 图卷积 x = F.relu(self.conv1(x, L)) x = F.relu(self.conv2(x, L)) # 预测评分 user_out = x[user_idx] item_out = x[num_users + item_idx] return torch.sigmoid(self.predict(user_out * item_out))

4. 模型训练与评估

4.1 数据预处理与拉普拉斯矩阵计算

def prepare_data(data, num_users, num_items): # 构建邻接矩阵 num_nodes = num_users + num_items adj = torch.zeros((num_nodes, num_nodes)) adj[data.edge_index[0], data.edge_index[1]] = 1 adj = adj + adj.t() # 使矩阵对称 adj = adj.clamp(max=1) # 确保没有大于1的值 # 计算度矩阵 degree = torch.diag(adj.sum(dim=1)) # 计算归一化拉普拉斯矩阵 degree_inv_sqrt = torch.diag(1.0 / torch.sqrt(adj.sum(dim=1))) L = torch.eye(num_nodes) - degree_inv_sqrt @ adj @ degree_inv_sqrt # 缩放拉普拉斯矩阵到[-1,1]区间 lambda_max = 2.0 # 正则图的最大特征值理论为2 L_scaled = (2 * L) / lambda_max - torch.eye(num_nodes) return adj, L_scaled # 准备数据 adj, L_scaled = prepare_data(data, num_users=3, num_items=4)

4.2 训练循环与评估

from sklearn.model_selection import train_test_split # 创建训练和测试集 all_pairs = [(u, i) for u in range(3) for i in range(4)] labels = [adj[u, 3+i].item() for u, i in all_pairs] # 使用邻接矩阵中的交互作为标签 train_pairs, test_pairs, y_train, y_test = train_test_split(all_pairs, labels, test_size=0.2) # 初始化模型 model = GCNRecommender(num_users=3, num_items=4, user_feats=2, item_feats=2, hidden_size=16, K=2) optimizer = torch.optim.Adam(model.parameters(), lr=0.01) criterion = nn.BCELoss() # 训练 for epoch in range(100): model.train() optimizer.zero_grad() # 准备batch数据 users = torch.tensor([u for u, i in train_pairs]) items = torch.tensor([i for u, i in train_pairs]) preds = model(users, items, L_scaled).squeeze() loss = criterion(preds, torch.tensor(y_train, dtype=torch.float)) loss.backward() optimizer.step() # 评估 model.eval() with torch.no_grad(): test_users = torch.tensor([u for u, i in test_pairs]) test_items = torch.tensor([i for u, i in test_pairs]) test_preds = model(test_users, test_items, L_scaled).squeeze() test_loss = criterion(test_preds, torch.tensor(y_test, dtype=torch.float)) print(f'Epoch {epoch+1}, Train Loss: {loss.item():.4f}, Test Loss: {test_loss.item():.4f}')

4.3 推荐生成

训练完成后,我们可以为特定用户生成推荐:

def recommend_for_user(user_idx, model, num_items, L_scaled, top_k=2): model.eval() with torch.no_grad(): # 为指定用户对所有商品评分 user_tensor = torch.tensor([user_idx] * num_items) item_tensor = torch.tensor(range(num_items)) scores = model(user_tensor, item_tensor, L_scaled).squeeze() # 排除已交互的商品 interacted = adj[user_idx, 3:].nonzero().squeeze() scores[interacted] = -1 # 获取top-k推荐 _, top_items = torch.topk(scores, top_k) return top_items.tolist() # 为用户0生成推荐 print("为用户0推荐的商品:", recommend_for_user(0, model, num_items=4, L_scaled=L_scaled))

5. 进阶优化与实际应用技巧

5.1 处理大规模图的技巧

当面对百万级节点的图数据时,直接计算切比雪夫多项式可能不可行。以下是几种优化策略:

  1. 邻居采样:每次训练只采样每个节点的K-hop邻居
  2. 图分区:将大图分割为多个子图分别处理
  3. 稀疏矩阵运算:利用PyTorch的稀疏矩阵操作减少内存使用
# 稀疏矩阵版本的切比雪夫卷积 class SparseChebConv(nn.Module): def forward(self, x, L_sparse): Tx = [x] if self.K > 0: Tx.append(torch.sparse.mm(L_sparse, x)) for k in range(2, self.K+1): Tx.append(2 * torch.sparse.mm(L_sparse, Tx[-1]) - Tx[-2]) out = torch.zeros_like(Tx[0]) for k in range(self.K+1): out += torch.mm(Tx[k], self.weights[k]) return out

5.2 融合多种图结构

实际推荐系统中,可以融合多种图结构信息:

  • 用户-商品交互图
  • 用户-用户社交图
  • 商品-商品相似图
class MultiGraphGCN(nn.Module): def __init__(self, in_channels, hidden_size, K): super().__init__() self.conv_interact = ChebConv(in_channels, hidden_size, K) self.conv_social = ChebConv(in_channels, hidden_size, K) self.fusion = nn.Linear(2*hidden_size, hidden_size) def forward(self, x, L_interact, L_social): h1 = F.relu(self.conv_interact(x, L_interact)) h2 = F.relu(self.conv_social(x, L_social)) h = torch.cat([h1, h2], dim=1) return self.fusion(h)

5.3 冷启动问题解决方案

对于新用户或新商品,可以采用以下策略:

  1. 元学习:训练模型快速适应新节点
  2. 内容特征增强:利用商品描述、用户画像等辅助信息
  3. 图扩充:通过相似度连接新节点到现有图
# 处理新用户的示例 def process_new_user(user_features, existing_model, L_scaled): # 将新用户特征与现有图连接 new_x = torch.cat([existing_model.x, user_features], dim=0) # 更新拉普拉斯矩阵(需要重新计算) new_adj = update_adjacency_matrix() # 实现略 new_L = compute_laplacian(new_adj) # 实现略 # 生成推荐 return recommend_for_user(new_user_idx, existing_model, num_items, new_L)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 21:49:48

计算机毕业设计之医院预约挂号及满意度评价

摘 要在传统就医模式下,患者前往医院挂号常面临长时间排队等候的困境,不仅耗费大量时间和精力,还可能因号源有限而无法及时就诊。医院的信息发布渠道也较为分散,患者难以便捷获取出诊医生、科室等准确信息。此外,医院对…

作者头像 李华
网站建设 2026/6/11 21:49:15

28岁大专学历顺利转行网安,过来人8条避坑经验心得

网络安全行业 “人才缺口 300 万 、平均年薪超 25 万” 的红利,让无数职场人动了转行心思。尤其是学历普通(如大专)的群体,既面临原有岗位的天花板,又渴望通过技术转型实现薪资跃迁。但网安行业看似门槛低,…

作者头像 李华
网站建设 2026/6/11 21:48:40

关于企业AI转型,管理者最关心的12个问题

Q1:企业AI转型的第一步应该干什么?不是买模型,不是搭平台,不是选场景。第一步是搞清楚你们企业的知识体系在哪、长什么样、能不能被AI用起来。大部分企业的知识散落在文档、系统、员工的脑子里——没有统一管理、没有结构化、没有…

作者头像 李华
网站建设 2026/6/11 21:47:34

计算机毕业设计之基于协同过滤算法的汽车推荐系统

近年来,科技飞速发展,在经济全球化的背景之下,大数据将进一步提高社会综合发展的效率和速度,大数据技术也会涉及到各个领域,而爬虫实现网站数据可视化在网站数据可视化背景下有着无法忽视的作用。管理信息系统的开发是…

作者头像 李华
网站建设 2026/6/11 21:45:54

Windows音频切换神器:AudioSwitch让你告别繁琐的系统设置

Windows音频切换神器:AudioSwitch让你告别繁琐的系统设置 【免费下载链接】AudioSwitch Switch between default audio input or output change volume 项目地址: https://gitcode.com/gh_mirrors/au/AudioSwitch 你是否厌倦了在Windows系统中层层点击才能切…

作者头像 李华