机器学习最小可行知识链:从公式到可调试代码的完整实践
简介本资源是邹博主讲的《机器学习全方位解析从基础到实践》配套教学包面向零基础入门者与希望系统夯实理论与工程能力的学习者解决机器学习概念抽象、代码实践脱节、算法调优无从下手等核心痛点。压缩包共613个文件涵盖146个Python可运行代码含线性回归、SVM、随机森林、神经网络等完整实现、47个R语言脚本用于统计建模与可视化、25个PDF课件覆盖监督/无监督学习、模型评估、实战项目如MNIST识别与文本分类及14个PNG图表素材总大小174.73MB结构清晰、即下即用。已有1330人学习下载内容深度结合Scikit-learn、TensorFlow等主流工具链并包含xgboost源码级组件如allreduce_base.cc、rabit_wrapper.cc与典型数据集flower_256.bmp、son.bmp等便于理解算法底层逻辑与工程落地细节。1. 这不是“速成课件包”而是一套能跑通、调得动、改得动的机器学习最小可行知识链你点开“邹博-机器学习全套课件及代码.zip”这个文件名时大概率正卡在三个现实困境里刚学完线性回归但面对真实数据集连缺失值怎么填都犹豫下载了几十个GitHub项目却总在pip install后报错ModuleNotFoundError或者更扎心的——课件PPT写满公式推导可当你想把“梯度下降”改成用PyTorch实现、再加个早停机制时发现连模型结构定义那行代码都看不懂。这不是你的问题。这套资源真正的价值从来不在“全”字上而在于它用极简但完整的技术链路把“概念→数学→代码→调试→验证”五个环节全部串在同一个数据流里。它不教你怎么背SVM对偶问题但会带你用50行代码从零手写逻辑回归并可视化决策边界它不堆砌10种优化器对比表但会在同一份代码里让你切换SGD/Adam并实时观察loss曲线抖动差异。适合两类人一是刚啃完《统计学习方法》前四章、急需一个“能动手的锚点”的自学者二是带学生做课程设计的某高校讲师需要一套无环境依赖、参数可调、错误可追踪的课堂演示基线。别把它当资料库要当成一台已预装好所有螺丝刀、扳手和万用表的维修工作台——拧哪颗螺丝都能立刻听见回响。2. 从解压到第一个可运行模型三步建立可信执行环境这套课件最反直觉的设计是刻意规避“一键安装”幻觉。它不提供requirements.txt一键拉取所有包因为真实项目中scikit-learn1.3.0和scikit-learn1.4.2在RandomForestClassifier的oob_score_属性返回类型上存在静默差异——这正是你调试时最头疼的“玄学bug”来源。我们选择用最小依赖集显式版本锁定来重建确定性。2.1 解压后必须做的三件事校验、隔离、降级先确认你拿到的是原始未篡改包非网盘二次压缩版# 进入下载目录检查zip完整性Linux/macOS unzip -t 邹博-机器学习全套课件及代码.zip | grep OK$ | wc -l # 正常应输出 127课件PDF代码文件总数少于125说明损坏提示Windows用户请用7-Zip右键“测试压缩文件”勿用系统自带解压工具——它会静默跳过长路径文件如code/ensemble_methods/boosting_adaboost_from_scratch.py创建独立Python环境关键避免污染主环境# 推荐conda比venv更稳定处理科学计算包 conda create -n ml_zou python3.9 conda activate ml_zou # 安装核心三件套版本严格对应课件实测环境 pip install numpy1.23.5 pandas1.5.3 scikit-learn1.2.2 # 验证运行课件根目录下的check_env.py python check_env.py # 成功输出应含✅ All packages match expected versions2.2 找到那个“能跑通”的起点linear_regression_demo.py不要从README.md开始读直接定位到code/regression/linear_regression_demo.py——这是整套课件的技术心脏起搏器。它只做三件事加载内置波士顿房价数据、用解析法求解正规方程、绘制预测值vs真实值散点图。但它的精妙在于第17行X X[:, :-1]显式剔除截距列课件强调“特征矩阵不含偏置项”第32行theta np.linalg.inv(X.T X) X.T y用纯NumPy实现正规方程避开sklearn黑匣子第45行plt.scatter(y, y_pred, alpha0.6)的alpha参数让重叠点可见教学可视化细节运行它cd code/regression python linear_regression_demo.py若看到窗口弹出散点图且R²值显示为0.742课件PPT第23页标注值说明环境完全就绪。此时你已获得一个可验证、可修改、可打断点的基准模型——后续所有算法改进如加入L2正则、改用梯度下降都将基于此文件迭代。2.3 理解课件的“代码-课件”映射逻辑为什么PPT第41页对应svm_smo.py课件PDF与代码不是松散关联而是按算法演进阶段强绑定。例如PPT页码核心内容对应代码文件关键验证点38-40SVM对偶问题推导code/classification/svm_dual_form.py运行后输出alpha向量中非零元素个数支持向量数41-44SMO算法伪代码code/classification/svm_smo.py在update_alpha_j()函数内设断点观察alpha_i,alpha_j交替更新过程45-47核技巧与高斯核实现code/classification/svm_rbf_kernel.py修改gamma0.001→gamma10观察决策边界从平滑变锯齿这种设计让你能随时在PPT公式和代码变量间跳转。比如PPT第42页的η K_{ii} K_{jj} - 2K_{ij}在svm_smo.py第89行直接对应eta K[i,i] K[j,j] - 2*K[i,j]。公式不再是纸面符号而是内存中可打印、可修改的数值。3. 把课件代码变成你的“可调试资产”重构四步法下载即用的代码只是半成品。真正提升能力的关键在于把它改造成你能掌控每个神经元的模型。我带某高校本科生做课程设计时要求他们必须完成以下四步重构否则不给成绩——因为这四步覆盖了工业界模型开发的全部基础动作。3.1 步骤一注入日志与断点让训练过程“透明化”原始logistic_regression_gd.py只在最后打印一次准确率。我们添加实时监控# 在train()函数循环内插入原文件约第65行 if i % 100 0: y_pred predict(X_train, theta) train_acc accuracy_score(y_train, y_pred) # 新增记录每100轮的loss和acc print(fEpoch {i:4d} | Loss: {loss:.6f} | Train Acc: {train_acc:.4f}) # 新增保存中间模型便于后续分析 if i % 500 0: np.save(fmodels/theta_epoch_{i}.npy, theta)参数说明accuracy_score来自sklearn.metrics但课件刻意不用它——你需自己实现def accuracy_score(y_true, y_pred): return np.mean(y_true y_pred)。这迫使你理解准确率本质是布尔数组均值而非调包魔法。3.2 步骤二参数化硬编码构建最小配置接口原始代码中学习率lr0.01、迭代次数epochs1000散落在多处。我们提取为统一配置# 新建config.py与code同级目录 class Config: LR 0.01 EPOCHS 1000 BATCH_SIZE 32 RANDOM_SEED 42 # 在logistic_regression_gd.py顶部导入 from config import Config # 替换所有硬编码 for i in range(Config.EPOCHS): lr Config.LR # ...后续代码这样只需改config.py一行就能批量测试不同学习率效果。更重要的是它教会你配置即代码的工程思维——后续扩展交叉验证、网格搜索时配置管理将成倍降低复杂度。3.3 步骤三拆分数据加载逻辑接入真实数据源课件用make_classification生成模拟数据。我们替换为真实场景# 在data_loader.py中新增 def load_bank_marketing(): 加载UCI银行营销数据集课件PPT第88页案例 url https://archive.ics.uci.edu/ml/machine-learning-databases/00222/bank-additional.zip # 自动下载解压课件未提供但PPT明确引用 # 实际代码包含requestszipfile处理此处省略细节 return X, y # 返回特征矩阵和标签向量 # 在主训练脚本中调用 X, y load_bank_marketing() X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_stateConfig.RANDOM_SEED, stratifyy )注意该数据集含分类特征如jobadmin.、缺失值educationunknown这正是课件PPT第89页强调的“真实数据预处理挑战”。你将被迫实现OneHotEncoder和SimpleImputer——而课件代码里恰好有preprocessing/one_hot_encode.py作为参考。3.4 步骤四封装为可调用函数支持Jupyter交互式调试最终目标在Jupyter中一行代码启动训练两行代码修改超参# 在notebooks/debug_demo.ipynb中 from logistic_regression_gd import train_logistic_regression # 一行启动使用默认配置 model, history train_logistic_regression() # 两行修改超参无需改源码 model, history train_logistic_regression( lr0.005, epochs2000 ) # 可视化loss曲线 plt.plot(history[loss]) plt.title(fLoss Curve (lr{model.lr}))这要求你重构train_logistic_regression()函数使其返回model对象含theta、lr等属性和history字典含loss、acc列表。当代码能被当作函数调用时你就拥有了调试的主动权——而不是每次改参数都要重新运行整个脚本。4. 避坑指南那些让初学者卡住3小时以上的5个具体陷阱这套课件的威力与陷阱并存。我带过的23个学生中19人曾因以下问题中断超过2小时。这里不讲原理只列现象、原因、解决——你遇到时直接CtrlF搜索即可。4.1 现象svm_smo.py运行后支持向量数为0决策边界是条直线原因PPT第43页公式(7)中C1.0是软间隔惩罚系数但代码里C0.1课件为演示效果故意设小。当C过小时SMO算法认为“容忍更多误分类比增加模型复杂度更划算”导致所有alpha趋近于0。解决打开svm_smo.py找到C 0.1改为C 1.0或C 10.0重新运行。观察print(len(alphas[alphas 1e-5]))输出值从0变为5。4.2 现象kmeans_manual.py聚类结果每次运行都不一样原因KMeans对初始质心敏感课件代码用np.random.rand()随机初始化PPT第65页未强调随机种子。解决在kmeans_manual.py开头添加np.random.seed(42)并在init_centroids()函数第一行加入np.random.seed(seed)参数传递。课件PPT第66页“稳定性分析”章节实际暗示了此操作。4.3 现象pca_demo.py降维后可视化图形是空白原因课件用matplotlib.pyplot绘图但未调用plt.show()PPT第72页截图是Jupyter自动显示非脚本模式。解决在文件末尾添加plt.show()。更佳方案在config.py中添加PLOT_BACKEND inline并在主脚本开头加import matplotlib; matplotlib.use(Agg)以兼容服务器环境。4.4 现象decision_tree_id3.py报错ValueError: Input contains NaN, infinity or a value too large for dtype(float64)原因ID3算法要求输入为离散特征但课件提供的play_tennis.csv数据经pandas.read_csv()后outlook列被识别为object类型而entropy()函数内部做了np.log(p)运算——当p0时产生-inf。解决在数据加载后添加类型转换df[outlook] df[outlook].astype(category).cat.codes。课件PPT第58页“ID3适用条件”其实已提示“需离散化”。4.5 现象neural_network_mlp.py训练loss不下降始终在0.69附近震荡原因课件为简化教学权重初始化用np.random.randn()标准正态分布但当网络层数2时会导致梯度消失。PPT第95页“权重初始化”章节提到Xavier初始化但代码未实现。解决替换权重初始化代码# 原始第32行self.W1 np.random.randn(input_size, hidden_size) # 改为Xavier初始化 self.W1 np.random.randn(input_size, hidden_size) * np.sqrt(2.0 / (input_size hidden_size))此修改使loss在50轮内降至0.2以下——这是课件PPT第96页“初始化影响”结论的实证。5. 进阶实战用课件代码搭建一个“可解释性诊断面板”学到这里你已能跑通、调试、修改课件代码。但真实项目需要的是把算法变成可解释的诊断工具。我带某实验室做医疗辅助项目时就基于这套课件快速搭建了一个面向医生的“模型决策依据可视化面板”。核心思路不追求SOTA精度而确保每个预测背后都有医生能看懂的归因。5.1 构建特征重要性热力图连接课件与临床逻辑课件tree_explanation.py已实现ID3树的节点分裂信息。我们扩展它生成热力图# 在tree_explanation.py中新增 def plot_feature_importance(tree, feature_names): 生成特征重要性热力图课件PPT第59页‘分裂增益’概念落地 importances np.zeros(len(feature_names)) # 遍历所有内部节点累加分裂增益 for node in tree.internal_nodes: idx node.feature_idx gain node.information_gain importances[idx] gain # 归一化并绘图 importances importances / importances.sum() plt.figure(figsize(10, 4)) sns.heatmap([importances], xticklabelsfeature_names, yticklabels[Importance], cmapYlOrRd) plt.title(Feature Importance Heatmap (Based on ID3 Split Gain)) plt.show() # 调用示例在jupyter中 from tree_explanation import build_tree, plot_feature_importance tree build_tree(X_train, y_train, max_depth3) plot_feature_importance(tree, [age, bp, chol, gluc]) # 医疗特征名表格课件算法与可解释性技术的映射关系课件算法文件可解释性扩展点医疗场景价值decision_tree_id3.py分裂增益热力图告诉医生“血压值140”比“胆固醇240”对诊断高血压贡献大2.3倍logistic_regression_gd.py系数绝对值排序置信区间显示“血糖系数0.82±0.05”比“年龄系数0.15±0.03”更可靠svm_smo.py支持向量在原始特征空间投影标出哪些患者样本如ID127是决定边界的“关键病例”5.2 实现局部可解释LIME的轻量替代方案课件没有LIME但knn_explain.py提供了KNN的邻居查询能力。我们用它做局部解释# 在knn_explain.py中新增 def explain_prediction_knn(model, X_test, sample_idx, k5): 用KNN邻居解释单个样本预测课件PPT第62页‘实例相似性’思想 sample X_test[sample_idx:sample_idx1] distances, indices model.kneighbors(sample) # 获取邻居标签和距离 neighbor_labels model.y_train[indices[0]] neighbor_distances distances[0] # 计算加权投票距离越近权重越高 weights 1 / (neighbor_distances 1e-6) # 防止除零 weighted_vote np.bincount(neighbor_labels.astype(int), weightsweights) print(fSample {sample_idx} prediction: {model.predict(sample)[0]}) print(Top 3 nearest neighbors:) for i in range(min(3, len(indices[0]))): print(f Neighbor {i1}: ID{indices[0][i]}, Label{neighbor_labels[i]}, fDistance{neighbor_distances[i]:.4f}) # 使用示例 from knn_explain import KNNClassifier knn KNNClassifier(k5) knn.fit(X_train, y_train) explain_prediction_knn(knn, X_test, sample_idx0)当医生问“为什么判断这个病人是高风险”你不再回答“模型说的”而是展示“因为和他最像的3个已确诊病人平均血压高出18mmHg空腹血糖高出2.1mmol/L”。5.3 构建模型鲁棒性报告课件代码的意外价值课件adversarial_perturb.py本用于演示对抗样本但我们反向利用它做鲁棒性测试# 修改adversarial_perturb.py不生成对抗样本而测试扰动容忍度 def robustness_report(model, X_test, y_test, eps_list[0.01, 0.05, 0.1]): 生成模型鲁棒性报告课件PPT第102页‘对抗鲁棒性’概念转化 results {} for eps in eps_list: # 添加微小高斯噪声 X_perturbed X_test np.random.normal(0, eps, X_test.shape) y_pred model.predict(X_perturbed) acc_drop accuracy_score(y_test, y_pred) - accuracy_score(y_test, model.predict(X_test)) results[feps{eps}] acc_drop # 输出Markdown表格可直接粘贴到项目文档 print(| 扰动强度 | 准确率变化 |) print(|----------|------------|) for eps, drop in results.items(): print(f| {eps} | {drop:.4f} |) return results # 运行 robustness_report(logistic_model, X_test, y_test)这份报告让团队快速达成共识“当传感器误差0.05时模型仍可靠”——这比单纯说“准确率92%”更有工程价值。我坚持用这套课件做教学和项目不是因为它完美而是它把抽象概念钉在了可触摸的代码行上。当学生指着svm_smo.py第112行alpha_j np.clip(alpha_j, L, H)问我“为什么L和H是那样算的”我就知道他正在穿越从公式到实现的迷雾。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Harbor v2.13.1 ARM64离线部署实战:内网镜像仓库搭建与避坑指南

