news 2026/10/1 8:51:57

机器学习试卷自动化批改与知识图谱构建实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
机器学习试卷自动化批改与知识图谱构建实践

简介:本资源是一份面向高校计算机、人工智能及相关专业本科生的机器学习课程期末复习试卷,聚焦核心知识点梳理与应试能力提升。试卷内容系统覆盖机器学习基本概念(监督/无监督/半监督学习)、主流算法(逻辑回归、决策树、SVM、K-Means、PCA等)、模型评估指标(准确率、精确率、召回率、F1-score、ROC曲线)及模型选择方法(交叉验证、网格搜索),并延伸至图像识别、NLP、推荐系统等典型应用场景与深度学习、迁移学习等前沿趋势。资源为单个Word文档(.doc格式),文件大小137KB,结构清晰、排版规范,便于打印复习或电子查阅。目前已有6076人学习下载,适合考前系统回顾知识脉络、检验理解深度、查漏补缺,尤其适合作为课堂笔记补充与模拟自测材料。

1. 这不是一份普通 Word 试卷:它是一份可复用、可批改、可追溯的机器学习知识验证资产

“机器学习期末复习试卷.doc”——看到这个标题,很多人第一反应是:又一份考前突击资料?但如果你正在带课、出题、做教学评估,或者正被学生问“到底该学什么才算真懂机器学习”,这份文档就远不止是 PDF 打印件那么简单。它本质是一套结构化知识校验框架:覆盖监督/无监督学习边界、模型评估陷阱(比如混淆矩阵 vs. PR 曲线在不平衡数据下的误导性)、超参调试的实操逻辑(为什么 GridSearch 在树模型上常不如 RandomizedSearch)、以及最容易被忽略的工程落地约束(如推理延迟对部署选型的决定性影响)。我见过太多团队把“能跑通 sklearn 示例”当成掌握机器学习,结果在真实数据清洗阶段卡两周——而这恰恰是这份试卷里第 3 大题“数据预处理链路设计”的考点。它适合三类人:高校教师快速生成带评分标准的闭环考题;自学者用答案反推知识盲区(比如第 7 题要求手写梯度下降更新公式,但必须标注 learning_rate 衰减策略);还有 MLOps 工程师,把其中“模型监控指标设计”部分直接拆进 CI/CD 流水线。别把它当练习册,它是你检验“机器学习是否真正落地”的最小可行标尺。

2. 把 Word 试卷变成可执行知识验证工具:从静态文档到动态评估流水线

2.1 为什么不能直接打印?——解析试卷隐含的三层知识结构

这份.doc文件表面是文字+公式+图表,但实际承载着机器学习教学中三个不可割裂的层次:概念层(如第 2 题区分 bias-variance tradeoff 与 overfitting 的数学定义)、操作层(如第 5 题要求用 pandas 实现缺失值插补并说明 KNNImputer 与 IterativeImputer 的适用场景差异)、决策层(如第 9 题给出线上服务 SLA 要求,让考生选择模型压缩方案并量化精度-延迟权衡)。如果只当 Word 文档处理,这三层会坍缩成纯记忆题。我的做法是:先用python-docx库解析文档结构,提取所有题目编号、题干、分值、参考答案关键词(注意:不是完整答案,而是判分锚点,如“需写出 ROC-AUC 计算公式中的 TP/FP/FN/TN 定义”),再映射到知识图谱节点。例如,“第 4 题:比较 SVM 与 Logistic Regression 在高维稀疏文本特征上的表现”会被打标为<SVM><LogisticRegression><文本分类><高维稀疏>四个实体,并关联到 scikit-learn 官方文档对应章节的 URL。这样做的好处是,当学生答错时,系统能精准推送“SVM 核函数选择指南”而非泛泛的“机器学习入门”。

