尧图精选

西瓜书习题代码实战:KMeans、AdaBoost与SVM参数调优及避坑指南

🕒 发布时间:2026/9/24 18:08:04 📁 来源:尧图网络
简介这份资源是周志华《机器学习》西瓜书课程习题的代码实现合集面向正在学习机器学习基础理论、需要动手完成课后作业的高校学生与自学者。内容按章节组织覆盖线性模型、决策树、神经网络、支持向量机、贝叶斯分类、集成学习、聚类、降维与度量学习等核心主题每章配有习题说明与对应算法实现便于读者对照理论推导验证代码逻辑。压缩包共90个文件以22个Python脚本和10个Markdown笔记为主辅以jpg与png图示、csv与txt格式的西瓜数据集、xml工程配置及mat数据文件整体约11.74MB目录按章节划分清晰方便按知识点检索。目前已有934人学习下载。读者可借助KMeans、KNN、PCA、AdaBoost、StumpBagging等实现理解算法细节结合习题笔记与数据集复现实验适合作为课程作业参考与机器学习入门练手材料。1. 从一份西瓜书作业代码包说起周志华《机器学习》习题怎么落地周志华老师的《机器学习》俗称西瓜书几乎是每个机器学习入门者的必经之路但真正把课后习题从头到尾敲一遍的人并不多。原因很现实公式看懂了落到代码上却不知道从哪下手KMeans 的伪代码背得滚瓜烂熟真给你一份西瓜数据集聚类数 K 该设几、迭代什么时候停、结果怎么评估全是问号。这份 MachineLearning_Zhouzhihua_ProblemSets 就是冲着这个痛点来的——它按章节把西瓜书课后习题的代码实现整理成了可运行的 Python 工程覆盖线性模型、决策树、神经网络、支持向量机、贝叶斯分类、集成学习、聚类、降维与度量学习等核心章节还附带了西瓜数据集的多版本 CSV/TXT 文件。适合正在做课程作业、准备机器学习期末复习、或者想用传统机器学习模型练手的人。下面我按「这份资源是什么 → 怎么跑起来 → 参数怎么调 → 坑在哪」的顺序拆一遍。2. 工程结构与运行环境先搞清楚每个目录在干什么2.1 目录映射与章节对应关系拿到压缩包解压后根目录下是一堆以ch开头的文件夹命名规则很直白ch2--模型评估与选择、ch3--线性模型、ch4--决策树、ch5--神经网络、ch6--支持向量机、ch7--贝叶斯分类、ch8--集成学习、ch9--聚类、ch10--降维与度量学习。每个章节文件夹里通常包含三类东西一份chX习题.md的题目说明、若干.py实现文件、以及一个image文件夹存放结果图或公式截图。根目录还有一个data文件夹放的是西瓜数据集命名带版本号比如watermelon3_0_Ch.csv、watermelon2_0a_Ch.txt、watermelon4_0_Ch.txt对应书里不同章节用的不同属性版本。目录/文件内容对应习题ch3--线性模型3.3、3.4、3.5对数几率回归、LDAch4--决策树4.3-4.4、4.6信息增益划分、剪枝ch6--支持向量机mySVM、6.2/6.3/6.4/6.8SMO 实现、核函数ch8--集成学习8.3-AdaBoost.py、8.5-StumpBagging.pyAdaBoost、Baggingch9--聚类9.4-KMeans.pyKMeans 实现ch10--降维10.1-KNN.py、10.6-PCA.pyKNN、PCA这个结构的好处是章节边界清晰你想做哪一章的题直接进对应文件夹就行不用在几百个文件里翻。README.md在根目录一般会写运行方式和依赖建议先扫一眼。2.2 环境准备与依赖安装代码是纯 Python 写的没有用到深度学习框架主要依赖numpy、pandas、matplotlib部分章节可能用到scipy。我一般会先建一个干净的虚拟环境避免和系统里的包版本打架# 创建虚拟环境Python 3.8 均可 python -m venv ml_zhou_env # 激活Linux/Mac source ml_zhou_env/bin/activate # 激活Windows ml_zhou_env\Scripts\activate # 安装核心依赖 pip install numpy pandas matplotlib scipy这里有个细节西瓜书里的数据集属性值有中文比如色泽、根蒂、敲声代码读取时如果没指定编码在 Windows 上容易报UnicodeDecodeError。常见做法是在read_csv里显式加encodinggbk或encodingutf-8具体看文件实际编码。我一般会先用file命令或记事本另存为看一眼编码再决定参数。2.3 跑通第一个脚本以 KMeans 为例拿ch9--聚类/9.4-KMeans.py练手最合适因为它逻辑独立、依赖少。运行前先确认数据集路径。脚本里通常写的是相对路径如果你在根目录直接python ch9--聚类/9.4-KMeans.py路径可能对不上需要cd进章节目录再跑cd ch9--聚类 python 9.4-KMeans.py如果脚本里用的是../data/watermelon4_0_Ch.txt这种相对路径那在章节目录下跑正好。跑完后一般会弹出一张散点图不同簇用不同颜色标出控制台打印每轮的簇中心。看到图出来说明环境和数据链路都通了。这一步别急着改代码先确认「能跑」比「跑得好」重要。3. 核心算法实现拆解KMeans、AdaBoost 与 SVM 的参数怎么设3.1 KMeans 的簇数与迭代终止条件西瓜书 9.4 题要求实现 KMeans 并在西瓜数据集上聚类。代码里最关键的三个参数是簇数k、最大迭代次数max_iter、收敛阈值tol。书上的伪代码是「重复直到当前均值向量均未更新」落到代码里一般写成「簇中心变化小于 tol 就停」或「达到 max_iter 就停」。我一般会把max_iter设成 100tol设成 1e-4这两个值在西瓜数据集这种小规模数据上足够收敛。import numpy as np def kmeans(data, k, max_iter100, tol1e-4): # 随机选 k 个样本作为初始簇中心 n data.shape[0] idx np.random.choice(n, k, replaceFalse) centers data[idx].copy() for it in range(max_iter): # 计算每个样本到各中心的距离归入最近簇 dists np.linalg.norm(data[:, None] - centers[None], axis2) labels np.argmin(dists, axis1) new_centers np.array([data[labels j].mean(axis0) for j in range(k)]) # 中心变化小于阈值则提前终止 if np.linalg.norm(new_centers - centers) tol: break centers new_centers return labels, centers逻辑说明np.linalg.norm那行用广播机制一次性算出所有样本到所有中心的欧氏距离避免双重循环小数据上够用。参数上k是唯一需要你根据业务或肘部法确定的量max_iter和tol是保险丝防止死循环。注意初始中心是随机选的同一份数据跑两次结果可能不同这是 KMeans 的玄学之一想稳定就固定np.random.seed。3.2 AdaBoost 的基学习器与学习率ch8--集成学习/8.3-AdaBoost.py实现的是基于决策树桩的 AdaBoost。核心参数有两个基学习器数量n_estimators和学习率learning_rate。书上的 AdaBoost 没有显式学习率但工程实现里常加一个缩放因子控制每轮权重更新的幅度。我一般先设n_estimators50、learning_rate1.0看训练误差下降曲线如果震荡就降到 0.5。def adaboost(X, y, n_estimators50, learning_rate1.0): m X.shape[0] w np.ones(m) / m # 样本权重初始化 models, alphas [], [] for _ in range(n_estimators): stump build_stump(X, y, w) # 训练一个决策树桩 pred stump.predict(X) err np.sum(w * (pred ! y)) / np.sum(w) # 误差过大则跳过防止过拟合噪声 if err 0.5: continue alpha learning_rate * 0.5 * np.log((1 - err) / max(err, 1e-10)) w w * np.exp(-alpha * y * pred) w w / w.sum() # 权重归一化 models.append(stump) alphas.append(alpha) return models, alphas逻辑说明err 0.5这个判断是血泪经验——如果某个树桩比随机猜还差强行加进去只会拖累集成效果直接跳过。alpha是基学习器的投票权重误差越小权重越大。learning_rate乘在alpha上相当于给每轮更新踩一脚刹车防止权重被极端样本带偏。参数上n_estimators不是越大越好西瓜数据集样本少50 个树桩基本就收敛了再多容易过拟合。3.3 SVM 的核函数选择与软间隔参数ch6--支持向量机里的mySVM是手写实现6.2 到 6.8 分别对应不同核函数和软间隔的习题。核心参数是核函数类型线性/多项式/高斯、高斯核的gamma、以及软间隔的惩罚系数C。书上的 SVM 是硬间隔但真实数据往往线性不可分所以代码里一般会加松弛变量。我一般先用线性核跑一遍看基准再换高斯核gamma从1/特征数开始试C从 1 开始按 10 倍步长调。def rbf_kernel(X1, X2, gamma0.5): # 高斯核衡量两个样本的相似度 sq_dists np.sum(X1**2, axis1)[:, None] np.sum(X2**2, axis1)[None] - 2 * X1 X2.T return np.exp(-gamma * sq_dists)逻辑说明这里用矩阵运算展开欧氏距离平方避免逐对循环是常见做法。gamma越大核函数越「尖」模型越容易过拟合gamma越小决策边界越平滑。C越大对误分类的容忍越低间隔越窄。这两个参数是一对冤家调的时候建议固定一个调另一个别同时动。4. 避坑与排查数据编码、路径和随机种子那些事4.1 中文属性读取报 UnicodeDecodeError现象运行ch4--决策树或ch3--线性模型的脚本时pd.read_csv直接抛UnicodeDecodeError: utf-8 codec cant decode byte。原因西瓜数据集里的中文属性在 Windows 上常以 GBK 保存而 pandas 默认按 UTF-8 读。解决在读取时显式指定encodinggbk如果还不行就试encodinggb18030这个编码兼容性更广。我一般会写一个try/except兜底先试 UTF-8 再试 GBK。4.2 相对路径导致 FileNotFoundError现象在根目录直接python ch9--聚类/9.4-KMeans.py报找不到../data/watermelon4_0_Ch.txt。原因脚本里的相对路径是相对于「当前工作目录」而非脚本所在目录。解决要么cd进章节目录再跑要么在脚本开头用os.path.dirname(__file__)拼绝对路径。后者更稳改一次以后在哪跑都不怕。import os base os.path.dirname(os.path.abspath(__file__)) data_path os.path.join(base, .., data, watermelon4_0_Ch.txt)4.3 随机初始化导致结果不可复现现象KMeans 每次跑出来的簇划分不一样PCA 降维后的图每次朝向不同。原因np.random没固定种子初始中心或初始化矩阵随机。解决在脚本开头加np.random.seed(42)数字随意固定即可。做作业要交报告的话这一步是后悔药不加的话老师问你「为什么两次结果不一样」就尴尬了。4.4 矩阵维度不匹配的广播陷阱现象手写 SVM 或神经网络时报ValueError: operands could not be broadcast together。原因numpy的广播规则要求从最后一维往前对齐特征矩阵和标签向量的形状没对上比如(17, 2)和(17,)在某些运算里会出问题。解决用reshape(-1, 1)把标签变成列向量或者用np.newaxis显式扩维。调试时先print(X.shape, y.shape)比盯着报错猜快得多。4.5 决策树递归深度导致栈溢出现象ch4--决策树在某个数据集上递归建树时抛RecursionError: maximum recursion depth exceeded。原因数据里有连续值或噪声树一直分不下去递归层数超过 Python 默认的 1000。解决在划分函数里加两个终止条件——节点样本数小于min_samples或树深超过max_depth就停。常见做法是max_depth10、min_samples2既防溢出又防过拟合。5. 进阶用法把习题代码改成自己的实验模板5.1 用统一接口封装各章节算法习题代码各写各的函数签名不统一想横向对比算法很麻烦。我的习惯是抽一层薄封装让每个算法都暴露fit(X, y)和predict(X)两个方法这样就能用同一套评估流程跑所有模型。比如把 KMeans、AdaBoost、SVM 都包成类然后写一个evaluate函数统一算准确率或轮廓系数。class KMeansModel: def __init__(self, k3, max_iter100, tol1e-4): self.k, self.max_iter, self.tol k, max_iter, tol def fit(self, X): self.labels_, self.centers_ kmeans(X, self.k, self.max_iter, self.tol) return self def predict(self, X): dists np.linalg.norm(X[:, None] - self.centers_[None], axis2) return np.argmin(dists, axis1)逻辑说明fit里调用前面写的kmeans把结果存成实例属性predict用训练好的中心给新样本打标签。这样封装后换算法只改类名评估代码不用动。参数上k和max_iter通过构造函数传入方便做网格搜索。5.2 用交叉验证替代单次划分习题里大多是一次性划分训练集和测试集结果波动大。进阶做法是引入 k 折交叉验证把数据分成 k 份轮流做验证集最后取平均。西瓜书第 2 章讲模型评估时提过这个方法正好用习题代码实现一遍。常见做法是k5或k10小数据集用 5 折样本多点用 10 折。评估方式优点缺点适用场景留出法简单快速结果依赖单次划分数据量大5 折交叉验证结果稳定计算量翻 5 倍课程作业、小数据留一法用尽数据计算量极大样本极少5.3 结果可视化与报告输出跑完算法总得看图说话。matplotlib画散点图时我一般会把簇中心用大号星号标出来决策边界用contourf填充这样报告里一眼能看出模型在干什么。PCA 降维后的图记得标主成分方差贡献率不然读者不知道这两个轴代表多少信息量。最后把每章的运行结果、参数配置、评估指标整理成一张表比堆代码截图专业得多。从那以后我每次拿到一份习题代码包都强制先跑通一个最小脚本、固定随机种子、再动手改参数——这三步走完后面基本不会翻车。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →