简介:这是一套基于Jupyter Notebook的机器学习入门实践资源,面向希望从零掌握常见算法并落地代码的Python开发者与数据科学初学者。内容覆盖数据预处理、线性回归、逻辑回归、决策树、随机森林、SVM、K-Means聚类以及模型评估与参数调优,配有房价预测、贷款违约、市场细分、手写数字识别等案例,帮助读者理解算法原理并在Notebook中逐步复现完整流程。资源共25个文件,以10个Markdown说明文档、8个Jupyter Notebook代码、3个CSV数据集为主,另含Python脚本与配置文件,压缩包仅2.97MB,轻量易下载,结构按模型模块归类,便于按需查阅。已有2044人学习,适合作为课内实验或自学实战的参照资料。通过学习,读者可以获得从数据清洗、特征工程到模型训练与评估的完整思路,以及可直接运行的示例代码和配套数据,快速搭建自己的机器学习项目。
1. 为什么应该在 Jupyter Notebook 里学习机器学习基本模型算法
Jupyter Notebook 常被当成高级记事本:整段脚本丢进单元格运行,和直接跑 Python 文件没区别。真正有用的用法,是把数据形状、模型参数、输出结果拆成独立可改的单元。机器学习基本模型算法的难点在参数敏感性:决策树不加 max_depth,训练集接近 100%、测试集下滑;KNN 把 n_neighbors 从 1 改成 5,决策边界立刻变平滑。这种直觉靠背公式很难建立,在 Jupyter 里边改边看图却很自然。接下来按“搭环境、认算法、跑三个模型、做一个附加案例”的顺序展开,新手能逐步复现,熟手可直接看后文的参数边界和踩坑点。
2. 在 Jupyter Notebook 搭建机器学习算法环境:安装、镜像与算法选型
2.1 用 Miniconda 在本地跑通 Jupyter Notebook 的最小命令
“机器学习 python 环境配置”是入门遇到的第一个坎,常见问题是系统 Python 里装着老版本 numpy,再 pip install scikit-learn 时把整个环境弄崩。我一般用 Miniconda 把机器学习环境隔离出来,后续即使模型包升级失败,删掉这个环境重来即可。终端执行:
conda create -n mlp python=3.11 -y conda activate mlp pip install jupyterlab notebook numpy pandas matplotlib seaborn scikit-learn python -m ipykernel install --user --name mlp第一行创建独立环境 mlp,并固定 Python 3.11,避免依赖随系统更新漂移;第二行激活环境,后续所有包都装进 mlp 里;第三行一次装齐 Jupyter 和数据科学常用库,其中 jupyterlab 负责网页端交互,notebook 是经典界面,scikit-learn 提供本次要用到的大部分机器学习模型算法;第四行把当前环境注册为 Jupyter 内核。注册完启动即可:
jupyter notebook浏览器打开后,新建 Notebook 时选择 mlp 内核。如果下载慢,把 pip 临时指向国内镜像源再重复安装命令即可,不建议在系统 Python 里硬装。
这个流程解决的是“环境隔离”和“内核识别”两个问题。之后每次换机器,只需重跑这几行命令。实际使用中,如果从 conda 某环境切回 base 后找不到内核,通常不是安装失败,而是内核注册信息没刷新,这时运行jupyter kernelspec list看看当前可用名称再判断。
2.2 机器学习基本模型算法有哪些:一张表看清分类与回归
机器学习期末复习时最常被问到的就是“有哪些基本模型”,很多教材喜欢按李宏毅的课程或周志华《机器学习》书里的顺序排,但落到代码层面,其实用一张表就能说清:
| 模型 | 监督类型 | 典型任务 | 适合场景 | 可解释性 |
|---|---|---|---|---|
| 线性回归 | 回归 | 房价、销量预测 | 特征与目标接近线性 | 高 |
| 逻辑回归 | 分类 | 点击率、患病概率 | 二分类基线 | 高 |
| 决策树 | 分类/回归 | 规则提取、风控 | 小样本且需要解释 | 很高 |
| KNN | 分类/回归 | 推荐、图像分类 | 低维、样本量适中 | 中 |
| 朴素贝叶斯 | 分类 | 文本分类 | 高维稀疏特征 | 中 |
| SVM | 分类/回归 | 文本、图像小样本 | 中等样本、特征稠密 | 低 |
这些模型的差别不在准确率,而在归纳偏好:线性模型假设类别边界接近线性,KNN 假设相近的样本有相近输出,决策树则用一组特征阈值把样本逐步切开。没有谁绝对最优,scikit-learn 自带数据集里很多任务用逻辑回归就能跑出不错的基线。学习时不要在“哪个算法更强”上纠结,先弄清楚各自的假设适不适合当前数据。
2.3 算法选型的三条经验
选型可以按三条线记,比背算法流程图更快落地:
- 从简单开始:回归问题先跑线性回归,分类问题先跑逻辑回归,把它们的指标当作基线。基线差到不能看,再换复杂模型才有意义。
- 看解释需求:业务要求说清“为什么判负”,优先决策树,因为可以输出路径规则;如果只是预测概率,SVM 或集成模型放在后期再试。
- 数据规模决定选择:样本几千以内,决策树、KNN、逻辑回归足够;到几十万上百万样本,KNN 因每条样本都要算距离,延迟明显上升,线性模型和树模型更合适。
在 Jupyter 里落实这三条经验,就是给每个模型开一个单元格,用同一个cross_val_score跑一遍,比较均值和标准差。理解了单棵树之后,再看随机森林、梯度提升树这些“多个决策树组合”的思路会轻松得多。
3. 用 Jupyter Notebook 跑通三个机器学习基本模型算法:线性回归、KNN 与决策树
下面的代码按“一个模型一组单元格”组织,数据处理、模型训练、结果可视化分区放,不要把所有代码塞进一个格子里,否则又回到“跑大脚本”的老路。
3.1 线性回归:先看系数,再谈 R2
先用 scikit-learn 内置的糖尿病数据集跑一个多元线性回归:
from sklearn.datasets import load_diabetes from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split import pandas as pd diabetes = load_diabetes() X = pd.DataFrame(diabetes.data, columns=diabetes.feature_names) y = pd.Series(diabetes.target, name="target") X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42) model = LinearRegression() model.fit(X_train, y_train) print("系数:", model.coef_) print("截距:", round(model.intercept_, 4)) print("R2:", round(model.score(X_test, y_test), 4))load_diabetes()读取内置的 442 条数据,无需联网下载;train_test_split按 8:2 切分,random_state=42保证每次运行结果一致,方便复现和对比。model.coef_是 10 个特征的系数,正数代表该特征越大目标值越高,负数相反,这是线性回归最直接的可解释输出。score返回 R2,表示模型解释目标值方差的比例,这个数据集上普通线性回归得到 0.4 到 0.5 是正常水平,不用因为不是 0.9 就怀疑代码出错。
跑完后建议做一个实验:在训练前加一步StandardScaler标准化,再跑一遍同一个模型。线性回归对特征尺度不敏感,R2 几乎不变,这个结论能帮助你理解后来的 KNN 和 SVM 为什么要标准化,而树模型不需要。
3.2 KNN 分类器:调 n_neighbors 看到过拟合
KNN 是所有机器学习基本模型算法里最没有“训练”过程的:它把训练样本直接存下来,预测新样本时算它与所有记忆样本的距离再投票。唯一关键参数是邻居数n_neighbors,在 Jupyter 里最适合用循环看变化:
from sklearn.datasets import load_iris from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import cross_val_score X, y = load_iris(return_X_y=True) for k in [1, 3, 5, 7, 10, 15]: knn = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn, X, y, cv=5) print(f"k={k:2d} acc={scores.mean():.4f} std={scores.std():.4f}")cross_val_score把数据分成 5 份,每份轮流做验证集,得到 5 个准确率后取均值和标准差,比单次train_test_split更可信。运行输出通常能看到:k=1 时准确率不一定最高,且标准差偏大;k 到 5 到 7 附近达到峰值;继续增大后开始下滑。k=1 的决策区域完全贴着训练数据,属于典型过拟合,k=15 又因为决策边界太粗糙而欠拟合。KNeighborsClassifier还有一个值得对比的参数weights,默认uniform表示所有邻居一票平等,改成distance后距离越近权重越大,通常会带来一两个百分点的变化,但也更容易受局部噪声影响。
3.3 决策树:max_depth 与预剪枝
决策树是可解释性最高的分类器,训练后能输出一条明确的“特征 <= 阈值”路径,业务方接受度远高于 SVM。但它的过拟合风险也最明显:不加限制时,树会一直长到每个叶子只含一条样本,训练集接近满分。Jupyter 里可以直接观察这个变化:
from sklearn.datasets import load_iris from sklearn.tree import DecisionTreeClassifier, plot_tree import matplotlib.pyplot as plt iris = load_iris() model = DecisionTreeClassifier(max_depth=3, min_samples_leaf=5, random_state=0) model.fit(iris.data, iris.target) plt.figure(figsize=(12, 6)) plot_tree(model, filled=True, feature_names=iris.feature_names, class_names=iris.target_names) plt.show()max_depth=3限制树的层数,min_samples_leaf=5要求每个叶子至少包含 5 个样本,这两个参数组合起来就是“预剪枝”的常用手段。很多文章把max_depth直接叫剪枝,严格说它只是限制高度,真正剪枝还要结合叶子样本量、基尼增益阈值等条件。把max_depth从 2 改到 8 逐个跑一遍,训练集准确率递增、测试集先升后降的过程非常直观。plot_tree输出的树结构可以直接截图放进周报或课程报告,叶子颜色深浅代表类别概率。
DecisionTreeClassifier的criterion参数默认gini,改成entropy后树的形态可能不同,但在这个数据集上效果差别很小。入门阶段固定一个标准,重点研究max_depth和min_samples_leaf就够用。
4. 附加案例:用乳腺癌公开数据集把机器学习算法从 EDA 串到调参
前面对三个模型做了单独演示,这一节放进同一个附加案例,完整走一遍:读数据、EDA、建模比较、调参。数据集用load_breast_cancer,属于 scikit-learn 内置的公开数据,不需要额外下载,适合直接复现。
4.1 建模前先看数据:缺失值、数值范围和类别分布
from sklearn.datasets import load_breast_cancer import pandas as pd import seaborn as sns import matplotlib.pyplot as plt data = load_breast_cancer() df = pd.DataFrame(data.data, columns=data.feature_names) df["target"] = data.target print(df.shape) print(df.isnull().sum().sum()) print(df.describe().T[["mean", "min", "max"]]) print(df["target"].value_counts()) sns.countplot(x="target", data=df) plt.xticks([0, 1], data.target_names) plt.show()输出要点:样本 569 个、特征 30 个,缺失值数量为 0,正负样本比例约 1.3:1,属于比较均衡的二分类。更值得看的是describe里的 min 和 max:mean radius范围在 7 到 30,mean concavity可能在 0 到 0.5,量纲差距接近两个数量级。这一观察直接决定了后面必须做标准化。很多入门教程跳过这步直接 fit,Notebook 里不会报错,但 KNN 和 SVM 这类基于距离的模型,结果会明显偏移。
4.2 用 Pipeline 把标准化放进交叉验证,避免数据泄漏
常见错误是“先标准化全量数据,再切分训练测试集”。标准化器在全量数据上算均值方差,等于把测试集信息代入训练过程,验证指标会偏乐观。正确做法是把标准化放进交叉验证的每一折内部:
from sklearn.model_selection import cross_val_score from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier X = df.drop(columns="target") y = df["target"] models = { "logistic": LogisticRegression(max_iter=2000), "knn": KNeighborsClassifier(n_neighbors=5), "tree": DecisionTreeClassifier(max_depth=3, random_state=0), } for name, clf in models.items(): pipe = make_pipeline(StandardScaler(), clf) scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy") print(f"{name:8s} acc={scores.mean():.4f} std={scores.std():.4f}")make_pipeline(StandardScaler(), clf)把标准化和模型包成一个整体,交叉验证切出的每个训练折都先拟合 scaler,再用同一组均值方差去变换对应的验证折,杜绝信息泄漏。三个模型跑完后,逻辑回归和 KNN 标准化后通常接近,决策树则不论是否标准化差异都小,这与树模型按阈值切分、不依赖距离度量一致。准确率对类别不平衡不够敏感,但这个案例样本均衡,可以先用 accuracy 做横向比较,之后再补recall或roc_auc。
4.3 用 GridSearchCV 同时调两个超参数
交叉验证发现“标准化 + KNN”值得继续优化后,进入参数搜索。新手最容易用双重 for 循环手动调参,能跑但代码冗长且无法自动比较。scikit-learn 的GridSearchCV更适合:
from sklearn.model_selection import GridSearchCV from sklearn.neighbors import KNeighborsClassifier pipe = make_pipeline(StandardScaler(), KNeighborsClassifier()) params = { "kneighborsclassifier__n_neighbors": [3, 5, 7, 10], "kneighborsclassifier__weights": ["uniform", "distance"], } grid = GridSearchCV(pipe, params, cv=5, scoring="accuracy") grid.fit(X, y) print("best params:", grid.best_params_) print("best score:", round(grid.best_score_, 4)) print(grid.cv_results_["mean_test_score"])params的 key 用双下划线__连接,左边是子估计器在管道中的名字,右边才是它的参数名,这是 Pipeline 的固定语法。GridSearchCV对每组参数组合执行 5 折交叉验证,这里共 4×2×5=40 次模型拟合,在 569 条样本上几秒内跑完。best_score_是调参后的平均准确率,mean_test_score输出各组参数明细,方便看出哪一组波动最大。调完后用同一个流程换LogisticRegression(C=0.1)再跑一次,你会发现逻辑回归对 C 的敏感度通常低于 KNN 对 n_neighbors 的敏感度,这个结论在实际项目中很有参考价值。
5. 两个留在最后的实操技巧:重复验证与 Jupyter Notebook 无法运行排查
案例跑通不意味着流程结束,还要养成两个习惯:不要用单次切分结果汇报;报错时先分清是环境问题还是模型代码问题。
5.1 用重复交叉验证代替单次结果
交叉验证比单次切分稳定,但它仍有随机成分。换一个random_state,准确率可能从 90.4% 变成 91.1%。我一般用重复实验看波动:
import numpy as np from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression accs = [ cross_val_score(LogisticRegression(max_iter=2000), X, y, cv=5).mean() for _ in range(10) ] print("mean:", round(np.mean(accs), 4)) print("std:", round(np.std(accs), 4))如果标准差超过 0.02,说明模型对这个数据集的划分方式敏感,报告里应同时给出均值和标准差,而不是只写“准确率 91%”。这个习惯比调出 0.5 个百分点有意义得多。
5.2 Jupyter Notebook 无法运行的三步排查
“jupyter notebook 无法运行”大多能在三步内定位。第一步看报错位置:如果浏览器能打开,执行代码时报Kernel Restarting,基本是 Python 环境包冲突,处理方式是新建 conda 环境重装一套依赖,而不是在原环境里继续 pip install。第二步看端口:启动时提示端口占用,改用jupyter notebook --no-browser --port=8899。第三步看内核:切换 conda 环境后 Kernel 列表找不到新环境,执行python -m ipykernel install --user --name mlp重新注册,再用jupyter kernelspec list确认。还有一个易踩的坑:Jupyter 里运行的并非当前激活环境,可以在单元格里执行import sys; sys.executable看打印出的 Python 路径,路径不对就重新选择内核。排查掉这些之后,余下最高概率的报错是ValueError: Input contains NaN,那就不是环境问题,该回头检查数据清洗了。
提示:写机器学习代码时,每改动一个参数就重新运行一次当前单元格,看到输出后再改下一个,这是 Jupyter Notebook 比普通脚本更适合算法实验的根本原因。
本文还有配套的精品资源,点击获取