周志华《机器学习》代码练习包实战:从环境配置到算法实现与避坑指南
简介这份资源是周志华《机器学习》一书的配套代码练习包面向正在系统学习机器学习算法、希望动手复现经典模型的本科生、研究生及自学者。内容围绕线性模型、决策树、集成学习与支持向量机等核心章节展开涵盖逻辑回归、LDA、Friedman 决策树、Iterated Bagging、MultiBoosting、偏差方差分解以及简化SVM、SVR 等典型实验帮助读者把公式推导落到可运行的代码上。压缩包共16个文件以15个 Python 脚本为主另附1个 README.md 说明文档整体约20KB体积轻便便于逐模块阅读与调试。目前已有508人学习下载适合作为课程作业、算法复现或面试复习的参考。读者可借助这些脚本理解各算法的实现细节与参数设置对照教材章节完成从理论到编码的过渡并在此基础上修改数据与超参数加深对模型行为的认识。1. 从一份老派代码包说起周志华《机器学习》配套练习到底能跑出什么如果你手头正压着一堆机器学习入门资料却始终卡在“公式能看懂、代码写不出”这一步那这份周志华《机器学习》代码练习包大概率能对上你的需求。它对应的是那本被称作“西瓜书”的经典教材把书里从线性模型、决策树、神经网络到支持向量机、聚类、降维这些章节的核心算法用可运行的脚本重新落了一遍。和只给结论的笔记不同这份资源的价值在于你能看到每个算法从公式到矩阵运算、从损失函数到梯度更新的完整链路而不是停留在“调个库就完事”。它适合两类人一类是正在准备机器学习期末复习、想用代码反推公式的学生另一类是已经会用 sklearn但想搞清楚底层实现到底在算什么的一线开发者。下面我按“资源是什么、怎么跑、坑在哪、怎么进阶”的顺序把这份包拆开讲透。2. 环境与目录把代码练习包跑起来的第一道门槛2.1 先看清包里有什么再决定装什么拿到压缩包后别急着 pip install先解压看目录结构。常见的组织方式是按章节分文件夹比如chapter3_linear、chapter4_tree、chapter5_nn每个文件夹里放对应的.py脚本和一份小规模数据集。也有把公共工具函数抽到utils.py或common.py的写法。先扫一遍 import 语句能快速判断依赖范围如果只出现numpy、matplotlib、pandas那环境很轻如果出现torch、tensorflow说明神经网络部分用了框架实现而不是纯手写。我一般会先建一个独立虚拟环境避免和现有项目打架python -m venv ml_practice_env source ml_practice_env/bin/activate # Windows 用 ml_practice_env\Scripts\activate pip install numpy pandas matplotlib scikit-learn这几行做完先别装深度学习框架。因为西瓜书配套练习里神经网络章节很多是纯 numpy 手写反向传播装了 torch 反而容易让你误以为必须用框架。等确认某个脚本确实 import 了 torch再补装也不迟。2.2 用最小脚本验证环境是否真的通了环境装完跑一个最小验证脚本确认 numpy 的矩阵运算和 matplotlib 绘图都正常。这一步能提前暴露版本不兼容问题比如 numpy 2.x 对某些旧写法的np.float已经移除。import numpy as np import matplotlib matplotlib.use(Agg) # 无图形界面环境下也能保存图片 import matplotlib.pyplot as plt # 构造一个简单的线性回归数据验证矩阵运算和绘图链路 x np.linspace(-1, 1, 100) y 2 * x 1 np.random.normal(0, 0.1, sizex.shape) X np.c_[x, np.ones_like(x)] # 增广矩阵最后一列是偏置项 w np.linalg.inv(X.T X) X.T y # 最小二乘闭式解 print(拟合参数:, w) plt.scatter(x, y, s8, labeldata) plt.plot(x, X w, colorred, labelfit) plt.legend() plt.savefig(smoke_test.png, dpi120) print(图片已保存)这段代码的逻辑是用增广矩阵把偏置项并入权重向量再用正规方程一次性求出最小二乘解。参数上np.c_负责按列拼接X.T X是协方差矩阵np.linalg.inv求逆。如果这一步报Singular matrix说明数据存在完全共线性换一组随机数据即可。跑通后你会得到一张smoke_test.png说明 numpy 和 matplotlib 都没问题。2.3 数据集路径与随机种子的统一处理很多练习包会把数据集放在data/目录下脚本里用相对路径读取。如果你在错误的目录下执行python chapter3_linear/linear_regression.py就会报FileNotFoundError。常见做法是在脚本开头用os.path.dirname(__file__)定位当前文件所在目录再拼接数据路径import os import pandas as pd BASE_DIR os.path.dirname(os.path.abspath(__file__)) data_path os.path.join(BASE_DIR, .., data, watermelon.csv) df pd.read_csv(data_path) print(df.head())这样无论从哪个目录调用脚本路径都不会错。另外涉及随机初始化或数据划分的脚本一定要固定随机种子否则每次跑出来的结果都不一样调参时根本分不清是参数起作用还是随机性在作祟。常见写法是np.random.seed(42)和random.seed(42)同时设置。3. 核心算法脚本怎么读从线性回归到决策树的代码拆解3.1 线性回归与对数几率回归公式到代码的对应关系西瓜书里线性模型章节的练习通常会让你实现最小二乘法和梯度下降两种解法。读这类脚本时重点看三件事损失函数怎么定义、梯度怎么推导、更新步长怎么控制。以对数几率回归为例核心代码往往长这样def sigmoid(z): return 1.0 / (1.0 np.exp(-z)) def train_logistic(X, y, lr0.1, epochs500): m, n X.shape w np.zeros(n) # 权重初始化 for epoch in range(epochs): z X w y_hat sigmoid(z) grad X.T (y_hat - y) / m # 交叉熵损失对 w 的梯度 w - lr * grad if epoch % 100 0: loss -np.mean(y * np.log(y_hat 1e-9) (1 - y) * np.log(1 - y_hat 1e-9)) print(fepoch {epoch}, loss {loss:.4f}) return w逻辑说明sigmoid把线性输出压到 0 到 1 之间grad是交叉熵损失对权重的梯度除以m是做批量平均。参数上lr太大会震荡不收敛太小则收敛慢一般从 0.1 开始试epochs根据损失是否稳定来判断。代码里加1e-9是防止log(0)报-inf这是血泪经验不加的话训练到后期很容易出现 nan。3.2 决策树信息增益、基尼指数与递归划分决策树部分的练习重点在划分准则的实现。信息增益对应熵的减少基尼指数则是另一种不纯度度量。读代码时注意递归终止条件是节点样本全同类就停还是达到最大深度就停还是信息增益小于阈值就停。常见实现会先写一个calc_entropy或calc_gini再写split_dataset最后是build_tree递归。def calc_gini(y): _, counts np.unique(y, return_countsTrue) probs counts / len(y) return 1.0 - np.sum(probs ** 2) def best_split(X, y): best_feature, best_gain, best_value None, 0, None base_gini calc_gini(y) for feature in range(X.shape[1]): for value in np.unique(X[:, feature]): left_mask X[:, feature] value right_mask ~left_mask if left_mask.sum() 0 or right_mask.sum() 0: continue gini (left_mask.sum() * calc_gini(y[left_mask]) right_mask.sum() * calc_gini(y[right_mask])) / len(y) gain base_gini - gini if gain best_gain: best_feature, best_gain, best_value feature, gain, value return best_feature, best_value这段代码遍历每个特征的每个取值计算划分后的加权基尼指数取增益最大的划分点。参数上np.unique会自动排序并去重适合连续特征离散化。注意如果特征取值很多这个双重循环会很慢实际项目中会先做分箱或限制候选切分点。3.3 神经网络手写反向传播时最容易断的链路神经网络章节的练习如果是纯 numpy 实现通常会包含前向传播、损失计算、反向传播和参数更新四步。读这类代码时最容易断的链路是梯度形状对不上。比如输出层用 softmax损失用交叉熵那么输出层梯度就是y_hat - y_true这个结论可以直接用不需要再乘 softmax 的导数。def forward(X, W1, b1, W2, b2): Z1 X W1 b1 A1 np.maximum(0, Z1) # ReLU 激活 Z2 A1 W2 b2 exp_Z2 np.exp(Z2 - np.max(Z2, axis1, keepdimsTrue)) A2 exp_Z2 / np.sum(exp_Z2, axis1, keepdimsTrue) return Z1, A1, Z2, A2 def backward(X, y_onehot, Z1, A1, A2, W2): m X.shape[0] dZ2 (A2 - y_onehot) / m dW2 A1.T dZ2 db2 np.sum(dZ2, axis0) dA1 dZ2 W2.T dZ1 dA1 * (Z1 0) # ReLU 导数 dW1 X.T dZ1 db1 np.sum(dZ1, axis0) return dW1, db1, dW2, db2逻辑上exp_Z2 - np.max(...)是为了数值稳定防止指数爆炸。dZ2 A2 - y_onehot是 softmax 加交叉熵的经典简化结果。参数上m用于批量平均Z1 0是 ReLU 的导数掩码。如果训练时损失不下降先检查y_onehot的编码是否正确再检查学习率是否过大。3.4 支持向量机与聚类对偶问题与距离度量的实现差异SVM 部分如果要求手写 SMO 算法代码量会明显上升。读的时候抓住核心每次选两个乘子固定其他乘子求这两个乘子的最优解再裁剪到约束范围。聚类部分则重点看距离度量和迭代终止条件K-means 的常见实现是先随机选中心再分配样本再更新中心直到中心变化小于阈值。def kmeans(X, k, max_iter100, tol1e-4): idx np.random.choice(len(X), k, replaceFalse) centers X[idx] for _ in range(max_iter): dists np.linalg.norm(X[:, None] - centers[None], axis2) labels np.argmin(dists, axis1) new_centers np.array([X[labels i].mean(axis0) for i in range(k)]) if np.linalg.norm(new_centers - centers) tol: break centers new_centers return labels, centers这里X[:, None] - centers[None]利用广播机制算出每个样本到每个中心的距离np.argmin取最近中心。参数上tol控制收敛精度max_iter防止死循环。如果某个簇为空mean会报 nan常见做法是重新随机选一个中心或跳过该簇。4. 避坑与排查跑这份代码练习包时最容易翻车的五件事4.1 现象脚本报ModuleNotFoundError: No module named xxx原因通常不是没装包而是装到了全局环境而你在虚拟环境里跑。或者包名和 import 名不一致比如sklearn对应scikit-learn。解决方式是先which python确认当前解释器路径再pip list看包是否在列。如果确实缺包用pip install 包名补装注意不要混用 conda 和 pip。4.2 现象损失函数出现 nan 或 inf原因多半是学习率过大导致梯度爆炸或者 log 里出现了 0。解决方式是先降低学习率一个数量级再在 log 里加极小值1e-9。如果数据特征量纲差异大先做标准化否则梯度下降会非常不稳定。我一般会在训练前打印一次损失确认初始值合理再继续。4.3 现象决策树递归深度过大导致RecursionError原因是连续特征取值太多或者没有设置最大深度。解决方式是加max_depth参数或者在划分前对连续特征做分箱。另外如果数据集有大量重复样本递归也可能停不下来需要加一个“节点样本数小于阈值就停止”的条件。4.4 现象K-means 结果每次都不一样原因是初始中心随机选且没有固定随机种子。解决方式是设置np.random.seed(42)或者改用 K-means 初始化。如果数据本身簇结构不明显结果波动也正常可以多跑几次取最优。4.5 现象matplotlib 报RuntimeError: main thread is not in main loop原因是在无图形界面的服务器上默认用了交互式后端。解决方式是在 import matplotlib 后立刻设置matplotlib.use(Agg)再 import pyplot。这样绘图只保存文件不弹窗适合远程运行。5. 进阶用法把练习脚本改造成可复用的实验模板5.1 用配置文件管理超参数避免硬编码练习包里的脚本往往把学习率、迭代次数写死在代码里改一次参数就要翻一次源码。我一般会抽一个config.yaml或config.json把超参数集中管理import json with open(config.json, r, encodingutf-8) as f: cfg json.load(f) lr cfg[logistic][lr] epochs cfg[logistic][epochs]这样调参时只改配置文件脚本本身不动。参数说明lr控制步长epochs控制训练轮数batch_size控制每次更新用的样本数。配置文件的好处是实验记录可追溯换一组参数就是换一个文件。5.2 加一层交叉验证判断模型是否真的稳定练习脚本通常只做一次训练集/测试集划分结果波动大。加一层 K 折交叉验证能更客观地评估模型。常见做法是用sklearn.model_selection.KFold也可以手写def kfold_indices(n, k5): indices np.arange(n) np.random.shuffle(indices) fold_size n // k for i in range(k): test_idx indices[i * fold_size:(i 1) * fold_size] train_idx np.setdiff1d(indices, test_idx) yield train_idx, test_idx逻辑上先打乱索引再按折大小切分np.setdiff1d取补集作为训练集。参数上k一般取 5 或 10数据量小就取小一点。这样跑完能拿到每折的准确率看均值 and 方差比单次划分靠谱得多。5.3 把重复出现的评估指标封装成函数练习包里每个脚本都写一遍准确率、精确率、召回率既冗余又容易写错。我习惯抽一个metrics.pydef accuracy(y_true, y_pred): return np.mean(y_true y_pred) def precision(y_true, y_pred): tp np.sum((y_true 1) (y_pred 1)) fp np.sum((y_true 0) (y_pred 1)) return tp / (tp fp 1e-9) def recall(y_true, y_pred): tp np.sum((y_true 1) (y_pred 1)) fn np.sum((y_true 1) (y_pred 0)) return tp / (tp fn 1e-9)这样所有脚本统一调用结果可比。参数上1e-9防止除零。如果类别不平衡还要看 F1 和 AUC不能只看准确率。5.4 用版本记录实验避免“上次那个结果找不到了”我吃过最大的亏是跑出一个不错的结果过两天想复现却忘了当时改了什么。从那以后我每次跑实验前都会把当前脚本、配置文件、随机种子和输出指标写进一个experiment_log.md哪怕只是几行字。这个习惯看起来笨但能省下大量“后悔药”时间。你也可以用git管理代码每次实验打一个 tag配合配置文件就能完整复现。希望这份拆解能帮你把这份代码练习包真正跑起来而不是让它继续躺在硬盘里。本文还有配套的精品资源点击获取