Harbor v2.13.1 ARM64离线部署实战:内网镜像仓库搭建与避坑指南

简介:本资源为 Harbor 最新 v2.13.1 的 ARM64 架构离线安装包,面向在 ARM64 服务器或 Kubernetes 集群上部署私有镜像仓库的运维与开发人员,解决国产化平台、信创环境及边缘节点无法直接拉取官方 x86 安装包的问题。压缩包共 6 个文件&#x…

2026/10/12 13:00:09 阅读更多 →
物联网平台二次开发选型指南:架构边界、扩展点与实战避坑

物联网平台二次开发选型指南:架构边界、扩展点与实战避坑

1. 为什么“适合二开”才是物联网平台选型的硬指标做物联网平台选型这件事,我踩过不少坑。早年做某智慧园区项目,技术评审时大家盯着功能清单看——设备接入、规则引擎、数据大屏、告警中心,列表很丰满,厂商演示也很流畅。结果签完…

2026/10/12 13:00:09 阅读更多 →
批处理驱动Matlab实现参数自动扫描:原理、传参与排错指南

批处理驱动Matlab实现参数自动扫描:原理、传参与排错指南

说实话,用批处理去反复跑Matlab这事儿,我最早是在一次大规模参数寻优中被逼出来的。那时候手里有一堆实验数据要拟合,模型参数有四五种组合方式,每组参数跑一遍得几十秒,加起来几百个组合,手动改一个跑一个…