from docx import Document import re def parse_exam_doc(doc_path): doc = Document(doc_path) questions = [] current_q_num = None current_content = "" for para in doc.paragraphs: # 匹配题号格式:如 "1."、"(2)"、"二、" q_match = re.match(r'^(\d+\.|(\d+)|[\u4e00-\u9fff]+、)', para.text.strip()) if q_match: # 保存上一题 if current_q_num and current_content.strip(): questions.append({ 'number': current_q_num, 'content': current_content.strip(), 'score': extract_score(current_content) # 自定义函数提取分值 }) # 新题开始 current_q_num = para.text.strip().split('、')[0].strip() if '、' in para.text else q_match.group(0) current_content = para.text.strip() else: current_content += "\n" + para.text.strip() # 处理最后一题 if current_q_num and current_content.strip(): questions.append({ 'number': current_q_num, 'content': current_content.strip(), 'score': extract_score(current_content) }) return questions # 示例:提取分值(常见格式:"(5分)"、"【3分】") def extract_score(text): score_match = re.search(r'[((]([0-9]+)[分)]', text) return int(score_match.group(1)) if score_match else 0

提示:python-docx只能读取.docx,若原始文件是.doc(旧版 Word),必须先用 LibreOffice 或pandoc转换:pandoc input.doc -o output.docx。直接用win32com调用 Word COM 接口虽能读.doc,但在 Linux 服务器上不可行,教学环境应优先保证跨平台兼容性。

2.2 构建可验证答案库:用代码替代人工阅卷的 3 个关键锚点

人工批改机器学习试卷最大的痛点是主观题判分不一致。比如第 6 题“设计一个异常检测 pipeline”,不同老师可能对“是否必须包含特征重要性分析”有分歧。解决方案是:将参考答案拆解为可执行验证点。我们定义三个强制锚点:①代码可运行性(提交的 Python 脚本能否在指定数据集上完成训练+预测);②逻辑完整性(是否包含数据加载→预处理→模型选择→评估→解释的全链路);③约束满足度(如题目要求“使用孤立森林且 n_estimators ≥ 100”,则需静态解析代码中IsolationForest(n_estimators=...)参数)。下面是一个验证第 8 题(手写反向传播)的最小检查脚本:

import ast import numpy as np def validate_bp_code(code_str): """ 检查学生提交的反向传播代码是否包含核心要素: - 至少一个矩阵乘法(np.dot 或 @) - 激活函数导数计算(如 sigmoid_derivative) - 权重更新语句(包含 learning_rate 和梯度) """ try: tree = ast.parse(code_str) except SyntaxError: return False, "代码语法错误" # 检查是否调用 np.dot 或 @ 运算符 has_matmul = False has_derivative = False has_weight_update = False for node in ast.walk(tree): if isinstance(node, ast.Call) and hasattr(node.func, 'id'): if node.func.id in ['dot', 'matmul'] or (hasattr(node.func, 'attr') and node.func.attr == 'dot'): has_matmul = True elif isinstance(node, ast.BinOp) and isinstance(node.op, (ast.MatMult, ast.Mult)): has_matmul = True elif isinstance(node, ast.Assign): # 检查权重更新:w = w - lr * grad for target in node.targets: if isinstance(target, ast.Name) and target.id.endswith('_weights'): has_weight_update = True # 检查导数计算(简单模式匹配,实际项目中用更严谨的 AST 分析) if re.search(r'derivative|grad|d_.*?|backward', code_str): has_derivative = True missing = [] if not has_matmul: missing.append("缺少矩阵运算") if not has_derivative: missing.append("缺少梯度计算") if not has_weight_update: missing.append("缺少权重更新") return len(missing) == 0, "、".join(missing) if missing else "通过" # 示例调用 student_code = """ def sigmoid_derivative(x): return x * (1 - x) # 前向传播省略... # 反向传播 dZ2 = A2 - Y dW2 = np.dot(A1.T, dZ2) / m W2 = W2 - 0.01 * dW2 """ is_valid, msg = validate_bp_code(student_code) print(f"验证结果:{msg}") # 输出:验证结果:通过

这段代码的核心价值不在技术复杂度,而在于把模糊的教学要求转化为可量化的代码特征。它不判断学生是否“理解”反向传播,只确认其代码是否具备该算法的骨架。这种思路可直接迁移到其他题型:对聚类题,检查是否调用sklearn.cluster下的类;对评估题,检查是否计算了f1_score而非仅accuracy。

