
简介一份基于Jupyter Notebook的机器学习入门实践资源面向希望系统掌握常见算法并动手操作的初学者与开发者围绕Python生态讲解从数据预处理、线性回归、逻辑回归、决策树、随机森林、SVM到聚类、模型评估与参数调优的完整流程并配有具体案例便于在交互式环境中边看边练。资源包为RAR压缩格式共25个文件大小约2.97MB以.ipynb笔记、.md说明文档和.csv数据集为主体另有.py脚本与license等辅助文件可直接在Jupyter中打开运行适合跟着步骤复现建模过程。目前已有2046人学习下载内容覆盖常用算法原理与Scikit-learn实现能够帮助读者快速上手构建、评估和优化自己的机器学习模型是一份实用且易读的入门参考资料。1. 先把 Jupyter Notebook 和机器学习基本模型算法放在同一张桌子上训练集上精度漂亮切换到测试集就崩盘这是我见过最多人在 Jupyter Notebook 里踩的坑。标题里的“机器学习基本模型算法”不是让你背公式而是让你在单元格里一行一行跑通线性回归、逻辑回归、决策树再配一个附加案例把数据到评估的完整链路走一遍。Jupyter Notebook 的作用不是替代 IDE而是让你把每个中间结果都摊开看——这正是机器学习入门阶段最需要的能改、能看、能复盘。这篇文章按我自己的实践路径来写适合刚装好 Miniconda、准备开始机器学习期末复习的读者也适合那些想用 notebook 快速验证模型选型的人。2. 先把 Jupyter Notebook 跑起来Miniconda 环境搭建与四个必会操作2.1 为什么用 Miniconda 而不是直接装 Python新手最容易犯的错是去官网装一个 Python然后用 pip 一个个装包三天后环境就乱了。机器学习基本模型算法涉及的包有 scikit-learn、pandas、matplotlib、jupyter它们各自依赖不同版本的 NumPy直接 pip 很容易把系统 Python 搅浑。Miniconda 是一个迷你版 conda 环境管理器它能帮你在一个机器上建多个互不干扰的 Python 环境这也是业界默认的实践。你不需要装完整 AnacondaMiniconda 加上按需安装的包已经足够启动速度快很多。我在给朋友搭环境时遇到最多的场景Miniconda 安装后 如何使用 jupyter notebook 成了第一个拦路虎。其实核心就三步建环境、激活环境、启动 notebook。conda 环境不激活你输入的 jupyter 命令可能指向全局的旧版本或者干脆提示“找不到指定的程序”。所以这一节的命令值得反复确认。2.2 建环境、启动 Notebook 的最小命令打开终端Windows 用 Anaconda Prompt依次执行下面这段。我这里把环境命名为 mlbasePython 版本选 3.10兼容性和包支持都比较稳。conda create -n mlbase python3.10 -y conda activate mlbase conda install jupyter matplotlib scikit-learn pandas -c conda-forge -y jupyter notebook第一行创建一个名叫 mlbase 的独立环境-y 表示自动确认。第二行激活这个环境注意激活后终端前面会出现(mlbase)字样这是判断环境是否切换成功的唯一指标。第三行从 conda-forge 频道安装四个核心包jupyter 负责 notebook 服务matplotlib 负责画图scikit-learn 提供机器学习算法pandas 做表格数据处理。第四行启动 notebook默认会在浏览器打开 http://localhost:8888 的页面。如果你在浏览器里看到文件列表环境就算成功了。我把这几个命令当成“后悔药”来用环境搞坏了直接conda remove -n mlbase --all删掉重建十分钟内又是一条好汉根本不用重装系统。2.3 写代码之前先知道的三个魔法命令Jupyter Notebook 的输入框叫单元格里面除了能写 Python 代码还能写“魔法命令”控制 notebook 自身行为。我平时用得最频繁的是下面三个它们直接影响复现效率和排错速度。%matplotlib inline %config InlineBackend.figure_format retina %timeit model.fit(X_train, y_train)第一行让 matplotlib 画的图直接嵌在单元格输出区而不是弹出独立窗口。在 notebook 里如果漏写这行经常出现图一闪而过或者空白一片的翻车现场。第二行让图在高分屏上显示得更清晰不是必需但笔记本上开了这条会更舒服。第三行%timeit用来测试一行代码的平均运行时间比如你想比较线性回归和决策树的训练耗时用它就能得到靠谱数字远比自己time.time()掐表准。这三个魔法命令不是算法本身却是 notebook 里做实验的“基础设施”。后面的模型训练和评估都会依赖它们所以先写在这里后面不再重复解释。2.4 把 notebook 当草稿纸而不是文档很多人习惯在 notebook 里写一大堆 Markdown 标题和解释然后再写代码。我的建议反过来刚开始实验就把代码当草稿纸跑通了再回头补 Markdown。机器学习基本模型算法的实验过程中90% 的代码都是临时的你真正要留下的是“哪些超参数组合有效”这个结论而不是排版漂亮却跑不动的单元格。我一般会给 notebook 命名成01_lr_baseline.ipynb这样的格式数字开头是为了排序lr表示逻辑回归baseline表示这是基线版本。所有单元格尽量按“读取数据 → 清洗 → 划分 → 训练 → 评估”的顺序排列一旦乱序后面重新运行时会出现变量找不到的尴尬场面。这一点在长期项目中比选哪一个模型更重要。3. 机器学习基本模型算法从线性到树模型的选型思路3.1 回归问题从线性回归开始机器学习基本模型算法里线性回归是第一个要跑通的。它假设目标值和特征之间是线性关系公式是 y w·x bscikit-learn 里一行代码就能训练。但它的价值不在“准”而在“能解释”你可以直接看系数 w 的大小和正负知道哪个特征对结果影响最大。这在给业务方解释模型时至关重要比树模型的黑匣子友好得多。我在做房价预测案例时第一版模型就用线性回归。虽然效果一般但至少能回答“面积每增加一平米房价大概涨多少”这种具体问题。如果换用随机森林解释起来就费劲了。所以我的选型经验是数据维度低、特征与目标关系简单时无脑先跑线性回归跑不通再考虑复杂模型。3.2 分类问题看逻辑回归与 KNN逻辑回归虽然名字里有“回归”实际是处理二分类问题的。它在线性回归外面套了一层 sigmoid 函数把输出压到 0 和 1 之间变成概率。scikit-learn 的LogisticRegression用起来很简单但参数C是正则化强度的倒数新手常把它当成越大越好导致过拟合。from sklearn.linear_model import LogisticRegression from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split data load_breast_cancer() X_train, X_test, y_train, y_test train_test_split( data.data, data.target, test_size0.2, random_state42 ) model LogisticRegression(C0.1, max_iter1000) model.fit(X_train, y_train) print(训练集得分:, model.score(X_train, y_train)) print(测试集得分:, model.score(X_test, y_test))这里C0.1表示正则化强度较高能防止系数过大max_iter1000给足迭代次数否则会报“ConvergenceWarning”。train_test_split的random_state42固定随机种子保证每次运行划分结果一致。这段代码是分类任务的标准骨架换数据集时只需要换数据和调 C 参数。KNN 则是最直观的机器学习算法之一新样本的类别由它 k 个最近邻居投票决定。它没有训练过程所以模型文件几乎不占空间但预测时需要计算样本间距离数据量大时非常慢。KNN 在特征少、样本量小的情况下精度不输复杂模型我用它做过一个图像小样本分类结果比决策树还好。不过它的可解释性差而且对特征尺度极度敏感用之前必须做标准化。3.3 决策树与集成模型的自由度决策树的核心是递归划分特征空间每次选一个特征和一个阈值让划分后的纯度提升最大。sklearn 的DecisionTreeClassifier如果不限制深度会疯狂生长直到每个叶子都只剩一类这在训练集上 100% 准确测试集上却可能一塌糊涂。所以用决策树时务必设置max_depth和min_samples_leaf。from sklearn.tree import DecisionTreeClassifier tree DecisionTreeClassifier(max_depth3, min_samples_leaf5, random_state42) tree.fit(X_train, y_train) print(树的深度:, tree.get_depth()) print(叶子节点数:, tree.get_n_leaves())max_depth3限制树最多分裂三层min_samples_leaf5要求叶子节点至少包含 5 个样本这两个参数是控制过拟合的主力。get_depth()和get_n_leaves()用来检查训练出的树是否被压住了。一个只分裂三层的决策树很容易用plot_tree画出来给业务看这也是它比线性模型更能讲故事的地方。但我现在做项目很少直接用单棵决策树而是用随机森林或梯度提升这类集成模型。它们把几百棵树的预测结果平均稳定性和精度都高一个档次。集成模型的自由度在超参数上n_estimators决定树的数量max_features决定每棵树的特征抽样比例。初学者不需要调太多先把n_estimators设成 100max_depth设成 5通常已经能超过线性回归。3.4 模型比较表该用哪个当基线把上面的基本模型放在一张表里对比方便你在拿到新任务时快速选择基线。模型任务类型优点缺点必调参数线性回归回归训练快、可解释只能表达线性关系无逻辑回归二分类输出概率、可解释边界仍是线性的C、max_iterKNN分类/回归无训练过程预测慢、对尺度敏感n_neighbors、权重决策树分类/回归可视化强容易过拟合max_depth、min_samples_leaf随机森林分类/回归精度稳、抗过拟合模型大、解释性差n_estimators、max_depth我自己的习惯是回归任务先跑线性回归分类任务先跑逻辑回归如果精度不够再跳到随机森林。KNN 只在样本量小于一万且特征维度不高时当作交叉验证的对照组。这张表不是绝对的但对机器学习入门来说至少能帮你把前几次实验的方向框住不用一上来就瞎试深度学习。4. 附加案例用 Jupyter Notebook 从数据到模型评估跑一遍4.1 案例目标与数据集选择附加案例要能完整展示从数据到模型的链路我用的是 scikit-learn 自带的乳腺癌数据集它包含 569 个样本、30 个数值型特征目标是判断肿瘤是良性还是恶性。选它有三个理由数据量小在 notebook 里秒跑特征全是数值不需要太复杂的预处理二分类问题足够说明逻辑回归、KNN、决策树三种模型的差别。这个案例也适合期末复习时反复练手因为不依赖外部数据文件只要 scikit-learn 装好就能跑。如果你想换自己的生活数据只要把数据组织成 pandas DataFrame 格式后面的代码基本不用改。4.2 加载数据与探索性分析打开 Jupyter Notebook新建一个 Python 3 内核的笔记本。第一个单元格写加载数据的代码顺便看一眼数据长什么样。import pandas as pd from sklearn.datasets import load_breast_cancer cancer load_breast_cancer() df pd.DataFrame(cancer.data, columnscancer.feature_names) df[target] cancer.target df.head()cancer.data是特征矩阵cancer.feature_names是特征名cancer.target是标签。把它们合成一个表后df.head()会显示前 5 行方便直观检查是否有缺失值或离谱的数值。这里没有做标准化但后续 KNN 模型必须要做因为它的距离计算受量纲影响极大。探索性分析我一般看两类东西类别是否均衡特征之间是否高度相关。代码放在同一个单元格里print(df[target].value_counts()) print(df.isnull().sum().sum()) corr df.iloc[:, :-1].corr().abs() upper_tri corr.where(np.triu(np.ones(corr.shape), k1).astype(bool)) print(最大相关系数:, upper_tri.stack().max())类别均衡性直接影响评价指标的选择——如果恶性样本只占 10%准确率就不能代表模型好坏。这里 target 为 1 表示恶性样本量约 212/357不算极端不平衡。缺失值总和为 0省去了清洗步骤。最后一行计算特征间相关系数矩阵找出绝对值最大的相关对这能帮你判断是否有多重共线性问题线性回归遇到它时要小心。4.3 训练三个模型并比较指标接下来把数据划分成训练集和测试集然后让逻辑回归、KNN、决策树各跑一遍。先写一个公共数据准备单元格import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler X df.iloc[:, :-1].values y df[target].values X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) scaler StandardScaler() X_train_s scaler.fit_transform(X_train) X_test_s scaler.transform(X_test)stratifyy保证划分后训练集和测试集里良性与恶性的比例和原数据一致这在分类任务中是必须的否则运气不好时测试集里可能完全没有某个类别。StandardScaler先对训练集计算均值方差再应用同样参数到测试集注意不能分别对测试集做 fit否则就信息泄露了。下面分别训练三个模型from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier models { 逻辑回归: LogisticRegression(C0.1, max_iter1000, random_state42), KNN: KNeighborsClassifier(n_neighbors5), 决策树: DecisionTreeClassifier(max_depth3, min_samples_leaf5, random_state42), } for name, model in models.items(): if name KNN: model.fit(X_train_s, y_train) train_acc model.score(X_train_s, y_train) test_acc model.score(X_test_s, y_test) else: model.fit(X_train, y_train) train_acc model.score(X_train, y_train) test_acc model.score(X_test, y_test) print(f{name}: 训练集 {train_acc:.3f}, 测试集 {test_acc:.3f})这里用字典把模型实例装起来循环训练和打分。注意 KNN 用的是标准化后的数据其他模型用原始数据所以单独判断。score方法返回准确率对二分类来说就是预测正确的比例。跑出来后你会看到逻辑回归和决策树在测试集都能到 0.94 左右KNN 略低一点。这很正常因为数据本身线性可分的程度较高。4.4 用图表看模型差异只看数字不直观我习惯在 notebook 里画一张混淆矩阵和 ROC 曲线一眼就能看出模型在哪些样本上犯错。把图画放在同一个单元格里用子图排列。import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay fig, axes plt.subplots(1, 3, figsize(12, 4)) for ax, (name, model) in zip(axes, models.items()): if name KNN: y_pred model.predict(X_test_s) else: y_pred model.predict(X_test) cm confusion_matrix(y_test, y_pred) disp ConfusionMatrixDisplay(cm, display_labels[良性, 恶性]) disp.plot(axax, colorbarFalse) ax.set_title(name) plt.tight_layout() plt.show()混淆矩阵的四个格子分别代表真正例、假正例、真负例、假负例。对于癌症筛查场景假负例把恶性判成良性是最不能接受的所以横向对比三个模型的混淆矩阵时重点看第二行第一列的数字。这个图放在报告里比单纯贴准确率更有说服力。如果你要在笔记本里继续做 ROC 曲线可以用sklearn.metrics.roc_curve拿到假正率和真正率再逐个画曲线。到这里一个完整的附加案例就跑通了。整个流程从加载数据到可视化评估每个步骤都能被独立单元格复现这也是 Jupyter Notebook 相比脚本文件的核心优势——你可以随时回到某个环节修改参数重新运行后面的部分不用从头跑一遍。5. Jupyter Notebook 与 sklearn 的避坑手册5 个常见问题5.1 Miniconda 安装后启动 notebook 提示找不到指定的程序现象在终端输入jupyter notebook窗口直接报错“找不到指定的程序”或者提示“jupyter 不是内部或外部命令”。原因最常见的情况是当前终端没有激活任何 conda 环境。Windows 上如果你直接打开 PowerShell 而没有先跑conda activate系统调用的还是全局路径里残留的旧版 Python 或 jupyter。另一个原因是 Miniconda 安装时没有把 conda 命令加入 PATH导致conda本身都找不到。解决先确认能否使用conda --version。如果可以先执行conda activate mlbase然后再启动。如果 conda 命令不存在打开“Anaconda Prompt”这个专用终端它已经配好了 conda 环境。实在不行就重新运行 Miniconda 安装包选中“Add to PATH”选项修复。我遇到这个问题的概率占 80%都是因为忘了激活。5.2 内核连接失败或单元格卡在“运行中”现象点击运行单元格后右上角圆圈一直转状态栏显示“Kernel connecting...”等待一分钟还在转或者直接弹出“死内核”对话框。原因内核崩通常是底层 Python 进程被某些操作搞挂比如 matplotlib 的某些后端在 macOS 上冲突或者 pandas 读取超大文件时内存不够。另一类原因是 notebook 默认使用 8888 端口端口被占用后内核连不上。解决首先把单元格里的代码分成小块运行定位是哪个操作崩的最常见的是plt.show()和某些自定义函数冲突试试把%matplotlib inline放在 notebook 最顶部。端口问题用jupyter notebook --port8889换个端口启动。如果内核还是死直接在终端 CtrlC 停掉服务然后重启 kernel。记住内核一崩当前内存里的变量全部丢失所以长任务要养成“先存盘再运行”的习惯否则半天白跑。5.3 matplotlib 画图空白或不显示现象运行plt.plot(x, y)后没有任何图有时候弹出Figure size 640x480 with 1 Axes一行字但图是空的。原因常见两种。第一缺少%matplotlib inline魔法命令在 notebook 里图形对象不会自动渲染。第二代码里用了多个plt.figure()但没调用plt.show()之前的图被覆盖掉了。解决在导入 matplotlib 后立刻写上%matplotlib inline。如果还是空白检查最后一行是不是漏了plt.show()——不过在 notebook 的 inline 模式下plt.show()不是必须的但写了更稳妥。还有一个小坑不要在一个单元格里连续创建 20 张子图还不开fig.tight_layout()布局冲突会让某些子图缩成一条线画出来像长毛刺这时加一行plt.tight_layout()再试。5.4 sklearn 版本升级导致 API 报错现象以前能跑的代码报AttributeError: module sklearn has no attribute xxx或者ImportError: cannot import name cross_val_score from sklearn.cross_validation。原因scikit-learn 版本迭代很快老代码里很多 API 被移动或改名。比如train_test_split以前在sklearn.cross_validation0.18 之后移到了sklearn.model_selection。网上很多旧教程和期末复习资料用的还是老 API直接照抄就翻车。解决在所有代码起始处加上import sklearn; print(sklearn.__version__)打印版本号。然后统一用最新 API 写法数据划分从sklearn.model_selection导入交叉验证从同一个位置导入。实在遇到旧代码不要急着找原版 API去官方文档看迁移指南或者直接基于新 API 重写那几行。版本差异是机器学习入门阶段常见的“黑匣子”但只要你保留环境快照遇到问题conda list检查一下就能定位。5.5 随机种子不固定导致结果每次都不一样现象同一段代码跑两次打印的准确率不同同一个模型训练出来的系数也不同。原因机器学习里有很多随机过程数据划分、KNN 打乱顺序、决策树分裂特征选择、逻辑回归的求解器初始值。不固定随机种子每次运行都是一个新的随机世界复现无从谈起。解决在 notebook 最顶部统一设置全局种子import numpy as np import random np.random.seed(42) random.seed(42)然后在每个模型实例里也显式设置random_state42在train_test_split里同样写明。注意StandardScaler和 KNN 没有 random_state 参数KNN 不涉及随机过程但如果你用了交叉验证那KFold(n_splits5, shuffleTrue, random_state42)里的 seed 也必须写。我把设置种子的单元格放在第一个后边所有单元格都依赖它这是我这几年吃过不少亏后形成的硬习惯。6. 让案例能复现notebook 的种子管理、导出与调参技巧6.1 固定随机种子的完整模板除了手工在每个模型里写random_state更省事的方式是在 notebook 最顶部用一个单元格统一设置。SEED 42 def set_seed(seedSEED): np.random.seed(seed) random.seed(seed) from sklearn.model_selection import KFold return KFold(n_splits5, shuffleTrue, random_stateseed) set_seed()把种子集中管理后面所有模型都用random_stateSEED。这样你调整别的超参数时不会因为数据划分变了而无法判断是“模型真的变好了”还是“随机运气变了”。这一点在期末复习实验和项目交付时都极其重要评审老师最反感“你跑出来了但我跑不出来”的说法。6.2 快速调参用 GridSearchCV 代替手工循环当一个模型需要调三个超参数时手工在 notebook 里写 for 循环非常难维护。我更推荐直接上GridSearchCV它内部帮你做了交叉验证和结果汇总。from sklearn.model_selection import GridSearchCV param_grid { n_neighbors: [3, 5, 7], weights: [uniform, distance] } knn KNeighborsClassifier() grid GridSearchCV(knn, param_grid, cv5, scoringaccuracy) grid.fit(X_train_s, y_train) print(最佳参数:, grid.best_params_) print(交叉验证最佳得分:, grid.best_score_) print(测试集得分:, grid.score(X_test_s, y_test))cv5表示五折交叉验证scoringaccuracy指定评价指标。GridSearchCV 会遍历所有参数组合并输出最佳的三个值。注意这里一定要用标准化之后的数据否则 KNN 的网格调参没有意义。调参结束后把最佳模型从grid.best_estimator_拿出来用于后续预测。这个技巧适合所有基本模型算法只是把模型和参数网格换掉即可。但要注意网格变大后运行时间指数上升比如 3 个参数各 5 个取值就是 125 次训练在 notebook 里会等很久。我一般先用小网格粗调找到最优范围后再细化。6.3 导出 notebook 为脚本或报告实验做完不能只留在 notebook 里。我最常用的保存方式是jupyter nbconvert --to script它会把所有代码单元格按顺序导出成一个 .py 文件方便放进自动化流程。另一个是导出 HTML直接分享给看结果的人并行不通不如用--to html保持图表和代码显示对方浏览器打开就能看。jupyter nbconvert --to script mlbase_breast_cancer.ipynb jupyter nbconvert --to html mlbase_breast_cancer.ipynb用--to script导出后得到的 .py 文件里每个单元格之间的代码是连续执行的但你原来用的魔法命令比如%matplotlib inline会被注释或保留直接python xxx.py跑大概率会报错。所以如果需要离线运行我会把导出的脚本里的魔法命令手动删掉并在文件开头补上plt.show()。这不是 notebook 的缺点而是它本来就不是给纯脚本执行设计的理解这一点就不会觉得导出功能难用了。这些年我带过不少同事入门机器学习最大的教训其实只有一条基础模型怎么选、参数怎么调都不难难的是让每一步都经得起“换台机器重跑”的检验。最初我嫌固定种子和统一环境麻烦直到有一次把 notebook 发给客户对方跑出来的图和我的完全不同才意识到这些细节才是交付物的一部分。后来我每开一个实验第一件事就是建环境、写种子、设目录名。希望帮到你从这篇案例开始把每一步都留在可复现的单元格里你后面调参、抽象、换数据时会感谢这些看似琐碎的纪律。本文还有配套的精品资源点击获取