相关新闻

自动化测试进阶:从pytest框架到持续集成,如何达到20K岗位能力?

自动化测试进阶:从pytest框架到持续集成,如何达到20K岗位能力?

前段时间公司招聘自动化测试岗位,我面了个开口要20K的候选人。简历写得很漂亮:熟悉自动化测试框架,做过两个项目的UI自动化,能独立完成脚本开发。当时心里预期还不错,结果一聊细节就出了问题。问pytest的fixture作用域…

2026/10/13 20:28:00 阅读更多 →
分销商城二开实战:FastAdmin+Shopro+Uni-App佣金结算与上线踩坑

分销商城二开实战:FastAdmin+Shopro+Uni-App佣金结算与上线踩坑

上周终于把模拟项目X的最后一版分销佣金规则部署上线了。表面上看,这只是给一个基于FastAdmin、Shopro和Uni-App的分销商城做二次开发和功能定制,实际拆完才发现,要动的地方横跨三块:FastAdmin后台的佣金等级与提现配置、订单结算…

2026/10/13 8:42:42 阅读更多 →
PAE物理地址扩展:32位系统突破4GB内存限制的核心机制

PAE物理地址扩展:32位系统突破4GB内存限制的核心机制

1. 什么是PAE:从“物理地址扩展”到现代内存管理的底层支点PAE,全称Physical Address Extension,中文直译为“物理地址扩展”。这个词听起来像教科书里的冷门术语,但其实它早已悄悄嵌入你每天使用的设备底层——无论是某实验室正在…

