想法

1
2
3
1. 首先确定从0到1的产出具体步骤是怎么样的,也就是他的生命周期是怎么样的,时间安排是怎么样的
2. 明白毕设项目的背景是什么,提供了哪些帮助解决了现实当中的什么问题?
3. 感觉可以结合科大讯飞的AIMind知识图谱来做

ToDo

1
2
1. 收集研究生入学考试历年试题数据
2.

提纲

面向研究生入学考试英语试题数据分析的可视系统设计与实现

随着研究生入学考试的日益竞争激烈,对英语试题的数据分析成为了提高教学质量和帮助考生备考的关键。本课题旨在设计并实现一个面向研究生入学考试英语试题数据分析的可视系统,
通过数据可视化手段帮助教育机构和考生深入了解考试趋势、知识点覆盖情况等信息。课题的设计目标包括:
(1)数据收集与整理: 开发数据收集模块,从研究生入学英语考试的历年试题中抽取相关数据,并进行整理和标准化。
(2)知识点分析: 进行试题中涉及的各个知识点的分析,包括知识点的覆盖频率、考察难度等信息。
(3)趋势分析: 通过时间序列分析,揭示考试题型和难度的变化趋势,帮助教育机构更好地调整教学方向。
(4)个体表现: 提供考生个体成绩分析,支持对每个考生在不同知识点上的表现进行深入挖掘。
(5)可视化报告:设计直观的可视化报告,以图表和图形的形式呈现分析结果,使用户能够迅速理解和利用数据

数据收集与整理

  1. 首先,确定数据来源,例如研究生入学英语考试的历年真题。
  2. 利用网络爬虫技术或手动方式收集历年真题,并将其存储在数据库中。
  3. 对收集到的数据进行清洗、去重和标准化,以便后续分析。

知识点分析

  1. 定义知识点分类体系,如词汇、语法、阅读理解、写作等。

词频分析

整体思路:
1
2
3
4
5
首先读取docx文件并获得docx文件列表
获取词干列表
申请有道翻译开发者并获得apiKey等参数
获取带翻译的键值对列表
将数据存储到Excel当中
文件结构:

word版

​ – docx文件

词频提取.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from docx import Document
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import re
from nltk.stem import PorterStemmer
from nltk.stem.lancaster import LancasterStemmer
from nltk.stem.snowball import SnowballStemmer
from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet
import collections
import uuid
import requests
import hashlib
import time
import json
interpunctuations = [',', '.', ':', ';', '?', '(', ')', '[', ']', '&', '!', '*', '@', '#', '$', '%', '_', '-', '—', '"', '“', '”', "'"]

stops = set(stopwords.words("english"))
docxs1 = [Document('./word版/'+str(year)+'年考研英语一真题.docx') for year in range(2018, 2021)]
def get_words(docxs): # 输入文件名列表,输出单词列表(去标点数字符号,题目要求标题)
words = [] # 储存单词
for doc in docxs: # 遍历每一个文件
for para in doc.paragraphs: # 遍历文件中的每一个段落
if len(para.runs)>=1 and len(para.text)>=1: # 确实是有效段落
if para.runs[0].font.bold or para.runs[0].font.italic: # 如果是粗体或者斜体,不处理
continue
# s = re.sub(r'[.*?]', ' ', para.text)
s = re.sub(r'[[A-Z]+]', ' ', para.text) # 去掉特殊符号
s = re.sub(r'[0-9]+', ' ', s)
s = re.sub(r'②|③|①|④|⑤|⑥|⑦|⑧|⑨|⑩|⑪|⑫|⑬|⑭|⑮|⑯|⑰|_|—|-|\.', ' ', s)
s = re.sub(r'\[0-9a-z]', ' ', s)
# print(s)
s_words = word_tokenize(s) # 分词

