这次我们来看一个偏整理性质的主题:机器学习总结扩展。很多同学学到后期容易被算法、模型、评估指标、部署方式这些零散知识点耗尽精力,刷课的时候觉得都懂,一做项目就不知道从哪里开始调。这篇文章不是某个具体开源工具的测评,而是把机器学习从入门到落地的知识体系做一次完整梳理,同时给出一套可以直接在本地跑通的实验代码,让学习路径和工程实践能衔接起来。

内容重点包括:机器学习常见算法及应用场景、标准应用流程、环境搭建、模型训练与评估、参数调优、模型保存与 API 封装、批量预测、资源占用观察以及常见的坑。不管你是准备期末复习、转行做算法,还是已经在做机器学习相关开发,这篇文章都适合收藏后反复对照。

如果你是那种“先看能不能跑,再看怎么跑”的读者,直接从第 4 章环境准备和第 5 章本地实验开始看,几分钟就能在本地跑出一个分类模型;如果你希望完整理解体系,建议按章节顺序读一遍。

1. 核心能力速览

先把本文能提供的价值用表格列出来,方便快速判断有没有你需要的部分。

内容项 说明
知识范围 机器学习算法分类、常用算法、应用流程、特征工程、模型评估、调参、部署
编码环境 Python 3 为主,依赖 scikit-learn、pandas、numpy、matplotlib、FastAPI 可选
硬件门槛 CPU 即可完成入门实验;深度学习和超大数据集建议搭配 GPU
可运行实验 鸢尾花分类:数据加载、划分、训练、评估、调优代码可直接复用
API 服务 使用 FastAPI 封装机器学习模型推理接口,支持 POST 请求
批量任务 Python 脚本批量读取目录文件并预测,配合日志与失败重试
性能观察 训练耗时、内存占用、GPU 使用率观察方法
适合读者 机器学习初学者、转行开发者、准备面试或期末复习的同学、算法工程师

本文中的代码以 scikit-learn 自带数据集为例,不需要额外准备数据,下载和运行门槛很低。

2. 机器学习知识体系与常见算法

2.1 机器学习解决什么问题

机器学习本质是从数据中自动学习规律,并用学习到的规律对新数据做出预测或决策。它不适合规则明确、可以用传统 if-else 解决的问题,更适合数据量大、特征复杂、人工规则难以覆盖的场景。

典型应用包括:图像识别、语音识别、文本分类、推荐系统、风控反欺诈、销量预测、故障诊断等。机器学习不是万能的,它依赖数据质量、特征质量和评价指标,这三个因素往往比算法本身更影响最终效果。

2.2 算法按学习方式分类

  • 监督学习:训练数据包含输入特征和标签,模型学习从特征到标签的映射。常见任务包括分类和回归。
  • 无监督学习:训练数据没有标签,模型自动发现数据内在结构。常见任务包括聚类、降维、异常检测。
  • 半监督学习:少量有标签数据加大量无标签数据一起训练,适合标注成本高的场景。
  • 强化学习:智能体通过与环境交互获得奖励信号,学习最优策略,常用于游戏、机器人控制、推荐系统等。

2.3 常见算法清单

算法 类型 典型用途 优点 缺点
线性回归 监督学习 房价预测、销量预测 简单、可解释 对非线性关系拟合差
逻辑回归 监督学习 二分类、CTR预估 训练快、可解释 特征工程要求高
决策树 监督学习 分类、回归 可解释、不需要归一化 容易过拟合
随机森林 监督学习 分类、回归、特征重要性 抗过拟合、稳定性好 模型较大、解释性下降
XGBoost / LightGBM 监督学习 表格数据竞赛、业务预测 精度高、训练快 参数多、需要调优
SVM 监督学习 文本分类、小样本分类 小样本效果好 大数据集训练慢
KNN 监督学习 推荐、分类 简单、不用训练 预测慢、对特征尺度敏感
K-Means 无监督学习 用户分群、图像分割 简单高效 需要指定K值
PCA 无监督学习 降维、可视化、去噪 降低特征维度 损失可解释性
神经网络 / 深度学习 监督/无监督 图像、语音、文本 拟合能力强 需要数据和算力

实际项目中不需要把所有算法都跑一遍,更合理的思路是:先确定任务类型,再用线性模型或树模型做 baseline,最后根据效果决定是否升级到复杂模型。

2.4 模型选择思路

选择算法时先看数据形态。表格数据优先尝试逻辑回归、随机森林、XGBoost;图像数据优先使用 CNN 类模型;文本数据优先使用 Transformer 类模型;如果数据量小且要求可解释性,优先用决策树或线性模型。