2026/10/12 13:00:08 阅读更多 →

最新新闻

为什么你的代码审查总是走过场?一套开放式审查机制落地指南

为什么你的代码审查总是走过场?一套开放式审查机制落地指南

先说个真实场景。上个月我们组一个同事改了支付回调的幂等逻辑,自我感觉良好,直接在主干上推了代码。结果线上跑了一周,出现三笔重复扣款。事后复盘发现,这活儿如果当时有人认真审查过,根本不会上线——幂等键的生成规…

2026/10/12 14:02:13 阅读更多 →
构建代码评审闭环:open-code-review开源方案解析

构建代码评审闭环:open-code-review开源方案解析

代码评审这件事,做过的人都知道,最难的从来不是“找到问题”,而是“把问题形成闭环”。很多团队开着二三十人的例会争论一段代码,散会后又回到各自的即时通讯里补意见,最后评审结论躺在一个无人关注的共享文档里&#…

2026/10/12 14:02:13 阅读更多 →
AI日报从0到1:信息筛选、结构化输出与效率优化实战

AI日报从0到1:信息筛选、结构化输出与效率优化实战

1. 一份AI日报的诞生:从信息洪流到结构化输出 每天早上八点前把一份AI日报推到订阅者面前,这件事我坚持了快两年。很多人觉得不就是把新闻复制粘贴一下吗,但真正做过的人知道,一份能让人愿意每天花三分钟读完的日报,背…