2.3 将试卷题干转为自动化测试用例:以第 3 题为例的完整链路

第 3 题:“给定一个含 10% 缺失值的信用卡交易数据集(字段:amount, time, is_fraud),设计完整的预处理流程”。这道题的标准答案通常包含:缺失值填充(用中位数或 KNN)、时间特征工程(提取小时、星期几)、类别编码(one-hot)、目标变量平衡(SMOTE)。我们可以把这个题干直接生成 pytest 测试用例:

# test_preprocessing.py import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler from imblearn.over_sampling import SMOTE def test_preprocessing_pipeline(): # 模拟题目数据集 np.random.seed(42) df = pd.DataFrame({ 'amount': np.random.exponential(100, 1000), 'time': np.random.randint(0, 86400, 1000), # 秒级时间戳 'is_fraud': np.random.binomial(1, 0.05, 1000) # 5% fraud rate }) # 注入 10% 缺失值 missing_idx = np.random.choice(df.index, size=int(0.1*len(df)), replace=False) df.loc[missing_idx, 'amount'] = np.nan # 学生实现的预处理函数(需在 student_solution.py 中定义) from student_solution import preprocess_credit_data processed_df, y = preprocess_credit_data(df) # 验证点 1:缺失值已填充(检查是否还有 NaN) assert not processed_df.isnull().any().any(), "缺失值未处理" # 验证点 2:时间特征已提取(必须包含 hour 和 day_of_week) assert 'hour' in processed_df.columns, "缺少 hour 特征" assert 'day_of_week' in processed_df.columns, "缺少 day_of_week 特征" # 验证点 3:目标变量已平衡(fraud 样本数应接近非 fraud) fraud_ratio = y.mean() assert 0.4 <= fraud_ratio <= 0.6, f"SMOTE 平衡失败,fraud 比例为 {fraud_ratio:.3f}" # 验证点 4:数值特征已标准化(检查 std ≈ 1) numeric_cols = processed_df.select_dtypes(include=[np.number]).columns assert np.allclose(processed_df[numeric_cols].std(), 1, atol=0.1), "数值特征未标准化"

运行pytest test_preprocessing.py -v即可自动判分。这种做法把“设计流程”从纸上谈兵变成可验证行为,学生提交代码后,系统返回具体失败项(如“缺少 hour 特征”),比“扣 2 分”更有教学价值。更重要的是,这套测试用例可直接复用到真实项目中——我们团队就曾把期末试卷的第 3 题测试用例,稍作修改后嵌入到生产环境的数据质量监控脚本里。

3. 避坑:机器学习试卷解析与自动化批改的 5 个血泪经验

3.1 现象:Word 公式解析失败,LaTeX 公式变成乱码

原因:python-docx无法解析 Word 内嵌的 OMML(Office Math Markup Language)公式,会将其读作不可见字符或空字符串。尤其当试卷中出现 $\frac{\partial L}{\partial w}$ 这类偏导公式时,题干关键信息直接丢失。
解决:在解析前用 LibreOffice headless 模式将.docx转为 PDF,再用pdfplumber提取文本(保留公式位置),最后用latex2mathml库将 PDF 中的 LaTeX 片段还原。实操命令:

libreoffice --headless --convert-to pdf "machine_learning_exam.docx"

然后在 Python 中:

import pdfplumber with pdfplumber.open("machine_learning_exam.pdf") as pdf: page = pdf.pages[0] # 提取文本(公式区域会显示为占位符,但位置可定位) text = page.extract_text() # 用正则匹配 LaTeX 公式片段:\$...\$ 或 $$...$$ latex_matches = re.findall(r'\$(.*?)\$', text, re.DOTALL)

3.2 现象:学生代码能运行但逻辑错误,自动化测试误判为通过

原因:第 7 题要求“用交叉验证选择最优 K 值”,学生可能写KNeighborsClassifier(n_neighbors=5)硬编码 K=5,绕过 CV 流程。我们的测试只检查cross_val_score是否被调用,但没验证是否真的用了网格搜索。
解决:在 AST 解析中增加控制流检查。不仅要找cross_val_score调用,还要确认其cv参数是否为GridSearchCV实例,且param_grid包含'n_neighbors'键:

def check_cv_usage(tree): for node in ast.walk(tree): if isinstance(node, ast.Call) and hasattr(node.func, 'id'): if node.func.id == 'cross_val_score': # 检查 cv 参数是否为 GridSearchCV for kw in node.keywords: if kw.arg == 'cv': if isinstance(kw.value, ast.Call) and hasattr(kw.value.func, 'id'): if kw.value.func.id == 'GridSearchCV': # 检查 param_grid 是否含 n_neighbors for arg in kw.value.args: if isinstance(arg, ast.Dict): keys = [k.s for k in arg.keys if isinstance(k, ast.Str)] if 'n_neighbors' in keys: return True return False

3.3 现象:多选题判分不准,学生选了部分正确选项却被判零分

原因:第 1 题是多选题:“以下哪些是防止过拟合的方法?A. Dropout B. Batch Normalization C. 增加训练数据 D. 减少网络层数”。标准答案是 A、C、D,但学生只选了 A 和 C。传统判分按“全对才给分”,忽略了部分正确性。
解决:采用比例计分法。定义每个选项的权重(如 A=0.4, C=0.4, D=0.2),学生每选对一个得对应权重分,选错倒扣 0.1 分(防乱猜)。实现时用字典映射:

MCQ_WEIGHTS = { 'A': 0.4, 'B': 0.0, 'C': 0.4, 'D': 0.2 # B 是干扰项,权重为 0 } def score_mcq(student_choices, correct_choices): score = 0.0 for choice in student_choices: if choice in correct_choices: score += MCQ_WEIGHTS.get(choice, 0) else: score -= 0.1 # 选错扣分 return max(0, score) # 不低于 0 分

3.4 现象:图像题无法自动化批改(如手绘决策树)

原因:第 10 题要求“手绘 ID3 算法生成的决策树”,学生提交扫描件 JPG。OCR 对手写体识别率低,且无法判断树结构是否正确。
解决:强制要求学生用graphviz或dtreeviz生成可解析的 DOT 文件。在试卷说明中明确:“请用 Python 生成决策树可视化,并导出为 .dot 文件提交”。这样可直接用pydot解析 DOT 结构,验证节点分裂条件、叶节点纯度等:

import pydot graph = pydot.graph_from_dot_file("tree.dot")[0] nodes = graph.get_nodes() # 检查是否至少有 3 个内部节点(符合 ID3 三层树要求) internal_nodes = [n for n in nodes if 'label' in n.get_attributes() and 'class' not in n.get_attributes()['label']] assert len(internal_nodes) >= 3, "决策树深度不足"

3.5 现象:答案关键词匹配过于宽松,导致错误答案被误判

原因:第 5 题参考答案关键词是“KNNImputer”,但学生写了“KNN 插补器”,因中文分词问题匹配失败。
解决:构建同义词映射表,用jieba分词 + 余弦相似度匹配。预先定义:

SYNONYMS = { "KNNImputer": ["KNN插补", "KNN填充", "基于K近邻的缺失值填充"], "SMOTE": ["合成少数类过采样", "SMOTE算法", "过采样技术"] } def fuzzy_match_answer(student_answer, keyword): # 用 jieba 分词 import jieba words = list(jieba.cut(student_answer)) # 检查是否包含同义词中的任意词 for syn in SYNONYMS.get(keyword, []): if any(syn_word in student_answer or syn_word in ''.join(words) for syn_word in syn.split(' ')): return True return keyword.lower() in student_answer.lower()

4. 从试卷到知识图谱:用 Neo4j 构建机器学习能力诊断网络

4.1 为什么需要知识图谱?——单题判分无法暴露能力断层

学生第 4 题(SVM vs LR)答得很好,但第 9 题(模型压缩)完全空白,这说明他掌握了理论对比,却缺乏工程落地意识。传统试卷只给总分,无法定位这种跨维度能力断层。知识图谱的价值在于:把每道题映射为“能力节点”,题与题之间的关联构成“能力路径”。例如,“第 4 题”节点连接到<SVM>、<LogisticRegression>、<高维稀疏>,而“第 9 题”连接到<模型压缩>、<TensorRT>、<量化>。当学生在第 4 题得分高、第 9 题得分为 0 时,图谱会高亮<高维稀疏>到<量化>的路径断裂——这意味着他可能不理解“稀疏模型天然适合量化”这一关键连接点。

4.2 构建图谱的 4 类核心节点与关系

我们定义以下节点类型(用 Cypher 创建):

// 创建能力节点 CREATE (:Capability {name: "SVM", category: "Algorithm", level: "Intermediate"}) CREATE (:Capability {name: "模型压缩", category: "Engineering", level: "Advanced"}) CREATE (:Capability {name: "混淆矩阵", category: "Evaluation", level: "Basic"}) // 创建题目节点 CREATE (:Question {id: "Q4", text: "比较 SVM 与 Logistic Regression...", score: 10}) // 创建关系:题目考察哪些能力 MATCH (q:Question {id: "Q4"}), (c1:Capability {name: "SVM"}), (c2:Capability {name: "LogisticRegression"}) CREATE (q)-[:TESTS]->(c1), (q)-[:TESTS]->(c2) // 创建能力依赖关系(学习路径) MATCH (c1:Capability {name: "混淆矩阵"}), (c2:Capability {name: "PR曲线"}) CREATE (c1)-[:PREREQUISITE]->(c2)

4.3 用图查询诊断学生弱点:3 个实战查询示例

查询 1:找出学生未掌握但前置能力已达标的能力(即“卡点”)

// 假设学生已掌握混淆矩阵(Q3 得分 > 8),但 PR 曲线相关题(Q7)得分为 0 MATCH (q3:Question {id: "Q3"})-[:TESTS]->(c1:Capability {name: "混淆矩阵"}) MATCH (q7:Question {id: "Q7"})-[:TESTS]->(c2:Capability {name: "PR曲线"}) WHERE q3.student_score > 8 AND q7.student_score = 0 MATCH (c1)-[:PREREQUISITE*]->(c2) RETURN c2.name AS bottleneck, c1.name AS mastered_prerequisite

结果:bottleneck: "PR曲线",mastered_prerequisite: "混淆矩阵"—— 明确指向“从混淆矩阵到 PR 曲线”的认知断层。

查询 2:推荐补救学习路径

// 找出所有依赖于 "PR曲线" 的高级能力,并按难度排序 MATCH (c:Capability)-[:PREREQUISITE*]->(target:Capability {name: "PR曲线"}) WHERE c.level IN ["Intermediate", "Advanced"] RETURN c.name, c.level ORDER BY CASE c.level WHEN "Basic" THEN 1 WHEN "Intermediate" THEN 2 ELSE 3 END DESC

查询 3:识别教学薄弱环节(全班 70% 学生在 Q7 失分,且 Q3 得分率 > 90%)

MATCH (q7:Question {id: "Q7"})-[:TESTS]->(c:Capability {name: "PR曲线"}) WITH c, COUNT(*) AS total_students MATCH (q7)-[r:HAS_SCORE]->(s:Student) WHERE r.score = 0 WITH c, COUNT(*) AS failed_count, total_students WHERE toFloat(failed_count) / total_students > 0.7 RETURN c.name AS weak_capability, failed_count, total_students

注意:Neo4j 社区版支持单机部署,但教学场景建议用 AuraDB Cloud 免费 tier(250MB 存储),避免本地维护。图谱数据从试卷解析结果自动生成,无需手动录入。

5. 终极技巧:用试卷题干生成对抗样本,反向验证教学有效性

5.1 什么是“教学对抗样本”?——不是攻击模型,而是攻击教学盲区

常规对抗样本是给图片加扰动让模型认错,而教学对抗样本是构造一道题,专门暴露学生最可能误解的概念。例如,第 2 题标准问法是“什么是 bias-variance tradeoff?”,这容易让学生背定义。我们改成:

“某模型在训练集上 MSE=0.01,在验证集上 MSE=0.8,调整正则化强度 λ 后,验证集 MSE 降至 0.3,但训练集 MSE 升至 0.15。请画出 bias-variance 分解示意图,并标出当前 λ 值对应的 bias/variance 位置。”

这道题迫使学生理解:bias-variance 不是固定值,而是随超参变化的曲线。如果学生只会背“bias 是欠拟合,variance 是过拟合”,就无法完成绘图。

5.2 自动生成对抗题的 3 步法

步骤 1:识别易错概念簇
从历史试卷数据中统计错误率最高的 TOP5 概念:

概念全班错误率典型错误
梯度消失68%认为只发生在 Sigmoid,忽略 ReLU 的 dying ReLU
ROC 曲线52%混淆 TPR/FPR 与 precision/recall
BatchNorm45%认为训练和推理时行为相同

步骤 2:设计混淆场景
针对“BatchNorm”,构造对抗场景:

“某模型在训练时 BatchNorm 开启,验证时关闭,发现验证 loss 突然升高。开发者认为这是数据分布变化导致,于是用更大 batch size 重训。请问该做法是否合理?为什么?”
这里埋了两个陷阱:① BatchNorm 在推理时默认使用 running_mean/runing_var,不是“关闭”;② 增大 batch size 会加剧训练时的统计偏差,反而恶化问题。

步骤 3:注入现实约束
在题干中加入工程细节,逼学生跳出理论:

“该模型部署在边缘设备(内存 < 1GB),BatchNorm 层参数需实时更新。请设计一种内存开销 < 10MB 的在线统计方案,并对比其与标准 BatchNorm 的精度损失。”
这题的答案不再是教科书定义,而是要权衡torch.nn.SyncBatchNorm的通信开销 vs.torch.nn.InstanceNorm的领域适应性。

5.3 用对抗题反向优化教学——我的血泪教训

去年我设计了一道对抗题:“用 PCA 降维后,为何 SVM 分类效果反而下降?” 全班 82% 的学生回答“因为 PCA 丢弃了信息”,这没错但不完整。直到我拿到学生的代码才发现:他们全用PCA(n_components=0.95)(保留 95% 方差),但没意识到——在高维稀疏文本中,前 95% 方差集中在少数几个主成分,剩余 5% 方差分散在上千维,恰恰携带类别判别信息。这个洞见让我立刻调整了 PCA 教学:不再强调“保留多少方差”,而是带学生看pca.explained_variance_ratio_的累积曲线,找到“拐点”而非固定阈值。现在我的课件里,PCA 章节永远跟着一个 Jupyter Notebook,里面预置了文本 TF-IDF 矩阵,让学生拖动滑块实时观察分类准确率变化。

希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 8:51:44

OpenHarmony NDK工具链实战:从环境配置到交叉编译调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 8:51:19

AI日报实战:Agent开发、Claude与Gemini使用及vLLM部署指南

1. 从一份日报说起&#xff1a;AI 圈的信息密度正在失控 做 AI 方向的人最近应该都有同一种体感&#xff1a;一天不刷消息&#xff0c;第二天就跟不上节奏了。模型版本号在跳&#xff0c;Agent 框架在冒&#xff0c;推理引擎的镜像 tag 一天一个样&#xff0c;昨天还能跑通的部…

作者头像 李华
网站建设 2026/10/1 8:51:09

从 ECharts 到 Power BI:数据可视化工具选型与组合打法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 8:50:47

BC.G下放electroNic引入asap:CS2阵容变阵背后的战术逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 8:50:47

TestStand界面中文本地化全攻略:从序列编辑器到自定义操作员界面

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 8:50:42

机载软件适航符合性:需求追溯、MC/DC覆盖与工具鉴定

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华