模型复杂度不是越高越好。小数据集上复杂模型容易过拟合,简单模型反而泛化能力更好。正确的做法是从简单模型开始,建立 baseline,再逐步增加复杂度。

3. 机器学习标准应用流程

很多人学了一堆算法,但实际做项目时不知道从哪一步开始。标准流程大致如下:

3.1 问题定义与指标选择

先确认是分类、回归、聚类还是排序问题,再定义成功指标。分类问题常用准确率、精确率、召回率、F1、AUC;回归问题常用 MAE、MSE、RMSE、R2;排序问题常用 NDCG、MAP。

指标必须贴合业务。例如在风控场景中,关注的是少数正样本能不能被识别出来,所以召回率比准确率更重要;在广告点击率预测中,AUC 和 LogLoss 更常用。

3.2 数据采集与清洗

数据是机器学习的上限。需要确认数据来源、字段含义、时间范围、样本量级。清洗阶段主要处理:

  • 缺失值:删除、填充均值/中位数/众数,或者用模型预测填充;
  • 异常值:通过箱线图、3σ 原则识别,再决定删除或修正;
  • 重复值:去重,避免同一份样本重复参与训练导致结果虚高;
  • 错误数据:类型错乱、范围不合理的数据需要单独处理。

3.3 特征工程与特征选择

特征工程是机器学习中最耗时的部分之一。常见操作包括:

  • 数值特征:归一化、标准化、分箱、取对数、构造交叉特征;
  • 类别特征:LabelEncoder、OneHotEncoder、TargetEncoder;
  • 时间特征:提取年、月、日、星期、是否节假日等;
  • 文本特征:TF-IDF、词向量、句子向量;
  • 特征选择:过滤法、包裹法、嵌入法,随机森林和 XGBoost 也自带特征重要性。

特征工程的目标不是特征越多越好。冗余特征会增加训练时间、降低模型解释性,甚至带来数据泄露风险。

3.4 数据集划分与验证策略

模型需要在训练集上学习,在验证集上调参,在测试集上做最终评估。常见划分方式包括:

  • Hold-out:按比例随机划分训练集、验证集、测试集;
  • K-Fold 交叉验证:把数据分成 K 份,每次取 K-1 份训练、1 份验证,循环 K 次;
  • Stratified K-Fold:保持每折中类别比例一致,适合分类问题。

时间序列数据不能随机打乱,必须按时间先后划分,否则会引入未来信息,造成数据泄露。

3.5 模型训练与对比

先在同一个验证集上训练多个 baseline 模型,对比指标后再选择最优模型做进一步调优。训练时要固定随机种子,保证结果可复现。

3.6 模型评估与可解释性

评估阶段不仅要看整体指标,还要看分维度表现。例如分类模型可以查看混淆矩阵、每个类别的精确率和召回率;回归模型可以绘制预测值 vs 真实值散点图;树模型可以分析特征重要性。

可解释性工具包括 SHAP、LIME、Partial Dependence Plot。在风控、医疗等场景中,可解释性往往是上线的前置条件。

3.7 上线与监控

模型上线后不代表结束,需要持续监控数据分布变化、预测结果分布、指标衰减情况。常见的监控方案是把模型预测结果、特征分布写入日志,定期做报表和告警。

4. 环境准备与前置条件

本文所有实验代码只需要 CPU 即可运行,不需要独立 GPU。建议配置如下:

  • 操作系统:Windows 10/11、Ubuntu 20.04+、macOS 均可;
  • Python 版本:建议 Python 3.10 或 3.11,尽量使用 64 位版本;
  • 依赖库:numpy、pandas、scikit-learn、matplotlib、joblib、fastapi、uvicorn、requests;
  • 开发工具:Jupyter Notebook、VS Code、PyCharm 任选其一;
  • 磁盘空间:安装依赖和保存模型大约需要 2GB 左右空间。

如果你使用 Anaconda,可以创建独立虚拟环境,避免依赖冲突:

conda create -n ml-summary python=3.10 -y
conda activate ml-summary

如果使用 pip,也可以直接创建 venv:

python -m venv ml-summary
# Windows
ml-summary\Scripts\activate
# Linux / macOS
source ml-summary/bin/activate

安装依赖:

pip install numpy pandas scikit-learn matplotlib joblib
pip install fastapi uvicorn requests

如果是在国内网络环境,可以添加镜像源加速安装:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy pandas scikit-learn matplotlib joblib