# print(s_words)
cutwords = [word for word in s_words if word not in interpunctuations]
cutwords = [word.lower() for word in cutwords if word not in stops] # 去除停用词与标点
if cutwords:
if cutwords[0] == 'read' or cutwords[0] == 'translate': # 有的翻译和阅读题目介绍没有粗体和斜体
continue
words+=cutwords
return words
def get_wordnet_pos(tag): # 词性转化翻译
if tag.startswith('J'):
return wordnet.ADJ
elif tag.startswith('V'):
return wordnet.VERB
elif tag.startswith('N'):
return wordnet.NOUN
elif tag.startswith('R'):
return wordnet.ADV
else:
return ''
def get_stems(words): # 获得词干
lem = WordNetLemmatizer() # 词形还原
words_tag = nltk.pos_tag(words)
words_final = []
for couple in words_tag:
if couple[0][0]<'a' or couple[0][0]>'z' or len(couple[0])<=1: # 去除非单词及空格
continue
if get_wordnet_pos(couple[1]):
words_final.append(lem.lemmatize(couple[0], get_wordnet_pos(couple[1])))
else:
words_final.append(lem.lemmatize(couple[0]))
return(words_final)
# APPID 与 秘钥
appid = '****'
secretKey = '********'
myurl = 'https://openapi.youdao.com/api'

def encrypt(signStr):
hash_algorithm = hashlib.sha256()
hash_algorithm.update(signStr.encode('utf-8'))
return hash_algorithm.hexdigest()

def translate(q):

# 将key设置为字典,填写参照文档
data = {}
data['from'] = 'en'
data['to'] = 'zh-CHS'
data['signType'] = 'v3'
curtime = str(int(time.time()))
data['curtime'] = curtime
salt = str(uuid.uuid1())
signStr = appid + q + salt + curtime + secretKey
sign = encrypt(signStr)
sign = encrypt(signStr)
data['appKey'] = appid
data['q'] = q
data['salt'] = salt
data['sign'] = sign
headers = {'Content-Type': 'application/x-www-form-urlencoded'}

# 使用requests的post获取
response = requests.post(myurl, data=data, headers=headers)
# print(response.content)

# 对response的内容解码
result_all = response.content.decode("utf-8")
# 转换为json形式
result = json.loads(result_all)
if 'basic' in result:
return result['basic']['explains']
else:
return '释义错误'
def translate_alls(coun):
ans = {}
for k,v in coun.items():
trans = translate(k)
ans[k] = [v, trans]
return ans
if __name__ == '__main__':
words_1 = get_words(docxs1) # 由文件获得分词列表
words_final_1 = get_stems(words_1) # 获得词干列表
coun_1 = dict(collections.Counter(words_final_1).most_common()) # 进行统计
print(coun_1)
# ans_1 = translate_alls(coun_1) # 调用API获得翻译+词频字典

结果截图展示:

image-20231217233315614

遇到的问题1:
1
ValueError: file './word版/2020年考研英语一真题.docx' is not a Word file, content type is 'application/vnd.ms-word.document.macroEnabled.main+xml'

这个报错就是docx在2007年之前的word版本创建的文件python里面的docx第三方库不支持打开

遇到的问题2:
1
2
3
  File "/usr/lib/python3.6/zipfile.py", line 1198, in _RealGetContents
raise BadZipFile("File is not a zip file")
zipfile.BadZipFile: File is not a zip file

这个代码修改一下就行

1
load_workbook("a.xlsx")----> wb = Workbook()  # 加载文件
效果展示

image-20231218184317275

缺憾:

有道翻译的API调用有些解释翻译有问题

  1. 分析每道试题所属的知识点,并统计各个知识点的覆盖频率和考察难度。

  2. 可以使用Excel或Python等工具进行数据处理和分析。

趋势分析

  1. 按照时间顺序整理试题数据,形成时间序列。
  2. 利用时间序列分析方法(如ARIMA模型)预测考试题型和难度的变化趋势。
  3. 结合可视化工具(如Matplotlib、Seaborn等)绘制趋势图,展示分析结果。

个体表现

  1. 针对每个考生,统计其在不同知识点上的正确率、得分等指标。
  2. 利用聚类、分类等机器学习算法对考生进行分组,分析不同组别在知识点上的表现。
  3. 可使用Python的scikit-learn库进行算法实现。

可视化报告

