资讯动态

数学建模实战:基于复杂网络与因子分析的智能推荐系统构建

发布时间:2026/8/27 19:26:18 来源:尧图企业网站定制
1. 项目概述从数学建模到智能推荐的一次实战最近在整理过往的参赛资料翻到了当年参加Mathorcup妈妈杯数学建模竞赛B题的完整解题过程。这道题的核心是“基于复杂网络和因子分析的智能推荐”它完美地将理论模型与实际应用结合在了一起。对于很多刚接触数学建模或者对推荐系统感兴趣的朋友来说这道题是一个绝佳的练手项目。它不像纯算法题那样抽象而是要求你从一堆看似杂乱的数据中构建网络、提取特征最终形成一个能“理解”用户和物品的推荐模型。今天我就把自己当时的解题思路、用到的工具主要是SPSS和MATLAB以及踩过的坑系统地梳理一遍。无论你是为了备战数模竞赛还是想深入理解推荐系统的底层逻辑相信这篇内容都能给你带来直接的帮助。简单来说这道题给了我们一个典型的“用户-物品”交互数据集比如用户对商品的评分、点击或购买记录。我们的任务不是简单地套用协同过滤而是要先用复杂网络的理论去刻画用户和物品之间的关系结构再用因子分析等方法降维、提取核心特征最后构建一个智能推荐模型。整个过程涉及数据预处理、网络构建与指标计算、特征工程、模型建立与评估等多个环节非常考验综合能力。下面我就分步骤拆解当时是怎么做的。2. 解题整体思路与核心逻辑拆解面对这样一个题目第一步不是急着打开MATLAB写代码而是要把整个问题的逻辑链条理清楚。题目要求“基于复杂网络和因子分析”这直接指明了我们的技术路径。我的核心思路可以概括为“分治与融合”先将庞大的“用户-物品”二分网络进行拆解和量化再用因子分析提炼出简洁有效的特征最后将这些特征输入到一个可解释的推荐模型中。2.1 为什么是“复杂网络”“因子分析”这是一个非常巧妙的设计。复杂网络擅长描述对象之间的关联结构和动力学特性。在推荐场景中用户和物品构成了一个天然的二分网络。通过计算网络的节点度、聚类系数、中心性等指标我们可以量化每个用户的活跃度、每个物品的流行度以及用户之间通过共同物品产生的“隐性社群”结构。这些网络指标是原始评分数据之外的一层深层信息。但是直接使用这些网络指标作为特征维度可能依然很高且彼此之间存在共线性比如度中心性和接近中心性可能高度相关。这时因子分析Factor Analysis就派上用场了。它的核心思想是从多个观测变量即我们的网络指标和原始评分统计量中提取出少数几个潜在的、不可观测的“因子”。这些因子能够解释原始变量的大部分方差。在推荐系统中这些因子可以被理解为“潜在兴趣维度”例如“科技发烧友因子”、“文艺清新因子”、“性价比追求因子”等。通过因子分析我们实现了特征降维和去噪得到了更纯净、更具解释性的用户和物品特征向量。2.2 整体技术路线图基于以上理解我规划了如下四阶段技术路线数据预处理与网络构建清洗原始数据构建“用户-物品”二分关联矩阵并分别投影得到“用户-用户”同构网络和“物品-物品”同构网络。复杂网络特征提取对上述两个同构网络计算一系列节点级和网络级的拓扑指标作为原始特征池。因子分析与特征降维将上一步得到的高维特征可能包含几十个指标输入SPSS进行因子分析提取出少数几个主因子并计算每个用户/物品在这些因子上的得分即新的特征向量。推荐模型构建与评估利用降维后的特征向量构建推荐模型。常用的方法包括基于余弦相似度的近邻推荐、或构建一个简单的回归/分类模型来预测评分。最后必须使用留出法或交叉验证来评估推荐效果。这个路线的优势在于它既有坚实的理论支撑图论、多元统计又步步为营每个环节的输出都是下一个环节的输入最终形成一个完整的解决方案。3. 数据预处理与复杂网络构建实操一切始于数据。竞赛提供的数据通常是CSV或Excel格式记录了UserID,ItemID,Rating或Action这样的三元组。3.1 数据清洗与矩阵化首先在MATLAB中读入数据。清洗工作包括处理缺失值如删除评分记录为空的条目、处理异常值如将超出合理范围的评分截断或视为缺失。对于隐式反馈数据如点击可能需要将其转化为0/1的二元信号。% 假设数据文件为 ratings.csv包含三列userId, itemId, rating data readtable(ratings.csv); userIds data.userId; itemIds data.itemId; ratings data.rating; % 获取唯一的用户和物品列表 uniqueUsers unique(userIds); uniqueItems unique(itemIds); numUsers length(uniqueUsers); numItems length(uniqueItems); % 创建用户-物品评分矩阵 R (稀疏矩阵效率更高) R zeros(numUsers, numItems); % 建立映射字典将原始ID映射到矩阵索引 [~, userIdx] ismember(userIds, uniqueUsers); [~, itemIdx] ismember(itemIds, uniqueItems); for k 1:length(ratings) R(userIdx(k), itemIdx(k)) ratings(k); end % 此时R(i,j) 表示用户i对物品j的评分0表示无交互注意如果数据量极大务必使用稀疏矩阵sparse来存储R否则内存可能爆炸。R sparse(userIdx, itemIdx, ratings, numUsers, numItems);3.2 构建复杂网络从二分网络到投影网络原始的R矩阵定义了一个二分网络用户和物品是两类节点评分是边。为了分析用户之间的关系或物品之间的关系我们需要进行网络投影。用户-用户网络基于共同评分物品 如果两个用户共同评分过多个物品那么他们之间可能存在相似的兴趣。我们可以用共同评分的物品数量或者更精细的加权方式如评分向量的余弦相似度来定义用户节点之间边的权重。% 方法1基于共同评分物品数量的简单投影未加权 % 将评分矩阵二值化有评分则为1 R_binary (R 0); % 用户-用户邻接矩阵A_uu R_binary * R_binary % 对角线元素是每个用户评分的物品数应置零去除自环 A_uu R_binary * R_binary; A_uu A_uu - diag(diag(A_uu)); % 去除自环 % 方法2基于余弦相似度的加权投影更常用 % 计算用户之间的余弦相似度作为边权 normR sqrt(sum(R.^2, 2)); % 每个用户的评分向量模长 % 避免除零 normR(normR 0) eps; R_norm R ./ normR; % 行归一化按用户 A_uu_cos R_norm * R_norm; % 这就是余弦相似度矩阵 A_uu_cos A_uu_cos - diag(diag(A_uu_cos)); % 去除自环物品-物品网络基于共同被评用户 逻辑完全对称。如果两个物品被同一批用户评分则它们可能属于相似类别。同样可以用共同用户数或余弦相似度来构建边。% 物品-物品网络基于余弦相似度 normC sqrt(sum(R.^2, 1)); % 每个物品的评分向量模长按列 normC(normC 0) eps; C_norm R ./ normC; % 列归一化按物品 A_ii_cos C_norm * C_norm; % 物品间的余弦相似度矩阵 A_ii_cos A_ii_cos - diag(diag(A_ii_cos));至此我们得到了两个加权的同构网络A_uu_cos用户网络和A_ii_cos物品网络。它们是我们后续提取特征的基础。4. 复杂网络特征计算与指标解读有了网络下一步就是从中“挖矿”——计算各种网络科学指标。这些指标从不同维度描述了节点在网络中的地位和重要性。4.1 节点级特征计算对于每个用户在用户网络中和每个物品在物品网络中我们计算以下几类核心特征。这里以用户网络A_uu_cos为例物品网络计算方式完全相同。% 假设 A 是加权邻接矩阵已去自环 A A_uu_cos; numNodes size(A, 1); node_features struct(); % 1. 节点强度加权度所有连边权重之和 node_features.Strength sum(A, 2); % 2. 度中心性原始度连边数量权重0即算一条边 A_binary (A 0); node_features.Degree sum(A_binary, 2); % 3. 特征向量中心性一个节点的重要性取决于其邻居的重要性 % 使用MATLAB的eigs函数计算主特征向量 [V, ~] eigs(A, 1); % 获取最大特征值对应的特征向量 node_features.EigenvectorCentrality abs(V); % 取绝对值 % 4. 接近中心性节点到网络中所有其他节点最短路径距离之和的倒数 % 对于加权网络边权通常视为“距离”的倒数或成本。这里假设边权为相似度距离 1 / 权重需处理零权 % 这是一个计算密集型操作对于大网络需要谨慎或使用近似算法 % 此处给出概念代码实际比赛可能因规模而简化或采用其他中心性 % D graphallshortestpaths(sparse(A), Directed, false); % 需要将A转换为距离 % node_features.Closeness 1 ./ sum(D, 2); % 简化使用强度作为接近中心性的代理 % 5. 介数中心性经过该节点的最短路径占所有最短路径的比例 % 计算量极大通常用于中小型网络分析。可使用MATLAB的centrality函数。 % node_features.Betweenness centrality(graph(A), betweenness); % 比赛时若数据量大可考虑舍弃或抽样计算。 % 6. 聚类系数衡量节点邻居之间的紧密程度 % 对于加权网络有加权聚类系数的定义 node_features.ClusteringCoefficient clustering_coefficient_wu(A); % 需要自定义或调用工具箱函数实操心得在数模竞赛的有限时间内特征向量中心性和强度通常是性价比最高的选择。它们计算相对快速且能有效区分核心用户高影响力用户和普通用户。介数中心性计算复杂度是O(nm)对于成千上万个节点的网络可能跑几个小时都出不来结果务必慎用。如果数据规模大一个讨巧的办法是只计算节点强度和度中心性或者使用网络工具包如Brain Connectivity Toolbox里的优化函数。4.2 网络级特征与社群发现除了单个节点的特征整个网络的宏观特性也能提供信息。例如我们可以进行社群发现社区检测将用户或物品划分成若干群落。% 使用经典的Louvain算法进行社群发现需安装相应工具箱如GenLouvain % 这里以用户网络为例 % [S, Q] community_louvain(A); % S是每个节点的社区标签Q是模块度 % node_features.CommunityLabel S;将每个节点所属的社区编号也作为一个分类特征可以捕捉到“物以类聚人以群分”的效应。5. 因子分析从高维特征到潜在因子经过上一步我们可能为每个用户和物品生成了10-20个网络特征和原始统计特征如平均评分、评分方差等。直接把这些特征扔进推荐模型维度高且冗余。因子分析正是用来解决这个问题的。5.1 数据准备与SPSS操作将MATLAB中计算好的特征导出为CSV文件例如user_features.csv包含的列有UserID,Strength,Degree,EigenCentrality,AvgRating,RatingStd等。打开SPSS导入user_features.csv。检查数据适用性进行KMO和巴特利特球形检验。点击“分析” - “降维” - “因子分析”。将所有数值型特征变量选入“变量”框。点击“描述”按钮勾选“KMO和巴特利特球形度检验”。点击“继续”然后点击“确定”。结果解读KMO值大于0.6巴特利特检验p值小于0.05说明数据适合做因子分析。提取公因子再次打开“因子分析”对话框。在“抽取”方法中选择“主成分”这是最常用的方法实际上是在做主成分分析PCA但在此语境下常混用。在“输出”中勾选“未旋转的因子解”和“碎石图”。在“抽取”部分基于“特征值大于1”的准则凯泽准则来决定因子数量或者观察碎石图的拐点。因子旋转使结果更易解释在“旋转”方法中选择“最大方差法”Varimax。这是一种正交旋转能使得每个因子在部分变量上有高载荷在其他变量上载荷低便于解释因子含义。保存因子得分在“得分”对话框中勾选“保存为变量”并选择“回归”方法。这会在SPSS数据集中生成新的变量FAC1_1, FAC2_1...即每个用户在各因子上的得分。5.2 结果解读与因子命名SPSS输出结果中最关键的两个表格是“总方差解释”和“旋转后的成分矩阵”。总方差解释表告诉我们提取的几个因子累计解释了原始变量总方差的百分比。通常达到70%-85%就可以接受说明因子保留了大部分信息。旋转成分矩阵这个表是给因子“命名”的依据。例如你可能会发现因子1在“特征向量中心性”、“强度”、“度”上载荷很高。这可以命名为“网络影响力因子”得分高的用户是网络中的核心活跃分子。因子2在“平均评分”、“评分方差”上载荷很高。这可以命名为“评分行为因子”区分了宽容的高分用户和苛刻的低分用户。因子3在“聚类系数”和某个特定物品类别的平均评分上载荷高。这或许可以解释为“小众兴趣聚集因子”。通过因子分析我们将几十个原始特征压缩成了3-5个有明确意义的“潜在因子”。每个用户现在可以用一个低维向量[F1得分 F2得分 F3得分]来表示。对物品特征矩阵也进行完全相同的操作。避坑指南因子分析前一定要对特征进行标准化均值为0标准差为1因为不同特征的量纲差异巨大。SPSS在因子分析过程中默认会进行标准化处理但如果你在MATLAB中自己做PCA务必先zscore一下数据。另外因子数量的选择不是绝对的需要结合碎石图拐点和因子的可解释性综合判断。有时特征值略小于1但意义明确的因子也可以保留。6. 构建智能推荐模型现在我们有了降维后的用户特征矩阵U_factors(n_users x k_factors) 和物品特征矩阵I_factors(n_items x k_factors)。构建推荐模型的本质是预测一个用户对一个物品的评分r_ui。6.1 模型选择基于潜在因子的矩阵分解思想最直观的模型是基于内容的推荐但这里我们有了更丰富的“内容”——潜在因子。我们可以借鉴矩阵分解的思想假设评分由用户因子向量和物品因子向量的内积加上偏置项构成预测评分 r_ui_hat global_mean b_u b_i U_factors(u, :) * I_factors(i, :)其中global_mean全局平均评分。b_u用户偏置表示用户个人打分严格或宽松的程度。b_i物品偏置表示物品本身受欢迎或高质量的程度。这实际上是一个简单的线性回归模型。我们可以通过最小化预测评分与实际评分的均方误差来求解这些偏置项和因子向量虽然我们的因子是固定的但可以将其视为特征学习其权重。6.2 在MATLAB中实现模型训练与预测我们将问题转化为一个回归问题。对于每一条已知评分记录(u, i, r_ui)其特征是用户因子向量和物品因子向量的拼接目标是预测评分。% 假设已有 % factor_scores_user: n_users x k1 矩阵用户因子得分 % factor_scores_item: n_items x k2 矩阵物品因子得分 % train_idx: 训练集索引对应R矩阵中的非零元素已划分好训练测试集 % test_idx: 测试集索引 % 准备训练数据 [rows, cols] find(R_train); % R_train是训练集评分矩阵 y_train R_train(R_train ~ 0); % 真实评分 X_train []; for idx 1:length(y_train) u rows(idx); i cols(idx); % 拼接用户因子和物品因子作为特征 feature_vec [factor_scores_user(u, :), factor_scores_item(i, :)]; X_train [X_train; feature_vec]; end % 添加一列全1用于拟合全局均值/截距项 X_train [ones(size(X_train, 1), 1), X_train]; % 使用线性回归求解权重 w w (X_train * X_train) \ (X_train * y_train); % 准备测试数据并预测 [rows_test, cols_test] find(R_test); y_test_true R_test(R_test ~ 0); y_test_pred zeros(size(y_test_true)); for idx 1:length(y_test_true) u rows_test(idx); i cols_test(idx); feature_vec [factor_scores_user(u, :), factor_scores_item(i, :)]; x_test [1, feature_vec]; % 同样添加截距项 y_test_pred(idx) x_test * w; end % 评估模型计算均方根误差RMSE和平均绝对误差MAE rmse sqrt(mean((y_test_pred - y_test_true).^2)); mae mean(abs(y_test_pred - y_test_true)); fprintf(测试集 RMSE: %.4f, MAE: %.4f\n, rmse, mae);6.3 生成推荐列表模型训练好后对于目标用户u要预测其对所有未评分物品i的评分r_ui_hat然后取预测分最高的Top-N个物品作为推荐。function [topN_items, topN_scores] generate_recommendations(u, w, factor_scores_user, factor_scores_item, rated_items, N) % u: 目标用户索引 % rated_items: 该用户已评分的物品索引列表 % N: 推荐列表长度 num_items size(factor_scores_item, 1); pred_scores zeros(num_items, 1); user_factor factor_scores_user(u, :); for i 1:num_items if ~ismember(i, rated_items) % 只预测未评分的 feature_vec [user_factor, factor_scores_item(i, :)]; x [1, feature_vec]; pred_scores(i) x * w; else pred_scores(i) -inf; % 已评分的置为负无穷不会被选中 end end [sorted_scores, sorted_idx] sort(pred_scores, descend); topN_items sorted_idx(1:min(N, sum(pred_scores ~ -inf))); topN_scores sorted_scores(1:min(N, sum(pred_scores ~ -inf))); end7. 模型评估、优化与竞赛呈现要点模型建好不是终点评估和优化才能体现水平。7.1 评估指标的选择在数学建模竞赛中不仅要看预测精度还要考虑模型的创新性和解释性。预测精度指标必须汇报RMSE均方根误差对较大误差惩罚更重是评分预测最常用的指标。MAE平均绝对误差更直观。在划分训练集/测试集时建议采用5折或10折交叉验证使结果更稳健。推荐质量指标如果赛题要求Top-N推荐PrecisionN, RecallN在测试集上看推荐的N个物品中有多少是用户真正喜欢的在测试集中评分高的。NDCGN考虑推荐列表顺序的指标更符合实际场景。模型解释性评估加分项对你提取的“潜在因子”进行清晰的命名和解释。例如展示在某个因子上得分最高的用户群体有什么行为特征得分最高的物品属于什么类别。这能极大提升论文的理论深度。7.2 模型优化思路如果基线模型效果不理想可以从以下几个方向优化特征工程网络特征是否计算全面可以尝试加入PageRank值、局部聚类系数等。除了网络特征可以融合用户的人口统计学特征如果题目提供、物品的类别信息等。对特征进行非线性变换如平方、对数变换有时能提升效果。因子分析改进尝试不同的旋转方法如斜交旋转Promax看是否能得到更清晰的因子结构。调整因子数量观察模型性能变化找到最佳维度。模型层面将简单的线性回归升级为正则化的线性模型Ridge或Lasso防止过拟合。尝试更复杂的模型如梯度提升树LightGBM/XGBoost将因子得分作为特征输入。这在MATLAB中也有相应的函数库或可以通过调用Python实现。实现一个简单的神经网络将用户和物品的因子向量输入一个多层感知机MLP进行评分预测。7.3 竞赛论文撰写与代码呈现要点在Mathorcup这类竞赛中清晰的呈现和可复现的代码至关重要。论文结构问题重述与分析用自己的话解读题目明确任务。模型假设与符号说明列出关键假设定义文中所有数学符号。模型建立与求解这是核心。按照“网络构建 - 特征提取 - 因子分析 - 推荐模型”的逻辑线图文并茂地阐述。流程图是必备的。模型求解与结果分析展示实验结果包括评估指标、推荐样例、因子解释的可视化如因子载荷图。模型评价与推广分析模型的优缺点提出改进方向。代码附录提供完整、可运行的MATLAB和SPSS操作关键步骤代码/截图。MATLAB代码要模块化有清晰的注释。主脚本最好能一键运行。将SPSS因子分析的关键设置界面和结果表格如KMO检验、总方差解释表、旋转成分矩阵截图放入论文。在附录中说明运行环境如MATLAB R2021a, SPSS 26。终极心得数学建模竞赛比拼的不仅是模型复杂度更是解决问题的逻辑完整性和表述的清晰度。这道B题如果你能条理分明地走完“数据-网络-特征-因子-模型-评估”这个闭环并对其中的每一步做出合理解释即使模型比较简单也能获得不错的成绩。复杂网络和因子分析是工具核心思想是通过挖掘数据中隐藏的结构化信息来增强推荐系统的可解释性和效果。在论文中一定要突出这个思想而不仅仅是罗列代码和数字。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价