安装完成后,可以检查核心库版本,确认环境是否正常:

python -c "import sklearn, pandas, numpy; print('sklearn:', sklearn.__version__); print('pandas:', pandas.__version__); print('numpy:', numpy.__version__)"

如果输出正常,说明环境已准备好。

5. 本地快速实验:从数据到模型的完整代码

这一章用 scikit-learn 自带的鸢尾花数据集,完成一个完整分类实验。整个过程包括数据加载、训练集测试集划分、模型训练、预测、评估和可视化。

5.1 加载数据并查看结构

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris

iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Series(iris.target, name="target")

print(X.shape)
print(X.head())
print(y.value_counts())

数据包含 150 个样本、4 个特征,目标变量是 3 类鸢尾花。这个数据集很干净,适合用来验证代码流程。

5.2 划分训练集和测试集

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
print("训练集大小:", X_train.shape)
print("测试集大小:", X_test.shape)

这里设置 stratify=y ,保证训练集和测试集中各类别比例与原数据一致。 random_state=42 保证每次运行结果一致。

5.3 训练随机森林模型

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

训练完成后,可以查看特征重要性:

importance = pd.DataFrame({
    "feature": X.columns,
    "importance": model.feature_importances_
}).sort_values("importance", ascending=False)
print(importance)

5.4 模型预测与评估