设计简洁明了的报表模板,包括以下部分:

  1. 概述:简要介绍分析目的、数据来源和分析方法。
  2. 知识点覆盖情况:列出各知识点的覆盖频率和考察难度。
  3. 趋势分析:展示时间序列分析和预测结果。
  4. 考生个体表现:展示不同考生在知识点上的表现差异。
  5. 使用Python的echarts等库生成可视化报告。

相关文档:

1
2
3
4
5
6
https://blog.csdn.net/wardseptember/article/details/82015147
https://zhuanlan.zhihu.com/p/400688428
https://blog.csdn.net/qq_38463737/article/details/111387831
--------------------------------------------------------------
https://blog.csdn.net/Be_racle/article/details/128961533 主题提取
https://zhuanlan.zhihu.com/p/76636216

第三周

要求:

学习自然语言处理中的话题建模算法,对每一年的试题文本进行话题提取

什么是主题模型?

主题模型(Topic Model)是通过学习一系列的文档,发现抽象主题的一种统计模型。从词频的角度来讲,如果一篇文章包含某个主题,那么一定存在一些特定的词语会频繁出现。通常情况下,一篇文章中包含多个主题,而且每个主题所占的比例各不相同。

比如:“美国对伊朗再度实施单边制裁,这将对伊朗的出口贸易造成严重影响”。这里可以归为政治主题,因为描述国家的词语频繁出现。也可以归为经济主题,因为出现了制裁、出口贸易等词。我们可以预估一下,政治主题的比例为 0.7,经济主题的比例为 0.3。

主题模型是对文本中隐含主题的一种建模方法,每个主题其实是词表上词语的概率分布。主题模型是一种生成模型,一篇文章中每个词都是通过“以一定概率选择某个主题,并从这个主题中以一定概率选择某个词语”这样一个过程得到的。

比如,我们写文章一般先选定一个主题,然后用和这个主题有关的词语进行组合形成文章。

LDA 主题模型

LDA 是一种无监督学习方法,在训练时不需要手工标注的训练集,需要的仅仅是文档集以及指定主题的数量 k 即可。此外,LDA 的另一个优点是,对于每一个主题均可找出一些词语来描述它。

LDA实现原理

通过文档集生成主题集,通过主题集生成词语

code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from gensim import corpora, models, similarities
import gensim
import re
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

def process_articles(text):
text = text.lower()
text = text.replace('【', '')
text = text.replace('】', '')
text = text.replace('《', '')
text = text.replace('》', '')
text = re.sub('[\u4e00-\u9fa5]', ' ', text) #英文文档竟然出现了汉字,也是醉了
text = re.sub(r'/', ' ', text)
text = re.sub(r'//', ' ', text)
text = re.sub(r'\\', ' ', text)
text = re.sub(r'\\\\', ' ', text)
text = re.sub(r'-', ' ', text) #把 "-" 的两个单词分开(比如:july-edu ==> july edu)
text = re.sub(r'--', ' ', text)
text = re.sub(r'—', ' ', text)
text = re.sub(r'\d+', '', text) #去掉数字
words = word_tokenize(text)
english_stopwords = stopwords.words('english')
addition_stopwords = ['\'re', '\'s', '\'t', '\'m', '\'ll', '\'ve', '\'d', 'n\'t']
english_punctuations = [',', '.', ':', ';', '?', '(', ')', '[', ']', '&', '!', '*', '@', '#', '$', '%', '-',
'..', '...', '......', '|', '``', '\'', '\'\'', '<', '>', '~', '+', '/', '//', '"']

filter_words = [w for w in words if (w not in english_stopwords)]
filter_words = [w for w in filter_words if (w not in addition_stopwords)]
filter_words = [w for w in filter_words if (w not in english_punctuations)]

result = []
for filter_word in filter_words:
pattern = re.compile('.*[0-9]+.*') #用正则过滤后还是出现了数字,再过滤一次
match = pattern.findall(filter_word)

# 关于网址和邮箱的写法,不同文档也是五花八门,无奈写不出一个好的正则,只能在这里过滤掉
if ('www' not in filter_word and '.com' not in filter_word and '@' not in filter_word and len(
filter_word) > 1 and not match):
result.append(filter_word)

