ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于特征工程与相似度计算的数学建模:应用题量化分析实践

2026/8/22 18:55:36 拓冰建站 浏览量
基于特征工程与相似度计算的数学建模:应用题量化分析实践 1. 项目概述与核心价值看到这个标题很多参加过数学建模的朋友可能会心一笑。小学数学应用题听起来简单但真要把它变成一个可量化、可计算的数学模型里面的门道可一点都不少。这个项目说白了就是一次典型的“问题驱动”的数学建模实践我们手头有一堆小学应用题文本目标是设计一套方法既能判断任意两道题在“考什么”上有多像相似性度量又能给每道题打一个“难度分”难度评估。这可不是拍脑袋就能干的活。为什么这件事有价值从教育技术角度看它能为自适应学习系统、智能题库建设、个性化作业推荐提供核心算法支持。想象一下一个系统能自动识别出学生常错题型背后的“母题”或者根据学生当前水平推送难度匹配的练习题这背后的核心技术之一就是题目相似性度量和难度评估。从建模竞赛角度看这是一个融合了自然语言处理NLP、机器学习、教育测量学Psychometrics和统计分析的综合性课题非常考验参赛者将实际问题抽象为数学模型并用代码实现落地的能力。整个项目的核心挑战在于“量化”。小学数学应用题是半结构化的文本包含了场景描述、数量关系和最终问题。如何从这些文字中提取出可计算的特征如何定义“相似”是考察知识点的相似还是解题逻辑的相似或者是语言表述的相似难度又如何界定是看字数的多少还是涉及运算步骤的复杂度或是隐含逻辑关系的层数这些都是我们需要在建模伊始就厘清的关键问题。接下来我将结合常见的建模思路和工具选型为你拆解一个从问题分析到代码实现的完整方案。我们会用到MATLAB作为主要实现工具因为它强大的数学计算、矩阵操作和丰富的工具箱如统计、文本处理、机器学习非常适合这类任务。当然核心思想是语言无关的你也可以用Python等工具复现。2. 问题拆解与整体建模框架面对“相似性度量”和“难度评估”这两个目标我们不能混为一谈需要先分而治之再寻找关联。一个清晰的建模框架是成功的一半。2.1 核心概念定义与问题转化首先我们必须对我们想要度量的东西做出明确的、可操作的界定。题目相似性在此项目中我们主要关注解题逻辑与知识结构的相似性而非表面文字的相似。例如“小明有5个苹果吃了2个还剩几个”和“小华有5颗糖给了妹妹2颗还剩几颗”在文字上不同但在我们定义的相似性度量下应该被认为是高度相似的。反之两道题都关于“买水果”但一道是简单加减另一道是复合比例问题则不应被视为相似。题目难度这是一个多维概念。我们可以从文本复杂度、数量关系复杂度、解题步骤数、抽象程度等多个维度来综合评估。难度评估的目标是产生一个可比较的数值分数能够相对准确地反映小学生解答该题目的困难程度。基于以上定义我们将原始问题转化为两个子任务特征工程从每道应用题文本中抽取出能够表征其“解题逻辑”和“潜在难度”的特征向量。模型构建基于特征向量设计或选择距离/相似度度量算法实现题目间的相似性计算。基于特征向量构建回归或排序模型实现对题目难度的量化评分。2.2 整体技术路线图一个可行的整体技术路线如下图所示此处以文字描述流程数据预处理清洗原始题目文本包括去除无关字符、分词针对中文、去除停用词等。多维度特征提取这是项目的核心。我们将从多个维度抽取特征文本表面特征题目长度、句子数量、平均句长、不同词数占比等。这些特征与阅读难度相关。词袋模型Bag-of-Words与TF-IDF虽然我们不过分关注表面文字但关键词如“速度”、“单价”、“剩余”的出现与否及频率能反映题目所属的粗粒度类别如行程问题、价格问题。语义特征进阶使用预训练的词向量如Word2Vec, BERT将题目表示为稠密向量捕捉更深层的语义信息。对于小学数学题简单的词向量平均或BERT的[CLS]向量就能提供不错的基础。数量关系与运算图特征关键这是体现“解题逻辑”的核心。我们需要解析题目识别出已知量、未知量以及它们之间的运算关系加、减、乘、除、比较、比例等并将其抽象为一个“运算关系图”。从这个图中可以提取特征如节点变量数量、边运算数量、运算类型分布、图的深度反映解题步骤等。教育标签特征如果数据带有标签如所属知识点“两位数加减法”、“一步应用题”、“两步应用题”可以直接将其进行One-Hot编码作为特征。相似性度量模型将每个题目表示为一个高维特征向量后相似性度量就转化为向量空间中的距离计算。常用的方法有余弦相似度最常用衡量特征向量方向上的差异对绝对数值不敏感适合TF-IDF等特征。欧氏距离衡量向量空间中的直线距离。需要注意特征需标准化否则量纲大的特征会主导结果。基于聚类的相似性先使用聚类算法如K-Means, DBSCAN将题目分组同一簇内的题目被视为相似。相似性可以定义为“是否属于同一簇”或“到同一簇心的距离”。专门针对图结构的相似性如果提取了运算关系图可以使用图核Graph Kernel方法或图神经网络GNN来学习图的表示再计算相似度。这在竞赛中属于高级技巧。难度评估模型将难度评估视为一个有监督如果有一部分题目有难度标签或无监督问题。有监督方法如果有专家标注的难度等级如1-5星可以将其作为目标变量使用特征向量进行回归如线性回归、SVR或分类如有序逻辑回归。无监督/弱监督方法更常见的情况是没有标签。我们可以特征加权线性模型邀请领域专家如资深教师对各个特征维度如步骤数、抽象词数量赋予权重直接计算加权和作为难度分。基于解题数据的推断如果能有学生答题记录正确率、答题时间则可以直接用正确率的倒数或答题时间作为难度代理变量然后训练回归模型。排序学习收集题目两两之间的难度比较如“A题比B题难”使用排序学习算法如RankNet来学习一个评分函数。注意在实际竞赛或项目中由于时间和数据限制特征加权线性模型和基于文本/图特征的聚类是最务实、最容易出成果的起点。高级的语义模型和图模型可以作为创新点但需要扎实的工程实现和调优。3. 核心模块一应用题特征工程详解特征工程是模型的基石。对于小学数学应用题我们需要手工设计和提取一系列具有解释性的特征。以下是一个较为全面的特征列表及其计算方式。3.1 文本表面复杂度特征这些特征主要反映题目的阅读负担通过简单的统计即可获得。字符长度题目文本的总字符数。feature1 length(text)。句子数量以句号、问号等为分隔符的句子总数。题目陈述通常只有1-2句。词汇数量与多样性总词数分词后的词语总数。唯一词数去重后的词语数量。词汇丰富度唯一词数 / 总词数。比值越低重复词越多可能表述更简单。平均词长所有词语的平均字符数。汉语中平均词长较长可能意味着使用了更复杂的词汇。数字与单位密度数字出现次数正则表达式匹配\d包括整数和小数。单位词出现次数匹配“个”、“只”、“元”、“米”、“小时”等量词单位。数字密度数字出现次数 / 总词数。单位密度单位词出现次数 / 总词数。高密度可能意味着数量关系复杂。3.2 数量关系与运算特征关键这是区分应用题难度的核心。我们需要编写规则或简单的解析器来识别这些模式。数量实体识别识别题目中所有明确给出的数字及其关联对象。例如“小明有5个苹果” - (小明 苹果 5)。这可以通过依存句法分析或模式匹配实现对于规整的小学题模式匹配足够。运算关系识别识别连接数量实体的关键词。加法类“和”、“一共”、“总共”、“增加”、“多了”。减法类“差”、“还剩”、“剩下”、“减少”、“用了”、“给了”。乘法类“每”、“各”、“倍”、“乘积”。除法类“平均”、“每份”、“分给”、“除”。比较类“比…多/少”、“是…的几倍”、“相差”。基于识别的特征提取已知量个数题目中明确给出的数字数量。未知量个数问题中要求求解的未知数个数通常为1个。运算步骤数估计这是难度的重要指标。可以通过分析要得到答案需要经过几次中间计算来估算。例如一步直接运算特征词直接连接已知量和问题为1步需要先求中间量再求最终答案为2步。我们可以通过构建简单的“解题等式”来推断步骤数。运算类型多样性题目中出现了几种不同的运算加、减、乘、除、比较。类型越多可能越复杂。是否包含隐含条件条件没有直接以数字形式给出如“速度是原来的2倍”、“价格打八折”。这可以通过是否存在“是…的倍”、“折”等词判断是一个布尔特征。是否包含多余条件题目中给出的某个数字在解题中用不到。这需要更复杂的逻辑推理才能准确判断在简单模型中可暂不考虑。实操示例MATLAB思路 假设我们有一道题“商店有4盒钢笔每盒10支卖出25支还剩多少支”文本特征字符数、词数等略。数量关系特征已知量4盒10支/盒25支。运算关键词“每”乘“卖出…还剩”减。运算步骤数第一步4 * 10 40总钢笔数第二步40 - 25 15剩余。故步骤数2。运算类型乘法、减法。隐含条件无。未知量1个还剩多少支。我们可以将这些信息编码为一个特征向量例如[已知量个数3 未知量个数1 步骤数2 包含乘法1 包含减法1 包含除法0 包含比较0 有隐含条件0]。3.3 语义与主题特征为了捕捉超越表面文字的相似性我们需要引入语义信息。TF-IDF向量将整个题库的所有题目视为文档集合为每道题计算TF-IDF向量。向量维度为整个词汇表的大小经过过滤。这个向量可以用于计算题目在“关键词”层面的相似性。词向量平均使用预训练的中文词向量模型如腾讯AI Lab的Chinese Word Vectors将题目分词后每个词转换为词向量然后对所有词向量取平均得到题目的句向量。这种方法能捕捉“苹果”和“橘子”都是“水果”这类语义关联。预训练语言模型编码使用如BERT的预训练模型将整道题输入取[CLS]位置的输出向量作为题目表示。这是目前最强的语义表示方法但计算成本较高。在MATLAB中实现TF-IDF相对容易可以用bagOfWords和tfidf函数。词向量和BERT编码通常需要借助外部工具或调用PythonMATLAB支持调用Python库或者使用MATLAB的Text Analytics Toolbox中的wordEmbedding功能需加载预训练词向量文件。4. 核心模块二相似性度量模型实现有了特征向量我们就可以计算相似性了。这里介绍几种在MATLAB中易于实现的方法。4.1 基于余弦相似度的度量这是最直接的方法。假设我们已将N道题目表示为D维特征矩阵FeaturesN x D其中每一行是一道题的特征向量。% 假设 Features 是一个 N x D 的矩阵行是样本列是特征 % 计算余弦相似度矩阵 similarity_matrix 1 - pdist(Features, cosine); % pdist计算余弦距离1-距离相似度 similarity_matrix squareform(similarity_matrix); % 将向量形式的距离转换为方阵 % 查找与第i题最相似的题目 i 1; [similar_scores, similar_indices] sort(similarity_matrix(i, :), descend); % 最相似的是自己相似度为1所以取第2到第k1个 k 5; top_k_indices similar_indices(2:k1); top_k_scores similar_scores(2:k1); disp(最相似的5道题索引及相似度); disp([top_k_indices, top_k_scores]);关键点在使用余弦相似度前是否需要对特征进行标准化这取决于特征类型。对于TF-IDF特征通常不需要再标准化因为TF-IDF本身已经做了加权。对于手工设计的数值特征如步骤数、已知量个数如果量纲差异大例如字符长度是几百而步骤数是个位数建议进行标准化如Z-score标准化否则步骤数这个重要特征的影响力会被淹没。可以使用zscore(Features)。4.2 基于聚类结果的相似性度量聚类本身是一种无监督的相似性发现方法。同一簇内的题目被认为彼此相似。% 使用K-Means聚类 num_clusters 10; % 假设我们将题目分为10类 [idx, C] kmeans(Features, num_clusters); % idx是每道题所属簇的标签 % 计算两道题是否相似如果它们属于同一个簇则相似度为1否则为0或计算到同一簇心的距离相似度 question_a 1; question_b 2; if idx(question_a) idx(question_b) cluster_similarity 1; else cluster_similarity 0; end % 更精细的度量基于到簇心的距离 % 计算每道题到其所属簇心的距离 distances zeros(size(Features, 1), 1); for i 1:size(Features, 1) distances(i) norm(Features(i, :) - C(idx(i), :)); end % 相似度可以定义为 1 / (1 距离差)距离差越小相似度越高 dist_a distances(question_a); dist_b distances(question_b); centroid_a C(idx(question_a), :); centroid_b C(idx(question_b), :); if idx(question_a) idx(question_b) fine_similarity 1 / (1 abs(dist_a - dist_b)); % 同簇内比较 else % 不同簇可以计算两个簇心之间的距离作为惩罚项 centroid_distance norm(centroid_a - centroid_b); fine_similarity 1 / (1 centroid_distance); % 簇心越远相似度越低 end聚类算法选择K-Means最常用需要指定簇数K。对于题目分类K可以根据经验或通过肘部法则确定。DBSCAN不需要指定簇数能发现任意形状的簇并识别噪声点。如果题目特征空间结构复杂DBSCAN可能更合适。MATLAB中可以使用dbscan函数。实操心得在实际操作中混合使用多种相似度往往效果更好。例如可以分别计算基于TF-IDF的余弦相似度sim_text和基于手工数量关系特征的余弦相似度sim_logic然后进行加权融合sim_final alpha * sim_text (1-alpha) * sim_logic。权重alpha可以通过在一个小的验证集上调整或者根据业务逻辑设定如更看重逻辑相似则alpha设小些。4.3 相似性度量结果可视化与评估如何知道我们的相似性度量模型好不好由于通常没有“标准答案”我们可以采用以下方式评估人工抽样检查随机选取一些题目对让领域专家或自己判断是否相似与模型计算结果对比计算准确率、召回率。聚类效果评估如果用了聚类可以用轮廓系数Silhouette Coefficient评估聚类质量。MATLAB中可用silhouette(Features, idx)计算并绘图。降维可视化使用t-SNE或PCA将高维特征降到2维或3维在图上观察题目点的分布。相似的题目应该在空间中聚集在一起。% 使用PCA降维可视化 [coeff, score, latent] pca(Features); explained_variance cumsum(latent) / sum(latent); disp(前两主成分解释方差比例); disp(explained_variance(1:2)); % 取前两个主成分绘图 figure; gscatter(score(:,1), score(:,2), idx); % idx是聚类标签用颜色区分 xlabel(第一主成分); ylabel(第二主成分); title(应用题特征PCA降维可视化按聚类着色); grid on; % 或者用t-SNE需要Statistics and Machine Learning Toolbox % Y tsne(Features, NumDimensions, 2, Perplexity, 30); % figure; % gscatter(Y(:,1), Y(:,2), idx);5. 核心模块三难度评估模型构建难度评估模型的构建依赖于我们是否有标注数据。这里分别讨论有监督和无监督两种场景。5.1 无监督/专家权重法这是最直接、最可解释的方法。邀请几位资深小学数学教师对我们设计好的特征维度进行权重打分。例如采用德尔菲法Delphi method让专家背对背打分经过几轮反馈后收敛得到一组权重W [w1, w2, ..., wD]。假设我们提取了以下特征并获得了专家权重f1: 解题步骤数 (权重 0.4)f2: 运算类型数量 (权重 0.3)f3: 是否包含隐含条件 (是1否0) (权重 0.2)f4: 题目文本长度标准化后(权重 0.1)那么一道题的难度分Difficulty_Score可以计算为Difficulty_Score 0.4*f1 0.3*f2 0.2*f3 0.1*f4在MATLAB中实现非常简单% 假设 feature_matrix 是 N x 4 的矩阵列对应上述四个特征 % 权重向量 W [0.4, 0.3, 0.2, 0.1]; % 计算难度分 difficulty_scores feature_matrix * W; % 排序 [sorted_scores, sorted_idx] sort(difficulty_scores, descend); % 假设分数越高越难 disp(难度最高的5道题索引及分数); disp([sorted_idx(1:5), sorted_scores(1:5)]);注意事项特征需要先进行归一化到相近的范围如0-1否则权重的意义会失真。例如步骤数范围是1-5而文本长度范围是50-500如果不归一化文本长度的微小变化就会完全主导结果。专家权重的确定是关键需要保证专家的一致性和权威性。5.2 有监督回归模型法如果我们有一部分题目已经有了难度标签例如来自教材的星级标注或者通过众包获取的相对难度排序就可以训练一个回归模型。数据准备将题目特征矩阵Features作为自变量X难度标签连续值或有序等级作为因变量y。模型选择与训练线性回归最简单可解释性强。mdl fitlm(X, y)。支持向量回归SVR对于非线性关系可能效果更好。mdl fitrsvm(X, y, Standardize, true)。梯度提升树如LightGBM/XGBoost通常能获得较高的预测精度但可解释性稍差。MATLAB中可以使用fitrensemble函数选择 boosting 方法。模型评估使用交叉验证评估模型在测试集上的表现常用指标有均方根误差RMSE、平均绝对误差MAE和决定系数R²。% 假设有70%的数据用于训练30%用于测试 cv cvpartition(size(Features,1), HoldOut, 0.3); idx_train training(cv); idx_test test(cv); X_train Features(idx_train, :); y_train difficulty_labels(idx_train); X_test Features(idx_test, :); y_test difficulty_labels(idx_test); % 训练线性回归模型 mdl fitlm(X_train, y_train); % 预测 y_pred predict(mdl, X_test); % 评估 rmse sqrt(mean((y_test - y_pred).^2)); mae mean(abs(y_test - y_pred)); r2 1 - sum((y_test - y_pred).^2) / sum((y_test - mean(y_test)).^2); fprintf(测试集表现RMSE%.3f, MAE%.3f, R²%.3f\n, rmse, mae, r2); % 查看模型系数特征重要性 coeff_table mdl.Coefficients; disp(coeff_table);实操心得在有监督模型中特征工程的质量直接决定模型天花板。除了之前提到的特征还可以尝试构造交叉特征如“步骤数”和“隐含条件”的乘积。同时要警惕过拟合特别是当特征数量较多而标注数据较少时务必使用交叉验证并考虑使用正则化回归如岭回归ridge或 LASSOlasso。5.3 基于解题数据的难度推断理想情况如果能够获取到大量学生在该题库上的答题记录那么难度评估就拥有了最可靠的“金标准”。我们可以定义难度值 ≈ 1 - 正确率。正确率越低题目越难。难度值 ≈ 平均答题时间。耗时越长题目可能越难需排除学生个体差异。有了这些基于真实行为的难度标签再使用5.2中的回归模型进行训练模型的预测能力和泛化性会强很多。这属于教育数据挖掘EDM的范畴。6. 系统集成与方案优化将上述模块组合起来就形成了一个完整的应用题相似性度量与难度评估系统。6.1 端到端处理流程一个完整的处理流程可以封装成一个MATLAB函数或一个类classdef MathProblemAnalyzer properties FeatureExtractor % 特征提取器对象包含词表、向量化模型等 SimilarityModel % 相似性计算模型如特征矩阵、聚类中心等 DifficultyModel % 难度评估模型如回归模型、权重向量等 end methods function obj train(obj, problemTexts, varargin) % 训练流程 % 1. 特征提取 features obj.extractFeatures(problemTexts); % 2. 训练相似性模型如进行聚类 obj.SimilarityModel obj.trainSimilarityModel(features); % 3. 如果有难度标签训练难度模型 if nargin 2 ~isempty(varargin{1}) difficultyLabels varargin{1}; obj.DifficultyModel obj.trainDifficultyModel(features, difficultyLabels); else % 否则使用默认专家权重 obj.DifficultyModel obj.defaultExpertWeights(); end end function sim calculateSimilarity(obj, problemA, problemB) % 计算两道题的相似度 featA obj.extractFeatures({problemA}); featB obj.extractFeatures({problemB}); % 使用余弦相似度 sim 1 - pdist2(featA, featB, cosine); end function score estimateDifficulty(obj, problemText) % 评估单道题难度 feat obj.extractFeatures({problemText}); if isa(obj.DifficultyModel, RegressionModel) % 如果是回归模型 score predict(obj.DifficultyModel, feat); else % 如果是权重向量 score feat * obj.DifficultyModel; end end % ... 其他内部方法如 extractFeatures, trainSimilarityModel 等 end end6.2 方案优化与高级技巧在基础方案上可以从以下几个方面进行优化以提升模型性能特征选择与降维如果特征数量很多可能存在冗余或噪声。可以使用过滤法如计算特征与目标的相关性、包裹法如递归特征消除RFE或嵌入法如LASSO回归进行特征选择。也可以使用PCA进行降维用主成分作为新特征。集成相似度如前所述融合文本相似度TF-IDF/语义向量和逻辑相似度手工特征通常比单一方法更好。可以尝试不同的融合策略加权平均、最大值、最小值并在小样本上验证。图神经网络GNN的探索如果深入解析了应用题的运算关系图可以尝试使用GNN来学习图的表示。每个题目是一个图节点是变量边是运算关系。通过图卷积网络GCN或图注意力网络GAT可以学习到一个融合图结构信息的题目向量用于相似性和难度计算。这在近年来的研究中是一个热点但实现复杂度较高。难度评估的排序学习如果我们能获取题目两两之间的难度比较“A比B难”即使没有绝对分数也可以使用排序学习算法如RankNet、LambdaRank来学习一个评分函数。这比回归对数据的要求更弱也更符合人类的判断方式。6.3 常见问题与排查技巧实录在实际实现过程中你可能会遇到以下典型问题问题1特征提取不一致导致相似度计算偏差大。现象同一道题换种说法提取的特征向量差异巨大。排查检查文本预处理步骤分词、去停用词是否稳定。对于数量关系特征检查规则是否覆盖了常见的表达变体如“一共”、“总共”、“合计”都应识别为加法。解决丰富规则词典考虑使用同义词词林或哈工大同义词词库来扩展关键词匹配。对于核心逻辑特征可以尝试使用简单的句法分析来更稳定地提取主谓宾和数量关系。问题2聚类结果不理想同一簇内题目差异明显。现象通过可视化如t-SNE图发现聚类边界模糊同一簇包含明显不同类型的题目。排查首先检查特征是否进行了合适的标准化。其次尝试不同的聚类算法K-Means, DBSCAN, 谱聚类和参数如K值DBSCAN的Eps和MinPts。解决使用轮廓系数和Calinski-Harabasz指数等指标定量评估聚类质量选择最优的算法和参数。考虑是否特征维度需要先进行降维PCA再聚类。问题3难度评估模型在训练集上表现好在测试集上表现差过拟合。现象回归模型的训练集R²很高但测试集R²很低RMSE很大。排查检查训练样本数量是否过少特征数量是否过多。查看模型系数是否有某些特征的系数异常大。解决增加训练数据如果可能。进行特征选择减少不相关或冗余特征。使用正则化回归岭回归或LASSO。LASSO还可以自动进行特征选择。使用更简单的模型如线性回归替代复杂的非线性模型。确保训练集和测试集的数据分布如题目类型、难度范围是相似的。问题4对于极其简短的题目语义向量表示效果差。现象如“11”这类题目词向量平均或BERT编码可能无法有效捕捉其数学含义。解决对于这类题目应更依赖手工设计的数量关系特征。可以将语义特征和手工特征进行拼接让模型自行学习权重。或者为这类“简单计算题”单独设置一条处理规则。问题5MATLAB处理大规模文本数据速度慢。现象题库有上万道题时TF-IDF计算或相似度矩阵计算耗时很长。解决利用MATLAB的矩阵运算优势避免循环。例如计算所有样本对之间的余弦相似度使用pdist函数比双重循环快得多。对于非常大的矩阵考虑使用稀疏矩阵存储TF-IDF特征。将最耗时的步骤如BERT编码用Python实现再利用MATLAB的Python接口调用。如果内存允许使用parfor进行并行循环加速特征提取过程。最后我想分享的一点个人体会是数学建模竞赛中的这类题目精髓不在于使用了多么高深的模型而在于如何将一个模糊的实际问题通过合理的假设和抽象转化为一个清晰、可计算的数学问题。对于“相似性”和“难度”的定义本身就是建模的一部分。你的模型可能不完美但整个思考过程、方案设计的逻辑性、以及模型结果的可解释性往往比单纯的预测精度更重要。在论文写作中一定要清晰地阐述你的定义、假设、模型构建的每一步理由以及模型的局限性。附上结构清晰、注释完整的MATLAB代码无疑能为你的作品增色不少。