2023年华中杯数学建模
B题 小学数学应用题相似性度量及难度评估
原题再现
某 MOOC 在线教育平台希望能够进行个性化教学,实现用户自主学习。在用户学习时,系统从题库中随机抽取若干道与例题同步的随堂测试题,记录、分析学生的学习和答题信息,并且课后会自动生成作业题(或练习题)。此外,系统还能够定期回溯学生的易错题所涉及的内容,自动推荐题型相似、难度有层次的其他题目供用户进行拓展练习。为实现这样的功能,如何度量题目之间的相似性,如何评估题目的难度,是该产品要解决的关键问题。
以小学数学应用题 1为例,度量题目之间相似性的依据主要有以下两种:
题干文字。这种方法一般只能找到与题干文字相近的题目作为相似题目。但是,有些题目的题干文字相似,而关键字词不同,题意差异较大;有些问题的背景可能毫无关联,题干文字也几乎不同,而题目的解题思路与方法技巧却完全相同。因此,这种方法效果有限。
事先标注题目的知识点等信息。这种方法的推荐效果取决于知识点的划分方式和粒度。知识点划分太粗,推荐结果可能与例题或用户的易错题差别太大;知识点划分太细,推荐结果可能太单一。两种情况下都无法真正达到拓展练习的目的。评估题目难度的常见做法主要有以下两种 2:
根据考试的类型确定。比如,数学竞赛的试题一般比某个小学期末考试题目难。
教师根据经验主观判断。
上述判断题目相似性和评估难度的做法都有明显的局限性。该公司聘请你们团队尝试解决这些问题。以小学数学应用题为例,具体任务如下:
1. 设计刻画两道小学数学应用题之间相似性的度量方法。
2. 建立评估小学数学应用题难度的数学模型。
3. 附件 1 是一个示例题库,包含 100 道应用题。请将附件 1 中的题目,按相似性或难度分类(不限制某一道题目只能属于一个分类)。如果某道题目没有相似题目,可以单独成一类。评估算法的复杂度,能否适用于更大规模的题库。
4. 附件 2 中包含 10 道题目,请使用上述模型或方法分析这些题目的难度,并对于其中的每一道题目,在附件 1 中找出最相似的一道或若干道题目(没有相似题目可写“无)”。评估算法的复杂度,能否适用于更大规模的题库。
注 1:题目所述小学数学应用题,是指以四则运算为主要求解方法,有一定实际背景的问题。
注 2:教学中还有一种确定题目难度的常见做法,即根据题目的实际得分率来定义题目的难度。但是,题目的实际得分率不仅与学生考前的学习情况有关,还与很多“非技术”因素有关,比如题目所用的词语、句型、语态,甚至是题目在试卷中出现的先后顺序等等;实际的得分率也只能通过采集真实的试卷信息获得,工作量大。因此,本题所关心的是题目的“技术”难度,不考虑实际的得分率。
附件说明:
1. 附件 1 为 CSV 格式文件,无标题行,共 2 列 100 行。第一列为题目编号,形如“P001”、“P002”等。第二列为题目内容。
2. 附件 2 为 CSV 格式文件,无标题行,共 2 列 10 行。第一列为题目编号,形如“Q001”、“Q002”等。第二列为题目内容。
整体求解过程概述(摘要)
本文通过参考小学数学应用题实际背景,综合有关权威网站与文献,我们总结出小学数学应用题相似性与难度度量的多个角度,并进行对应的数据量化以实现问题的解决。
针对问题一,构建相似性度量方法时,我们的目的是为了能够精准地推荐给用户相关的练习题,提高其数学能力。为此,我们综合了多个有关权威网站的题型解析与相关文献的总结,确定了以下几个角度:应用题题型、标准解答是否需要画图解题、文本的相似性、应用真实场景进行相似性评估,并对其进行了数据量化,以实现相似性的精确度量。针对文本相似性,我们创新引入了 SimHash 算法进行高效率高精度的文本分析。通过搭建不同属性的量化矩阵,经过优化调整后的加权计算得到应用题相似性最终矩阵。
针对问题二,与问题一类似,我们通过结合小学生的学习实际与有关权威网站的数据,决定从多个角度进行小学数学应用题难度的评估,并进行数据量化,以实现难度的精确度量。难度评估属性囊括题目长度、题目长度、未知量个数、已知量个数、标准解答是否需要画图解题、涉及几位数的运算、加减号个数、乘号个数、除号个数、原子公式个数、方程元数、标准解答是否涉及分数、应用题题型。凭借收集到的小学数学应用题数据,我们进行属性的量化,并使用熵权法进行信息熵的分析,以使得难度评估更加客观。在此基础上结合 TopSis 方法,参考正理想解与负理想解,得出各应用题的最终难度评估。
针对问题三,我们针对相似度与难度两种分类情况,基于问题一与问题二所得到的两种不同结果形式采取针对性的分类算法。对于按相似度分类,我们采用 AGNES 算法进行分类;对于按难度分类,我们采用 K-means 算法进行分类。同时我们进行两类算法复杂度的评估,并讨论其是否能适用于更大规模的题库。
针对问题四,我们考虑将附件 2 中的 10 个应用题加入问题一的相似性度量模型,与附件 1中的 100 个应用题共同进行相似性度量,对于输出的相似性度量结果再进行进一步的分析总结。同时我们进行相似性度量算法复杂度的评估,并讨论其是否能适用于更大规模的题库。
模型假设:
1. 假设所有小学生的解题能力处于平均水平,即可以把所有小学生的数学能力视为同质的。
2. 假设题目的难度仅仅由题目本身的特征决定,而不受到小学生个体差异的影响。
3. 假设每个应用题目是独立的,即每个题目的难度与其他题目无关。
4. 假设不同小学生在理解题目和表达答案时使用的语言无差异性,而将其视为单纯的数学问题。
5. 假设不同小学生在解题时会按照标准的解题步骤进行操作,而不会使用其他不常见的解题方法,这些标准解题步骤是最容易被小学生理解和掌握的。
问题分析:
对于问题一,在构建相似性度量方法时,我们的目的是为了能够精准地推荐给用户相关的练习题,提高其数学能力。为此,我们综合了多个有关权威网站[1] 的题型解析与相关文献的总结,确定了以下几个角度进行相似性评估,并对其进行了数据量化,以实现相似性的精确度量:
1. 应用题题型:小学数学应用题有多种不同的题型,例如工程问题,牛吃草问题等等。每种题型都需要不同的思考方式和解决方法。我们将有关权威网站的题型分类纳入小学数学应用题之间相似性的度量要素中,进而不仅考虑到了知识点的相似性比较,还考虑到了题目思考方式,逻辑方法的相似性比较,具有很强的可信性。
2. 标准解答是否需要画图解题:在小学数学应用题中,有些问题需要通过绘制图形才能更好地理解和解决。而需要画图解决的问题与不需要画图解决的问题,有较大的技术差异性。即对于那些需要画图才能解决的问题,学生需要具备良好的空间想象和准确的绘图技能。故而通过将此纳入小学数学应用题之间相似性的度量要素中,能起到较强的度量辅助作用。
3. 文本的相似性:题目中的文字描述也是小学数学应用题之间相似性比较的重要要素之一。在结合了小学数学应用题的内在技术要素后,我们仍然需要将文本相似性纳入小学数学应用题之间相似性的度量要素中。因为小学数学应用题的题目背景大概率与题目的内在技术有强联系关系,如工程问题中的绝大部分问题的文本叙述重点会极大相同。这样能够更全面地考虑到题目之间的相似性,增强相似性评估的精确性。
4. 应用真实场景:小学数学应用题往往与现实场景有很强的关联性,因此考虑到题目与现实场景的相似性比较有助于更好地评估题目之间的相似性,通过类似真实场景的题目推荐,也能帮助小学生对该类问题进行理解的加强。因此,我们将真实场景相似性度量纳入了小学数学应用题之间相似性的度量要素中,加以综合考虑题目的知识点、解题方式、文本相似性以及与现实场景之间的关联性,从而提高题目相似性评估的准确性和可靠性。
对于问题二,针对问题二,需要建立评估小学数学应用题难度的数学模型。首先与问题一类似,我们通过结合小学生的学习实际与有关权威网站的数据,决定从以下角度进行小学数学应用题难度的评估,并进行数据量化,以实现难度的精确度量:
1. 题目长度:题目长度是一个影响小学数学应用题难度的重要因素。现在大多数学生对于应用题目的阅读通常是囫囵吞枣,当一遍阅读完成后即开始答题,最终所得到的答案大部分是错误的[3]。那么通常情况下,冗长和复杂的语句会造成学生的阅读困难,进而导致题目的难以理解,无法做出正确解答。我们通过计算小学数学应用题中的字符数来量化题目长度。
2. 未知量个数:未知量是数学应用题中需要被求解的数量,因此,未知量的个数直接影响着问题的难度,个数越多,意味着计算流程越复杂。在小学数学应用题中,未知量通常蕴含在问句中,即题目要求得到的结果。我们可以通过计算题目中未知量的个数来量化问题的难度。
3. 已知量个数:已知量是数学应用题中给定的已知条件或信息,是解题的基础。已知量的数量也会影响到问题的难度,个数阅越多,意味着题目所给条件越复杂,需要较强的归纳与理解能力。在小学数学应用题中,我们定义一条已知信息为一个已知量。我们可以通过计算题目中已知量的个数来量化问题的难度。
4. 标准解答是否需要画图解题:在小学数学应用题中,有些问题需要通过绘制图形才能更好地理解和解决。对于那些需要画图才能解决的问题,学生需要具备良好的空间想象和准确的绘图技能。因此,需要画图解题的问题通常比较困难。我们可以通过判断题目是否需要画图来量化问题的难度。
5. 涉及几位数的运算:在小学数学应用题中,涉及加、减、乘、除四则运算,其中四则运算涉及的位数也会影响问题的难度。例如,涉及两位数的乘法比涉及一位数的乘法要难得多。我们可以通过计算题目中涉及运算的最大位数来量化问题的难度。
6. 加减号个数:加减号的数量是影响小学数学应用题难度的因素之一。加减法是小学数学应用题中最基础的运算,加减号的数量越多,说明计算步骤越多,难度也就越大。因此,我们可以通过计算题目中加减号的数量来量化问题的难度。
7. 乘号个数:乘号的数量是影响小学数学应用题难度的因素之一。乘法是小学数学应用题中一个相对较难的运算,乘号的数量越多,说明计算步骤越多,难度也就越大。因此,我们可以通过计算题目中乘号的数量来量化问题的难度。
8. 除号个数:除号的数量是影响小学数学应用题难度的因素之一。除法是小学数学应用题中最难的四则运算,由于除法的运算方式与加减乘有很大差异. 除号的数量越多,说明计算步骤越多,难度也就越大。因此,我们可以通过计算题目中除号的数量来量化问题的难度。
9. 原子公式个数:基于小学数学应用题的逻辑步骤难以量化,我们通过收集官方解答步骤的数据,从中提取原子公式的个数以反映逻辑步骤,同时也反映了计算的复杂程度。原子公式是指数学应用题中的最基本的、不可分解的数学表达式,例如 2x + 3、4y − 5 等。原子公式的数量也会影响问题的难度。我们可以通过计算题目中原子公式的数量来量化问题的难度。
10. 方程元数:方程元数指的是方程中未知数的数量。一个方程中未知数越多,就需要进行更多的计算才能得到正确答案,因此难度也就越大。我们考虑到部分应用题并非必须采用方程的方式解决,但方程的解题方式一般意味着原子公式个数的减少,即推理过程的难度下降。故而考虑方程元数这一因素可与原子公式个数相互协调,使得度量可信度得到提高。我们可以通过计算题目中未知数的数量来量化方程元数。
11. 标准解答是否涉及分数:小学数学中,涉及分数的题目往往会被认为是较难的题目之一,因为它需要学生有较强的分数概念和运算能力,以及抽象理解能力。并且约分,最小公分母的计算,会涉及到全部四则运算,因此涉及分数的应用题难度较大。我们可以通过检测应用题中是否涉及分数来量化问题的难度。
12. 应用题题型:小学数学应用题有多种不同的题型,例如工程问题,牛吃草问题等等。每种题型都需要不同的思考方式和解决方法,因此难度也会有所不同。我们可以根据应用题的题型进行分类,然后使用对各大权威网站的有关题型难度的数据统计与处理,对应用题难度进行量化评估。
对于问题三,我们针对相似度与难度两种分类情况,基于问题一与问题二所得到的两种不同结果形式采取针对性的分类算法。对于按相似度分类,我们采用 AGNES 算法进行分类;对于按难度分类,我们采用 K-means 算法进行分类。同时我们进行两类算法的评估,并讨论其是否能适用于更大规模的数据集。
对于问题四,我们考虑将附件 2 中的 10 个应用题加入问题一的相似性度量模型,与附件 1中的 100 个应用题共同进行相似性度量,对于输出的相似性度量结果再进行进一步的分析总结。
模型的建立与求解整体论文缩略图
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:(代码和文档not free)
1 # −∗− coding : utf −8 −∗−
2 import j i e b a
3 import j i e b a . analyse
4 import numpy
5 import numpy as np
6 import pandas as pd
7 import openpyxl as op
8 import xlwt
9 import math
10
11
12 c l a s s SimHash ( object ) :
13 def simHash ( s e l f , content ) :
14 seg = j i e b a . cut ( content )
15 j i e b a . analyse . set_stop_words ( ’ stopwords . txt ’ )
16 keyWords = j i e b a . analyse . extract_tags ( ” | ” . j o i n ( seg ) , topK=10,
withWeight=True )
17 # print ( keyWords)
18 keyList = [ ]
19 f o r feature , weight in keyWords :
20 # weight = math . c e i l ( weight )
21 weight = i n t ( weight ∗ 10) + 1
22 # print ( ’ weight : { } ’ . format ( weight ) )
23 b i n s t r = s e l f . string_hash ( f e a t u r e )
24 temp = [ ]
25 f o r c in b i n s t r :
26 i f ( c == ’ 1 ’ ) :
27 temp . append ( weight )
28 e l s e :
29 temp . append(−weight )
30 keyList . append ( temp )
31 listSum = np .sum(np . array ( keyList ) , a x i s =0)
32 # print ( listSum )
33 i f ( keyList == [ ] ) :
34 return ’ 00 ’
35 simhash = ’ ’
36 f o r i in listSum :
37 i f ( i > 0) :
38 simhash = simhash + ’ 1 ’
39 e l s e :
40 simhash = simhash + ’ 0 ’
41
42 return simhash
43
44 def string_hash ( s e l f , source ) :
45 i f source == ” ” :
46 return 0
47 e l s e :
48 x = ord ( source [ 0 ] ) << 7
49 m = 1000003
50 mask = 2 ∗∗ 128 − 1
51 f o r c in source :
52 x = ( ( x ∗ m) ^ ord ( c ) ) & mask
53 x ^= len ( source )
54 i f x == −1:
55 x = −2
56 x = bin ( x ) . r e p l a c e ( ’ 0b ’ , ’ ’ ) . z f i l l (64) [ −64:]
57 # print ( ’ strint_hash : %s , %s ’ % ( source , x ) )
58
59 return s t r ( x )
60
61 def getDistance ( s e l f , hashstr1 , hashstr2 ) :
62 ’ ’ ’
63 计 算 两 个 simhash 的 汉 明 距 离
64 ’ ’
65 length = 0
66 f o r index , char in enumerate ( hashstr1 ) :
67 i f char == hashstr2 [ index ] :
68 continue
69 e l s e :
70 length += 1
71
72 return length
73
74
75 i f __name__ == ’__main__ ’ :
76 simhash = SimHash ( )
77 f i l e = pd . read_excel ( ” t a g s i m i l a r . xlsx ” )
78 questions = pd . read_excel ( ” question . xlsx ” )
79 mid5 = xlwt . Workbook( encoding=’ utf −8 ’ , style_compression =0)
80 sheet = mid5 . add_sheet ( ’ Sheet ’ , cell_overwrite_ok=True )
81
82 f o r i in range (1 , 101) :
83 sheet . write ( i , 0 , i )
84 sheet . write (0 , 0 , ’INDEX ’ )
85 sheet . write (0 , 1 , ’SUBJECT ’ )
86 sheet . write (0 , 2 , ’SIMILARITY ’ )
87
88 text_w = 10
89 pic_w = 2
90 typ_w = 15
91 bac_w = 5
92
93 pic_stand = 1 / (math . s qr t (14028) )
94 typ_stand = 1 / (math . sq rt (6339) )
95 bac_stand = 1 / (math . sqr t (8085) )
96
97 t a r g e t = i n t ( input ( ”请 输 入 需 要 检 测 相 似 度 的 题 号: ” ) )
98
99 s t r 1 = questions . values [ target − 1 ] [ 1 ] . r e p l a c e ( ”\n” , ” ” ) . r e p l a c e ( ”\ t ” , ” ” ) .
r e p l a c e ( ” ” , ” ” ) # 被 测 题 目
100 pic = questions . values [ target − 1 ] [ 2 ]
101 typ = questions . values [ target − 1 ] [ 3 ]
102 bac = questions . values [ target − 1 ] [ 4 ]
103
104 # s i m i l a r i t y = np . zeros ((100 , 100) , f l o a t )
105 # print ( s i m i l a r i t y [ 9 9 ] [ 9 9 ] )
106
107 f o r i in range (0 , 100) :
108 s t r 2 = f i l e . values [ i ] [ 1 ] . r e p l a c e ( ”\ r ” , ” ” ) . r e p l a c e ( ”\n” , ” ” ) . r e p l a c e ( ”\
t ” , ” ” ) . r e p l a c e ( ” ” , ” ” ) # 竖 行 题 目
109 sheet . write ( i +1, 1 , s t r 2 )
110
111 # print ( s t r 2 )
112 # print(”=========”)
113
114 s1 = simhash . simHash ( s t r 1 )
115 s2 = simhash . simHash ( s t r 2 )
116 text_num = (64−simhash . getDistance ( s1 , s2 ) ) /64/6
117
118 i f f i l e . values [ i ] [ 2 ] == pic :
119 pic_num = pic_stand ∗ 2
120 e l s e :
121 pic_num = pic_stand
122
123 i f f i l e . values [ i ] [ 3 ] == typ :
124 typ_num = pic_stand ∗ 2
125 e l s e :
126 typ_num = pic_stand
127
128 i f f i l e . values [ i ] [ 4 ] == bac :
129 bac_num = bac_stand ∗ 2
130 e l s e :
131 bac_num = bac_stand
132
133 s i m i l a r i t y = text_num ∗ text_w + pic_num ∗ pic_w + \
134 typ_num ∗ typ_w + bac_num ∗ bac_w
135
136 sheet . write ( i +1, 2 , s i m i l a r i t y )
137
138 print ( ”您 要 查 找 与 该 题 相 似 的 题 目: ” )
139 print ( s t r 1 )
140 print ( ”−−−−−−−−−−−−−−−−−−−−−−−−−−−−” )
141 print ( ”查 询 成 功, 请 查 看 文 件 Search_result . x l s !” )
142 print ( ”−−−−−−−−−−−−−−−−−−−−−−−−−−−−” )
143 save_path = ” Search_result . x l s ”
144 mid5 . save ( save_path )