return result
def mark_title_distribute():
#对每篇文档,标记主题分布
with open(output_file_path, 'w', encoding='utf-8') as f:
for i in range(len(titles)):
f.write(titles[i])
topic_pro = lda.get_document_topics(corpus[i])
f.write(str(topic_pro) + '\n')
f.close()
def Merge_title_content():
#在保存语料时,我的做法是一行标题,一行内容。因此在取出时,需要将标题和内容合起来作为一篇文档
i = 1
for line in data_file.readlines():
if i % 2 == 1:
titles.append(line)
title = process_articles(line)
texts.append(title)
elif i % 2 == 0:
body = process_articles(line)
index = int(i / 2 - 1)
texts[index] = texts[index] + body
i = i + 1
data_file.close()
if __name__ == '__main__':
data_file_path = 'd:/2023.txt'
output_file_path = 'd:/output.txt'
data_file = open(data_file_path, encoding='utf-8')
texts = []
titles = []
Merge_title_content()
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts] #词频统计

lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=10) #模型训练,这里预定义20个主题

print(lda.print_topics(num_topics=10, num_words=10))
mark_title_distribute()
输出

image-20231230172949770

引用文章

[1] 王祖超, 袁晓如. 轨迹数据可视分析研究[J]. 计算机辅助设计与图形学学报, 2015, 27(1): 9-25.
[2] 刘明吉, 王秀峰. 数据挖掘中的数据预处理[J]. 计算机科学, 2000, 27(4): 54-57.
[3] 周水庚, 李丰, 陶宇飞, 等. 面向数据库应用的隐私保护研究综述[J]. 计算机学报, 2009, 32(5): 847-861.
[4] 徐宝文, 张卫丰. 数据挖掘技术在 Web 预取中的应用研究[J]. 计算机学报, 2001, 24(4): 430-436.
[5] 周庆, 牟超, 杨丹. 教育数据挖掘研究进展综述[J]. 软件学报, 2015, 26(11): 3026-3042.
[6] Souri A, Hosseini R. A state-of-the-art survey of malware detection approaches using data mining techniques[J]. Human-centric Computing and Information Sciences, 2018, 8(1): 1-22.
[7] Hasan M K, Ghazal T M, Alkhalifah A, et al. Fischer linear discrimination and quadratic discrimination analysis–based data mining technique for internet of things framework for Healthcare[J]. Frontiers in Public Health, 2021, 9: 737149.
[8] Lin G, Zhang J, Luo W, et al. Software vulnerability discovery via learning multi-domain knowledge bases[J]. IEEE Transactions on Dependable and Secure Computing, 2019, 18(5): 2469-2485.
[9] Eckhart M, Ekelhart A, Weippl E. Automated security risk identification using AutomationML-based engineering data[J]. IEEE Transactions on Dependable and Secure Computing, 2020, 19(3): 1655-1672.
[10] Luo Y, Qin X, Tang N, et al. Deepeye: Towards automatic data visualization[C]//2018 IEEE 34th international conference on data engineering (ICDE). IEEE, 2018: 101-112.

第四周

主题建模出结果;调研story telling可视化,下载代码跑一个示例

story telling代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.palettes import Category20_20
import pandas as pd

# 创建一个简单的数据集
data = {
'Year': [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019],
'Sales': [5, 8, 12, 15, 20, 18, 25, 30, 28, 35],
'Profit': [1, 2, 3, 5, 8, 7, 10, 12, 11, 15]
}

df = pd.DataFrame(data)

# 创建ColumnDataSource对象
source = ColumnDataSource(df)

# 创建绘图对象
p = figure(title="Sales and Profit Over Years", x_axis_label='Year', y_axis_label='Amount')

# 绘制线条
p.line(x='Year', y='Sales', line_width=2, legend_label='Sales', line_color=Category20_20[0], source=source)
p.line(x='Year', y='Profit', line_width=2, legend_label='Profit', line_color=Category20_20[2], source=source)

# 添加悬停工具
hover = HoverTool()
hover.tooltips = [('Year', '@Year'), ('Sales', '@Sales'), ('Profit', '@Profit')]
p.add_tools(hover)

# 显示图表
show(p)

效果展示

image-20240104214635122