from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
print("分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))

在鸢尾花数据集上,随机森林通常能取得很好效果。如果你的输出出现某些类别精确率或召回率很低,可以先检查数据划分是否正常,或者样本量是否太少。

5.5 使用 Pipeline 封装预处理和模型

实际项目中,预处理不能只做在训练集上,测试集也要用相同的预处理逻辑。Pipeline 可以把标准化、降维、模型训练封装成一个整体,避免重复写代码。

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline

pipeline = Pipeline([
    ("scaler", StandardScaler()),
    ("pca", PCA(n_components=2)),
    ("clf", RandomForestClassifier(n_estimators=100, random_state=42))
])

pipeline.fit(X_train, y_train)
print("Pipeline 测试集准确率:", pipeline.score(X_test, y_test))

这种做法更接近工业界的标准结构,后续换模型、加预处理步骤只需要改 Pipeline 配置,不用改训练和测试代码。

6. 模型调优与批量验证

6.1 交叉验证

只用一次划分的结果容易受随机性影响。更可靠的评估方式是做 K-Fold 交叉验证:

from sklearn.model_selection import cross_val_score

scores = cross_val_score(model, X, y, cv=5, scoring="accuracy")
print("5折交叉验证得分:", scores)
print("平均得分:", scores.mean())
print("标准差:", scores.std())

交叉验证得到的平均分可以更稳定地反映模型泛化能力。在实际比赛中,交叉验证分数和本地测试集分数要结合观察。

6.2 超参数搜索

随机森林需要调节的参数包括 n_estimators max_depth min_samples_split 等。scikit-learn 提供 GridSearchCV RandomizedSearchCV 两种方式。

from sklearn.model_selection import GridSearchCV

param_grid = {
    "n_estimators": [50, 100],
    "max_depth": [None, 5, 10],
    "min_samples_split": [2, 5]
}

grid_search = GridSearchCV(
    RandomForestClassifier(random_state=42),
    param_grid,
    cv=5,
    scoring="accuracy",
    n_jobs=-1
)
grid_search.fit(X_train, y_train)

print("最优参数:", grid_search.best_params_)
print("最优得分:", grid_search.best_score_)
print("测试集得分:", grid_search.score(X_test, y_test))

n_jobs=-1 表示使用所有 CPU 核心并行计算,会明显加快搜索速度。数据量大时网格搜索会非常耗时,建议先用 RandomizedSearchCV 缩小范围,再做精细搜索。

6.3 批量训练多模型

很多时候需要同时比较多模型的效果。可以写一个列表统一训练:

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier

models = [
    ("Logistic Regression", LogisticRegression(max_iter=1000, random_state=42)),
    ("SVM", SVC(random_state=42)),
    ("Random Forest", RandomForestClassifier(n_estimators=100, random_state=42))
]

for name, clf in models:
    scores = cross_val_score(clf, X, y, cv=5, scoring="accuracy")
    print(f"{name}: {scores.mean():.4f} (+/- {scores.std():.4f})")

通过对比不同模型的交叉验证平均分,可以快速选出 baseline 最优点。

7. 封装 API 服务与批量预测

模型训练好之后,如果希望业务系统调用,通常会封装成 API。这一章以 FastAPI 为例,把训练好的随机森林模型保存到文件,再通过 HTTP 接口提供服务。

7.1 保存模型

import joblib

joblib.dump(model, "iris_rf_model.joblib")
print("模型已保存")

同时把特征名称也保存下来,方便接口侧做参数校验:

joblib.dump(list(X.columns), "iris_feature_names.joblib")

7.2 使用 FastAPI 提供推理接口

创建一个 app.py 文件,内容如下:

from fastapi import FastAPI
from pydantic import BaseModel
import joblib
import numpy as np

app = FastAPI(title="Iris Classifier API")

model = joblib.load("iris_rf_model.joblib")
feature_names = joblib.load("iris_feature_names.joblib")

class PredictRequest(BaseModel):
    features: list

class PredictResponse(BaseModel):
    prediction: int
    probabilities: list

@app.post("/predict")
def predict(req: PredictRequest):
    if len(req.features) != len(feature_names):
        return {"error": f"Expected {len(feature_names)} features, got {len(req.features)}"}
    arr = np.array(req.features).reshape(1, -1)
    pred = model.predict(arr)[0]
    proba = model.predict_proba(arr)[0].tolist()
    return PredictResponse(prediction=int(pred), probabilities=proba)

@app.get("/health")
def health():
    return {"status": "ok"}

启动服务:

uvicorn app:app --host 127.0.0.1 --port 8000

启动后,打开 http://127.0.0.1:8000/docs 可以看到 Swagger 接口文档,也可以直接调试接口。

7.3 curl 调用接口

curl -X POST "http://127.0.0.1:8000/predict" \
  -H "Content-Type: application/json" \
  -d '{"features": [5.1, 3.5, 1.4, 0.2]}'

返回示例:

{
  "prediction": 0,
  "probabilities": [0.97, 0.03, 0.0]
}

7.4 Python 调用接口

import requests

url = "http://127.0.0.1:8000/predict"
payload = {
    "features": [6.2, 3.4, 5.4, 2.3]
}

response = requests.post(url, json=payload, timeout=10)
print(response.status_code)
print(response.json())

这里注意,接口只是演示。生产环境必须加鉴权、限流、超时和返回值校验,避免未授权访问和恶意请求。

7.5 批量预测脚本

如果有一批数据需要进行离线预测,可以直接写脚本批量读取、批量预测,并把结果写入 CSV。

import pandas as pd
import joblib

model = joblib.load("iris_rf_model.joblib")
feature_names = joblib.load("iris_feature_names.joblib")

df = pd.read_csv("new_data.csv")
X_new = df[feature_names].values

predictions = model.predict(X_new)
probabilities = model.predict_proba(X_new)

df["prediction"] = predictions
df["prob_class0"] = probabilities[:, 0]
df["prob_class1"] = probabilities[:, 1]
df["prob_class2"] = probabilities[:, 2]

df.to_csv("new_data_with_predictions.csv", index=False)
print("批量预测完成,结果已保存")

批量任务建议加日志、断点续跑和失败重试机制。例如每处理 100 条输出一次进度,如果某条数据格式异常,先记录下来,不影响整体任务继续执行。

8. 资源占用与性能观察

机器学习实验不仅要看模型指标,还要关注资源和耗时。运行训练任务时,可以通过以下方式观察资源占用。

8.1 CPU 和内存占用

如果使用 Linux 服务器,可以用 top htop 查看:

top

如果使用 Windows,可以打开任务管理器,在“性能”标签页查看 CPU 和内存使用率。Python 的 psutil 也可以在代码中实时打印:

import psutil

print("CPU 使用率:", psutil.cpu_percent(interval=1))
print("内存使用率:", psutil.virtual_memory().percent)

8.2 GPU 使用情况

如果使用深度学习或 XGBoost GPU 版本,可以观察显存和 GPU 利用率:

nvidia-smi

如果 nvidia-smi 中看不到 Python 进程,说明模型没有调用 GPU,需要检查 CUDA、cuDNN 和深度学习框架版本是否匹配。

8.3 影响性能的关键因素

  • 数据量:样本数越多,训练时间越长;
  • 特征维度:高维特征会明显增加内存占用和训练时间;
  • 模型复杂度:深层神经网络、大规模集成模型训练耗时更长;
  • 超参数:树的数量、网络层数、批量大小都影响训练速度;
  • 并行度: n_jobs device 参数、多卡设置影响资源利用率。

8.4 降低资源占用的方法

  • 在保持效果的前提下降低特征维度;
  • 先在小样本子集上测试代码,确认无误再全量训练;
  • 使用增量训练或分布式训练;
  • 对文本和图像数据使用预处理缓存,避免重复加载;
  • 减少不必要的日志输出,日志频繁写入磁盘会影响 IO。

9. 常见问题与排查方法

问题现象 可能原因 排查方式 解决方案
依赖安装失败 Python 版本不匹配、缺少编译环境 检查 Python 版本、使用 venv 更换 Python 版本或使用 conda 环境
模型训练后准确率很低 特征未预处理、数据泄露、样本不均衡 检查数据分布、验证集划分 加入标准化、使用分层采样、调整类别权重
验证集效果好但测试集差 过拟合 观察训练集和验证集差距 增加正则化、减少模型复杂度、增加数据量
模型运行报“特征数量不匹配” 训练和预测时特征不一致 打印特征列表对比 确保特征顺序统一、保存特征名称
API 请求超时 推理时间过长、服务线程不够 查看服务日志、请求耗时 增加超时时间、优化模型、添加并发配置
批量任务卡住 数据格式异常、网络超时 加日志定位卡住位置 增加 try-except 和重试机制
显存不足 批量大小过大、输入分辨率过高 观察 nvidia-smi 显存占用 减小 batch_size 或降低分辨率
输出结果不稳定 随机种子未固定 检查 random_state 是否固定 设置全局随机种子

另外,很多初学者会遇到数据泄露问题。比如先对全量数据做归一化,再划分训练集和测试集,这就导致测试集的信息混入训练集。正确做法是先划分数据,再在训练集上 fit 预处理参数,然后 transform 测试集。

10. 最佳实践与使用建议

10.1 从最小可行实验开始

不要一上来就训练大模型。先用一部分数据、简单模型、少量参数跑通整个流程,确认代码没问题后再放大规模。

10.2 保留一套可复现配置

固定随机种子、固定依赖版本、记录模型参数和数据版本,方便后续复盘。可以在代码里统一设置随机种子:

import random
import numpy as np

random.seed(42)
np.random.seed(42)

如果是深度学习,还需要设置 PyTorch 或 TensorFlow 的随机种子。

10.3 文件目录分模块管理

推荐这样的目录结构:

project/
├── data/
│   ├── raw/
│   ├── processed/
│   └── predictions/
├── notebooks/
├── src/
│   ├── data_preprocessing.py
│   ├── train.py
│   ├── predict.py
│   └── api.py
├── models/
├── logs/
└── config/

模型文件、输入数据、输出结果不要混在一起,否则后期清理和维护成本很高。

10.4 接口服务安全边界

API 服务启动后,除非有明确需求,否则不要绑定 0.0.0.0 暴露到公网。本地调试建议使用 127.0.0.1 。生产环境需要加 API Key、请求频率限制、输入校验和访问日志。

10.5 数据与合规提醒

如果使用真实用户数据训练模型,必须确认数据采集和使用的授权范围。涉及人脸、声音、医疗、金融等敏感数据时,需要做匿名化处理,并遵守相关法规。训练和部署环境建议使用脱敏测试数据,避免隐私泄露风险。

10.6 发布前做效果复核

模型在实验室指标好不代表生产环境效果好。上线前需要在真实业务数据上进行小流量验证,观察不同时间段、不同用户群体的表现差异。如果效果波动,要先检查数据分布是否发生变化,再决定是否重新训练。

11. 总结与下一步

这次整理的机器学习总结扩展覆盖了从概念到落地的完整链路:算法体系、应用流程、开发环境、训练评估、调优方法、API 封装和批量预测。对初学者来说,最有价值的不是记下所有算法公式,而是先跑通第 5 章的完整实验流程;对已经做过项目的开发者来说,可以重点对照第 7 章到第 10 章的工程化内容,检查自己在部署、监控和合规方面是否有遗漏。

最容易踩的坑有三个:一是忽略数据泄露,先全量预处理再划分数据集;二是只关注测试集分数,不关注模型在真实场景中的稳定性;三是训练好模型后不知道如何对外提供服务,导致算法和业务系统脱节。

下一步可以继续扩展的方向包括:深度学习模型迁移到图像或文本任务、使用 SHAP 提升模型可解释性、学习模型监控与自动重训机制、尝试用 Docker 容器化部署推理服务。建议先保存这篇文章,等到需要做本地实验或面试复习时,再对照里面的代码和流程,把机器学习真正变成自己手中的工具。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