2026/10/13 7:18:36 阅读更多 →

最新新闻

Node.js+Vue全栈开发出租车智能调度系统实践

Node.js+Vue全栈开发出租车智能调度系统实践

1. 项目背景与核心需求出租车业务管理系统是传统运输行业数字化转型的典型场景。随着网约车平台的兴起,传统出租车公司面临着运营效率低下、调度方式落后、数据统计困难等痛点。这个基于Node.jsVue的全栈项目,正是为了解决以下核心问题:实时调…

2026/10/14 10:08:38 阅读更多 →
瑞利-里茨法:弹性力学能量原理与工程实践

瑞利-里茨法:弹性力学能量原理与工程实践

1. 瑞利-里茨法基础理论1.1 能量原理的物理背景在弹性力学系统中,能量原理为我们提供了一种强有力的分析工具。最小势能原理指出:在所有满足位移边界条件的可能位移场中,真实的位移场使得系统的总势能取得极小值。这个原理不仅适用于静力学问…

2026/10/14 10:08:38 阅读更多 →
Kafka Log存储原理:揭秘顺序写、稀疏索引与Segment分片设计

Kafka Log存储原理:揭秘顺序写、稀疏索引与Segment分片设计

1. 这不是“日志存储”,而是 Kafka 的数据心脏——从磁盘文件结构看吞吐与一致性的底层博弈你打开 Kafka 的 data 目录,看到一堆形如topic-partition-0/00000000000000000000.log和00000000000000000000.index的文件,第一反应可能是&#xff…