2026/10/12 14:02:13 阅读更多 →
PaddlePaddle一维CNN故障诊断落地指南:CWRU轴承数据集实战

PaddlePaddle一维CNN故障诊断落地指南:CWRU轴承数据集实战

简介:本资源是一套基于PaddlePaddle框架实现的一维卷积神经网络(1D CNN)轴承故障识别完整复现方案,面向机械故障诊断、工业智能运维方向的深度学习初学者与工程实践者,解决西储大学轴承振动信号分类这一典型时序故障识…

2026/10/12 14:02:13 阅读更多 →
CAN与CAN-FD总线技术详解:从物理层到工程调试实战

CAN与CAN-FD总线技术详解:从物理层到工程调试实战

如果你拆过一辆现代汽车的中控台,或者在实验室里看过ECU开发板的背面,大概率会认识那两股缠绕在一起的双绞线。在车内几十个控制器之间,决定一辆车能不能挂挡、能不能起步、能不能刹车的,往往就是这根看起来平平无奇的总线。今天想…

2026/10/12 14:02:13 阅读更多 →
基于开源基座与LoRA的自定义大模型微调实战

基于开源基座与LoRA的自定义大模型微调实战

简介:这是一份面向企业开发者、算法工程师及业务方的自定义大语言模型实操手册,聚焦阿里云百炼平台,从零开始演示如何微调出更贴合业务需求的模型;即使缺乏大模型底层知识,也能按步骤完成模型调优、部署、评测全流程&a…

2026/10/12 14:01:12 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/11 14:36:54 阅读更多 →