2026/10/14 10:08:38 阅读更多 →
Qt+MinGW 编译 PCL 全依赖链实战指南

Qt+MinGW 编译 PCL 全依赖链实战指南

简介:本资源面向需要在Windows平台使用Qt与MinGW构建点云处理环境的C开发者,提供PCL及其全部依赖库的完整编译成果。PCL是开源三维点云处理库,涵盖数据采集、预处理、特征提取与表面重建;配套的Boost、Eigen、FLANN、Qhull与VTK分…

2026/10/14 10:08:38 阅读更多 →
基于机器学习的Web日志异常检测与根因分析

基于机器学习的Web日志异常检测与根因分析

简介:这是一套面向Web安全工程师、运维开发人员及机器学习初学者的终端日志分析工具,聚焦于Web服务器日志的自动化统计、审计与恶意请求识别。项目基于Python实现,集成日志解析、访问量/请求类型多维统计、SQLite(或MySQL&#xf…

2026/10/14 10:08:38 阅读更多 →
macOS C++20开发环境配置:LLVM+VS Code+Clang完整闭环

macOS C++20开发环境配置:LLVM+VS Code+Clang完整闭环

1. 为什么 macOS 上配 C 环境总让人“卡在第一步”?Mac 用着顺手,写代码也清爽,但一到配 C 环境,很多人就停在了终端里那行command not found: g上——不是没装 Xcode,就是装了却找不到编译器路径;不是clan…

2026/10/14 10:07:26 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →