机器学习教程

机器学习(Machine Learning)是人工智能的核心分支:让计算机从数据中自动学习规律,而不需要显式编程。它已广泛应用于推荐系统、图像识别、语音助手、风控等场景。

学习本教程你将掌握

模块内容
基础概念模型、特征、标签、训练/测试
经典算法线性回归、决策树、SVM、KNN、聚类
模型评估准确率、精确率、交叉验证
实践项目房价预测、客户分群、泰坦尼克预测
💡 提示
机器学习 ≠ 深度学习:深度学习是机器学习的一个子集(基于神经网络)。本教程从传统机器学习入门,再过渡到深度学习。

机器学习简介

机器学习(Machine Learning, ML)指通过算法让计算机从数据中学习规律并进行预测或决策。传统编程是人写规则,机器学习是数据 + 算法 → 自动产生规则。

与传统编程的区别

传统编程机器学习
人工定义规则算法自动学习规则
输入数据 + 规则 → 输出输入数据 + 输出 → 学习规则
规则固定规则随数据更新
# 传统编程:手写规则
def is_spam(msg):
    return '中奖' in msg or '点击链接' in msg

# 机器学习:从标注数据学习
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train)   # 自动学习
pred = model.predict(X_test)

三大类型

类型任务示例
监督学习有标签数据分类、回归
无监督学习无标签数据聚类、降维
强化学习试错 + 奖励游戏、机器人控制

机器学习学习路线

学习机器学习建议按以下路线循序渐进,先重实践、后深理论:

阶段内容目标
1. 语言基础Python + NumPy + Pandas能处理数据
2. 可视化Matplotlib + Seaborn能看懂数据
3. 经典算法回归/分类/聚类/降维掌握 sklearn
4. 模型评估交叉验证/指标/调参能评估模型
5. 实践项目Kaggle 入门竞赛完整流程
6. 深度学习神经网络/PyTorch进阶方向
✅ 建议
不要一开始就啃数学推导。先用 sklearn 跑通流程,遇到问题时再补线性代数、概率论知识,效率最高。

机器学习生命周期

一个完整的机器学习项目遵循生命周期(ML Lifecycle):

阶段关键工作
1. 问题定义明确业务目标与成功指标
2. 数据收集采集、标注、整合数据
3. 数据清洗缺失值、重复值、异常值
4. 特征工程构造、选择、缩放特征
5. 建模选择算法并训练
6. 评估交叉验证、指标分析
7. 部署监控上线、监控、迭代
⚠️ 注意
实际项目中 70% 以上的时间花在数据清洗与特征工程,而不是模型调参。

机器学习如何工作

机器学习如何工作?用一个简单例子理解核心机制——线性回归:

import numpy as np
import matplotlib.pyplot as plt

# 数据:房屋面积 -> 价格
X = np.array([50, 60, 70, 80, 90, 100])   # 面积(m²)
y = np.array([150, 180, 210, 240, 270, 300])  # 价格(万)

# 训练线性模型:y = w*x + b
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X.reshape(-1, 1), y)

# 预测 75m² 的价格
print(model.predict([[75]]))   # ~225 万

# 学习到的参数
print(model.coef_, model.intercept_)  # w≈3, b≈0

核心思想:模型先随机猜测 w、b,通过损失函数衡量预测误差,再用梯度下降反复调整参数,直到误差最小。

机器学习基础术语

机器学习的基础术语必须清晰:

术语含义示例
样本(Sample)一条数据一个用户、一笔订单
特征(Feature)输入变量年龄、收入、地区
标签(Label)要预测的目标是否购买、房价
训练集用于学习的样本80% 数据
测试集用于评估的样本20% 数据
模型(Model)学习到的函数f(x) → y
过拟合学得太死,泛化差训练好测试差
欠拟合没学好训练测试都差
💡 提示
理解"特征 × 标签"的映射关系是机器学习建模的起点。

Python 入门机器学习

用 Python 入门机器学习,环境准备三步:

# 1. 安装核心库
pip install numpy pandas scikit-learn matplotlib seaborn

# 2. 验证环境
python -c "import sklearn; print(sklearn.__version__)"
# 3. 一个最小可运行示例
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

# 加载鸢尾花数据集
iris = load_iris()
X, y = iris.data, iris.target

# 划分训练/测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42)

# 训练决策树
model = DecisionTreeClassifier()
model.fit(X_train, y_train)

# 评估
print('准确率:', model.score(X_test, y_test))
✅ 建议
推荐使用 Anaconda 或 Jupyter Notebook 交互式学习。

Python 机器学习库

Python 机器学习生态核心库:

库用途
NumPy数值计算、数组
Pandas数据处理、表格
Matplotlib绘图可视化
Seaborn统计可视化(更美观)
Scikit-learn经典机器学习算法(主力)
PyTorch / TensorFlow深度学习
XGBoost / LightGBM梯度提升树(竞赛利器)
💡 提示
本教程的算法部分主要使用 Scikit-learn,它封装了几乎所有经典算法,API 统一,适合入门。

常用数据类型

机器学习中常用的数据表示:

import numpy as np
import pandas as pd

# 特征矩阵 X:二维数组(样本 × 特征)
X = np.array([
    [25, 5000],   # 年龄, 收入
    [30, 8000],
    [35, 10000]
])

# 标签向量 y:一维数组
y = np.array([0, 1, 1])   # 0 否 1 是

# 更常用:Pandas DataFrame
df = pd.DataFrame(X, columns=['age', 'income'])
df['buy'] = y
print(df)

# 提取特征与标签
X = df[['age', 'income']].values
y = df['buy'].values
⚠️ 注意
sklearn 要求 X 是二维数组(即使只有 1 个特征也要 reshape),y 是一维数组。

机器学习应用

机器学习在各行业的典型应用:

领域应用算法
电商推荐系统、销量预测协同过滤、回归
金融信用评分、反欺诈逻辑回归、XGBoost
医疗疾病诊断、影像识别CNN、决策树
制造设备故障预测异常检测
自动驾驶目标检测、路径规划深度学习
NLP翻译、客服机器人Transformer
💡 提示
选择算法前先明确:这是分类(离散)还是回归(连续)问题?数据有无标签?

数据理解

数据理解(EDA)是建模前的必修课,目标是把数据"看透":

import pandas as pd

df = pd.read_csv('data.csv')

# 1. 整体概览
df.info()          # 列类型、缺失
df.describe()      # 数值分布
df.shape           # 规模

# 2. 缺失值
df.isnull().sum()

# 3. 目标变量分布
df['label'].value_counts()
df['label'].value_counts(normalize=True)  # 占比

# 4. 特征分布(直方图)
df.hist(bins=30, figsize=(12, 8))

# 5. 相关性
df.corr()['label'].sort_values(ascending=False)
✅ 建议
EDA 阶段发现类别不平衡(如正负样本 1:99)要尽早处理,否则模型会"偷懒"全部预测多数类。

数据清洗

数据清洗决定模型上限:

import pandas as pd

df = pd.read_csv('raw.csv')

# 1. 缺失值
df['age'].fillna(df['age'].median(), inplace=True)
df.dropna(subset=['label'], inplace=True)   # 标签不能缺

# 2. 重复值
df.drop_duplicates(inplace=True)

# 3. 异常值(箱线图法:超出 1.5 倍 IQR)
q1, q3 = df['amount'].quantile([0.25, 0.75])
iqr = q3 - q1
df = df[(df['amount'] >= q1 - 1.5*iqr) &
        (df['amount'] <= q3 + 1.5*iqr)]

# 4. 统一文本
df['city'] = df['city'].str.strip().str.upper()
⚠️ 注意
删除异常值前要思考:是数据错误还是真实极端值?金融场景中的大额交易往往是最重要的信号。

特征工程

特征工程是"用领域知识创造更好特征"的过程,常比模型选择更影响效果:

import pandas as pd

df = pd.DataFrame({
    '注册日期': ['2025-01-15', '2025-03-20'],
    '总消费': [1000, 2000],
    '订单数': [5, 10],
})

# 1. 构造衍生特征
df['注册年'] = pd.to_datetime(df['注册日期']).dt.year
df['客单价'] = df['总消费'] / df['订单数']

# 2. 分箱
df['消费等级'] = pd.cut(df['总消费'], bins=[0, 500, 1500, 9999],
                     labels=['低', '中', '高'])

# 3. 数值特征缩放(标准化)
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(df[['总消费', '订单数']])
✅ 建议
好特征三原则:与目标相关、互不冗余、分布稳定。

数据可视化

数据可视化让你在建模前就发现模式与问题:

import matplotlib.pyplot as plt
import seaborn as sns

# 1. 目标变量分布
sns.countplot(x='label', data=df)

# 2. 特征与目标关系(箱线图)
sns.boxplot(x='label', y='amount', data=df)

# 3. 相关性热力图
sns.heatmap(df.corr(), annot=True, cmap='RdBu')

# 4. 散点图看两个特征关系
sns.scatterplot(x='age', y='income', hue='label', data=df)

# 5. 缺失值可视化
sns.heatmap(df.isnull(), cbar=False)

plt.show()
💡 提示
可视化要"带着问题看":类别是否平衡?特征是否可分?有没有离群点?

训练集测试集划分

训练集/测试集划分是评估模型泛化能力的基石:

from sklearn.model_selection import train_test_split

# 基础划分(7:3)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42)

# 分层抽样(保持类别比例,分类必用)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y)

# 时间序列:不能乱序切分!
train = df[df['date'] < '2026-06-01']
test = df[df['date'] >= '2026-06-01']
⚠️ 注意
三个原则:random_state 固定(可复现)、分类用 stratify、时序数据不能随机打乱。

统计学基础

机器学习需要的基础统计学知识:

import numpy as np
import pandas as pd

data = np.array([3, 5, 7, 8, 12, 15, 20])

# 描述统计
mean = np.mean(data)          # 均值
median = np.median(data)      # 中位数
std = np.std(data)            # 标准差
var = np.var(data)            # 方差

# 分位数
q1, q3 = np.percentile(data, [25, 75])

# 分布:正态分布(很多模型假设)
import scipy.stats as stats
# 生成正态分布样本
samples = np.random.normal(0, 1, 1000)
概念作用
均值/中位数数据中心位置
方差/标准差数据离散程度
正态分布统计检验的基础假设
相关系数变量间线性关系
💡 提示
先掌握描述统计即可入门,推导性统计(假设检验)可后续补。

概率思维

概率思维是理解机器学习算法的钥匙:

概念含义ML 应用
概率 P(A)事件发生可能性预测置信度
条件概率 P(A|B)B 发生下 A 的概率朴素贝叶斯
贝叶斯公式由果推因垃圾邮件过滤
似然数据对参数的拟合度最大似然估计
# 贝叶斯公式:P(垃圾|含"中奖") 
# = P(含"中奖"|垃圾) * P(垃圾) / P(含"中奖")

# 用统计估计
# P(垃圾) = 垃圾邮件数 / 总邮件数
# P(含"中奖"|垃圾) = 垃圾中命中数 / 垃圾总数
💡 提示
朴素贝叶斯分类器就是贝叶斯公式 + "特征独立"假设的产物。

损失函数与梯度

损失函数衡量预测与真实值的差距,梯度下降用来最小化它:

import numpy as np

# 均方误差损失(回归常用)
def mse(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 梯度下降示意(手动实现一元线性回归)
X = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 6])

w, b, lr, epochs = 0.0, 0.0, 0.01, 500
for _ in range(epochs):
    y_pred = w * X + b
    dw = np.mean(2 * (y_pred - y) * X)   # 对 w 求梯度
    db = np.mean(2 * (y_pred - y))       # 对 b 求梯度
    w -= lr * dw                          # 更新参数
    b -= lr * db
print(f'w={w:.2f}, b={b:.2f}')
损失函数适用公式
MSE回归(y-ŷ)² 的均值
MAE回归(抗离群)|y-ŷ| 的均值
交叉熵分类-Σy·log(ŷ)

过拟合、欠拟合、偏差与方差

过拟合/欠拟合、偏差/方差是模型诊断的核心概念:

现象表现解决
欠拟合训练、测试都差(模型太简单)加特征、换复杂模型
过拟合训练好、测试差(模型太复杂)正则化、加数据、早停
高偏差欠拟合(假设太强)换模型、加特征
高方差过拟合(对数据太敏感)正则化、交叉验证
from sklearn.learning_curve import learning_curve  # 新版用 sklearn.model_selection
from sklearn.model_selection import learning_curve
import numpy as np

# 学习曲线:观察训练/验证分数随数据量变化
train_sizes, train_scores, val_scores = learning_curve(
    model, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 5))

# 训练分高、验证分低 -> 过拟合(高方差)
# 两者都低 -> 欠拟合(高偏差)
✅ 建议
"训练误差高 = 偏差问题;训练好验证差 = 方差问题",对症下药。

机器学习算法

经典机器学习算法全景图:

问题类型算法
回归线性回归、岭回归、Lasso、SVR
分类逻辑回归、决策树、SVM、KNN、朴素贝叶斯、随机森林、XGBoost
聚类K-Means、层次聚类、DBSCAN
降维PCA、t-SNE、LDA
关联Apriori、FP-Growth
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier

# sklearn 统一接口:fit / predict / score
models = {
    '逻辑回归': LogisticRegression(),
    '决策树': DecisionTreeClassifier(),
    'SVM': SVC(),
    'KNN': KNeighborsClassifier(),
    '随机森林': RandomForestClassifier()
}
for name, m in models.items():
    m.fit(X_train, y_train)
    print(name, m.score(X_test, y_test))
✅ 建议
入门建议先跑多个基线模型对比,再深入调优最好的 1-2 个。

线性回归

线性回归预测连续数值,是最基础也最可解释的模型:

import numpy as np
from sklearn.linear_model import LinearRegression

# 数据:面积 -> 价格
X = np.array([50, 60, 70, 80, 90]).reshape(-1, 1)
y = np.array([150, 180, 210, 240, 270])

model = LinearRegression()
model.fit(X, y)

# 参数
print('斜率 w:', model.coef_[0])     # 3.0
print('截距 b:', model.intercept_)   # 0.0
print('预测 75m²:', model.predict([[75]]))  # 225

# R² 决定系数(越接近 1 越好)
print('R²:', model.score(X, y))
💡 提示
y = w·x + b,w 是斜率(每平米价格),b 是截距。可解释性极强。

多元线性回归

多元线性回归考虑多个特征:

import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# 多个特征:面积、房龄、楼层
data = pd.DataFrame({
    'area': [50, 60, 70, 80, 90, 100],
    'age': [20, 15, 10, 5, 3, 1],
    'floor': [1, 3, 5, 8, 12, 20],
    'price': [120, 165, 210, 255, 300, 360]
})

X = data[['area', 'age', 'floor']]
y = data['price']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

model = LinearRegression()
model.fit(X_train, y_train)

# 每个特征的权重(解释特征影响方向)
for col, coef in zip(X.columns, model.coef_):
    print(f'{col}: {coef:.2f}')

print('R²:', model.score(X_test, y_test))
⚠️ 注意
特征间若高度相关(多重共线性),系数会不稳定,可考虑用岭回归。

多项式回归

多项式回归用多项式拟合非线性关系:

import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

# 非线性数据(二次关系)
X = np.linspace(0, 10, 50).reshape(-1, 1)
y = 2 * X.ravel()**2 + 3 * X.ravel() + 1 + np.random.randn(50) * 10

# 构造多项式特征(x, x², x³...)
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X)

model = LinearRegression()
model.fit(X_poly, y)
print('R²:', model.score(X_poly, y))
✅ 建议
degree 越高拟合越灵活但越易过拟合,用交叉验证选合适的阶数。

逻辑回归

逻辑回归名字带"回归",实际是分类算法(输出概率):

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42, stratify=data.target)

model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)

# 输出概率而非仅类别
prob = model.predict_proba(X_test)[:3]
print('概率:', prob)

# 类别与准确率
print('预测:', model.predict(X_test[:3]))
print('准确率:', model.score(X_test, y_test))
💡 提示
逻辑回归输出 P(y=1|x),通过 sigmoid 函数把线性结果映射到 [0,1],天然适合二分类。

回归模型评估

回归模型评估指标:

from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

y_true = [100, 120, 130, 150]
y_pred = [105, 115, 140, 145]

mse = mean_squared_error(y_true, y_pred)
rmse = mse ** 0.5
mae = mean_absolute_error(y_true, y_pred)
r2 = r2_score(y_true, y_pred)

print(f'MSE={mse:.1f}, RMSE={rmse:.1f}, MAE={mae:.1f}, R²={r2:.3f}')
指标含义优劣
MSE误差平方均值大误差惩罚重
RMSEMSE 开方单位与 y 一致,常用
MAE绝对误差均值抗离群点
R²决定系数越接近 1 越好
✅ 建议
R² < 0 说明模型比"预测均值"还差;RMSE 与 MAE 结合看,两者差大说明存在离群误差。

决策树

决策树通过一系列"如果...那么..."规则做预测,可解释性强:

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

iris = load_iris()
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(iris.data, iris.target)

# 可视化树结构
plt.figure(figsize=(12, 8))
plot_tree(model, feature_names=iris.feature_names,
          class_names=iris.target_names, filled=True)
plt.show()

# 特征重要性
for name, imp in zip(iris.feature_names, model.feature_importances_):
    print(f'{name}: {imp:.3f}')
✅ 建议
max_depth 控制树深度防止过拟合;决策树对缺失值、量纲不敏感,适合表格数据。

支持向量机

支持向量机(SVM)通过寻找最大间隔超平面分类,擅长高维数据:

from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
# 二分类演示
X, y = data.data[:100], data.target[:100]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# RBF 核(默认,适合非线性)
model = SVC(kernel='rbf', C=1.0, gamma='scale')
model.fit(X_train, y_train)
print('SVM 准确率:', model.score(X_test, y_test))
核函数特点
linear线性可分,快
rbf默认,非线性强
poly多项式核
sigmoid类似神经网络
⚠️ 注意
SVM 对特征缩放敏感,使用前务必 StandardScaler 标准化。

K 近邻算法

K 近邻(KNN)是"物以类聚"的惰性算法:预测样本看它最近的 K 个邻居:

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42)

# KNN 对尺度敏感,必须标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train, y_train)
print('KNN 准确率:', model.score(X_test, y_test))
✅ 建议
K 越小越易过拟合,K 越大边界越平滑。经验值 5~20,可用交叉验证挑选。

集成学习

集成学习组合多个弱模型获得强模型,是竞赛常胜将军:

方法原理代表
Bagging并行训练 + 投票平均随机森林
Boosting串行训练,纠正前轮错误AdaBoost、GBDT、XGBoost
Stacking用元模型组合多个模型多模型融合
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.3, random_state=42)

rf = RandomForestClassifier(n_estimators=100)
gb = GradientBoostingClassifier()

for name, m in [('随机森林', rf), ('梯度提升', gb)]:
    m.fit(X_train, y_train)
    print(name, m.score(X_test, y_test))
💡 提示
集成模型通常比单个模型更稳,表格数据上 XGBoost/LightGBM 是首选。

朴素贝叶斯

朴素贝叶斯基于贝叶斯定理 + 特征独立假设,轻量高效:

from sklearn.naive_bayes import GaussianNB, MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split

# 文本分类(垃圾邮件检测)
texts = ['免费领取大奖', '本周促销', '重要会议通知', '点击链接领红包']
labels = [1, 0, 0, 1]   # 1 垃圾

vec = CountVectorizer()
X = vec.fit_transform(texts)

model = MultinomialNB()
model.fit(X, labels)
print('预测:', model.predict(vec.transform(['中奖点击链接'])))
✅ 建议
朴素贝叶斯训练快、小样本表现好,是文本分类(垃圾过滤、情感分析)的经典基线。

随机森林

随机森林 = Bagging + 决策树,最稳健的入门级集成模型:

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score

data = load_iris()

model = RandomForestClassifier(
    n_estimators=200,     # 树的数量
    max_depth=5,          # 树深
    max_features='sqrt',  # 每次分裂随机选特征数
    random_state=42
)

# 交叉验证(比单次切分更可靠)
scores = cross_val_score(model, data.data, data.target, cv=5)
print('5折交叉验证:', scores)
print('平均准确率:', scores.mean())

# 特征重要性
model.fit(data.data, data.target)
for name, imp in zip(data.feature_names, model.feature_importances_):
    print(f'{name}: {imp:.3f}')
✅ 建议
随机森林几乎不用调参就有不错效果,且能给出特征重要性,是表格数据的"万金油"。

分类指标

分类指标(不止看准确率):

from sklearn.metrics import (accuracy_score, precision_score,
    recall_score, f1_score, confusion_matrix, classification_report)

y_true = [1, 0, 1, 1, 0, 1, 0, 0]
y_pred = [1, 0, 0, 1, 0, 1, 1, 0]

print('准确率:', accuracy_score(y_true, y_pred))
print('精确率:', precision_score(y_true, y_pred))  # 预测为正中真的比例
print('召回率:', recall_score(y_true, y_pred))     # 正样本被找到的比例
print('F1:', f1_score(y_true, y_pred))
print(confusion_matrix(y_true, y_pred))
print(classification_report(y_true, y_pred))
指标场景
准确率类别均衡时
精确率误报代价高(垃圾邮件)
召回率漏报代价高(癌症筛查)
F1精确率召回率兼顾
⚠️ 注意
类别不平衡时,准确率会严重误导,务必看精确率/召回率/F1 与混淆矩阵。

聚类

聚类是无监督学习的核心任务:把相似样本自动分组:

from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成模拟数据(3 簇)
X, _ = make_blobs(n_samples=300, centers=3, random_state=42)

# K-Means 聚类
model = KMeans(n_clusters=3, random_state=42, n_init=10)
labels = model.fit_predict(X)

# 可视化
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')
plt.scatter(model.cluster_centers_[:, 0],
            model.cluster_centers_[:, 1],
            marker='X', s=200, color='red')
plt.show()

# 用肘部法选 K
import numpy as np
inertias = [KMeans(n_clusters=k, n_init=10).fit(X).inertia_ for k in range(1, 8)]
plt.plot(range(1, 8), inertias, marker='o')  # 拐点即合适 K
plt.show()
💡 提示
聚类常用于客户分群、图像压缩、异常检测。K 的选择常用肘部法或轮廓系数。

降维

降维在保留主要信息的前提下减少特征数量,利于可视化与加速:

from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

digits = load_digits()   # 64 维手写数字

# PCA 降到 2 维(用于可视化)
pca = PCA(n_components=2)
X_2d = pca.fit_transform(digits.data)

plt.scatter(X_2d[:, 0], X_2d[:, 1],
            c=digits.target, cmap='tab10', s=5)
plt.colorbar()
plt.show()

# 方差解释率(信息保留程度)
print('解释方差占比:', pca.explained_variance_ratio_)
print('累计:', pca.explained_variance_ratio_.sum())
✅ 建议
降维前先标准化;PCA 适合消除特征共线性,但不能提升信息量本身。

强化学习基本框架

强化学习(RL)让智能体在环境中试错学习,通过奖励信号优化决策:

要素说明
智能体(Agent)做出决策的主体
环境(Environment)智能体交互的对象
状态(State)环境的当前情况
动作(Action)智能体的选择
奖励(Reward)对动作的即时反馈
策略(Policy)状态 → 动作的映射
# 强化学习循环示意
state = env.reset()
while not done:
    action = agent.select_action(state)   # 根据策略选动作
    next_state, reward, done = env.step(action)  # 环境反馈
    agent.update(state, action, reward, next_state)  # 更新策略
    state = next_state
💡 提示
RL 的经典应用:AlphaGo、自动驾驶决策、推荐系统、机器人控制。

强化学习探索vs开采

强化学习中的探索 vs 开采(Exploration vs Exploitation)是核心权衡:

策略含义风险
探索尝试未知动作发现更好选择短期收益可能下降
开采选择当前已知最优动作可能错过更优策略
import numpy as np

# Epsilon-Greedy 策略(经典折中)
epsilon = 0.1   # 10% 概率探索

def select_action(q_values, epsilon):
    if np.random.random() < epsilon:
        return np.random.randint(len(q_values))  # 探索
    return np.argmax(q_values)                   # 开采

# epsilon 可随时间衰减:前期多探索,后期多开采
epsilon = max(0.01, epsilon * 0.995)
✅ 建议
常用策略:Epsilon-Greedy、UCB(置信上界)、Softmax 采样。

强化学习 Q-learning 与 SARSA

Q-Learning 与 SARSA是两种经典的免模型时序差分算法:

import numpy as np

# Q-Learning:更新 Q(s,a)
# Q(s,a) <- Q(s,a) + α[r + γ*max(Q(s',a')) - Q(s,a)]
def q_learning_update(q, s, a, r, s_next, alpha=0.1, gamma=0.9):
    best_next = np.max(q[s_next])          # 贪心看下一步最优
    q[s, a] += alpha * (r + gamma * best_next - q[s, a])
    return q

# SARSA:与 Q-Learning 区别在于用"实际执行的动作"更新
# Q(s,a) <- Q(s,a) + α[r + γ*Q(s',a') - Q(s,a)]
def sarsa_update(q, s, a, r, s_next, a_next, alpha=0.1, gamma=0.9):
    q[s, a] += alpha * (r + gamma * q[s_next, a_next] - q[s, a])
    return q
算法更新方式特点
Q-Learning取 max(离线策略)更激进、探索更充分
SARSA按当前策略(在线策略)更保守、更安全
💡 提示
著名例子:Cliff Walking 中 SARSA 更稳(会绕开悬崖),Q-Learning 更优(若探索充分)。

深度强化学习

深度强化学习(DRL)= 深度学习 + 强化学习,用神经网络近似 Q 值或策略:

代表算法核心思想
DQN用神经网络近似 Q 函数,引入经验回放与目标网络
Policy Gradient直接优化策略,适合连续动作
PPO策略梯度 + 截断,稳定高效(当下主流)
DDPG / SAC连续动作控制
# DQN 核心组件示意
import torch.nn as nn

class DQN(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(state_dim, 128), nn.ReLU(),
            nn.Linear(128, 128), nn.ReLU(),
            nn.Linear(128, action_dim)   # 输出每个动作的 Q 值
        )
    def forward(self, x):
        return self.net(x)
⚠️ 注意
深度强化学习训练不稳定、计算量大,入门建议先用 OpenAI Gym 环境跑通 DQN/PPO 示例。

神经网络的基本结构

神经网络的基本结构:输入层 → 隐藏层 → 输出层,层间通过权重连接:

import torch.nn as nn

# 一个三层全连接神经网络(PyTorch)
model = nn.Sequential(
    nn.Linear(4, 16),     # 输入 4 -> 隐藏 16
    nn.ReLU(),            # 激活函数
    nn.Linear(16, 16),
    nn.ReLU(),
    nn.Linear(16, 3)      # 隐藏 -> 输出 3 类
)

# 参数量
total = sum(p.numel() for p in model.parameters())
print('参数总数:', total)
组成作用
神经元加权求和 + 激活
权重/偏置可学习参数
激活函数引入非线性(ReLU/sigmoid/tanh)
损失函数衡量预测误差
💡 提示
没有激活函数,多层网络等价于一层线性变换,所以激活函数是"深度"的关键。

前向传播与反向传播

前向传播与反向传播是神经网络训练的两个阶段:

阶段过程
前向传播输入 → 逐层计算 → 输出预测值
反向传播损失 → 链式法则求梯度 → 逐层回传
参数更新w = w - 学习率 × 梯度
import torch

# 手写一个极小网络演示两个阶段
x = torch.tensor([1.0, 2.0])
w = torch.tensor([0.5, -0.3], requires_grad=True)
b = torch.tensor(0.1, requires_grad=True)

# 前向传播
y_pred = (x * w).sum() + b

# 计算损失(假设真实值为 1)
loss = (y_pred - 1) ** 2
print('损失:', loss.item())

# 反向传播(自动求梯度)
loss.backward()
print('梯度 w:', w.grad)   # 损失对 w 的偏导

# 参数更新
with torch.no_grad():
    w -= 0.01 * w.grad
    b -= 0.01 * b.grad
✅ 建议
框架(PyTorch/TensorFlow)自动完成反向传播,你只需理解"梯度从损失流向参数"这个过程。

深度学习vs传统机器学习

深度学习 vs 传统机器学习:

维度传统机器学习深度学习
特征人工特征工程自动学习特征
数据量千~万级万~亿级(越大越强)
硬件CPU 即可需要 GPU
可解释性较好较差(黑盒)
适用表格数据、中小样本图像、语音、文本
# 传统 ML:表格数据(sklearn)
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier().fit(X, y)

# 深度学习:图像分类(PyTorch)
import torch.nn as nn
cnn = nn.Sequential(
    nn.Conv2d(3, 32, 3), nn.ReLU(), nn.MaxPool2d(2),
    nn.Flatten(), nn.Linear(32*13*13, 10)
)
✅ 建议
先判断数据形态:表格 → 传统 ML/GBDT;图像文本 → 深度学习。

常见网络类型

常见网络类型:

网络全称适用
CNN卷积神经网络图像、视频
RNN / LSTM循环神经网络序列(文本、时间序列)
Transformer注意力机制NLP、多模态(主流)
GAN生成对抗网络图像生成
AutoEncoder自编码器降维、异常检测
# CNN 图像分类示意
import torch.nn as nn

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.fc = nn.Linear(64*7*7, 10)
    def forward(self, x):
        x = self.conv(x)
        return self.fc(x.flatten(1))
💡 提示
如今 Transformer 已统一视觉与语言领域(ViT、BERT、GPT),但 CNN 仍是图像基础。

交叉验证

交叉验证比单次切分更可靠地评估模型泛化能力:

from sklearn.model_selection import cross_val_score, KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

data = load_iris()
model = RandomForestClassifier(random_state=42)

# 5 折交叉验证
scores = cross_val_score(model, data.data, data.target, cv=5)
print('每折分数:', scores)
print('平均:', scores.mean().round(3), '±', scores.std().round(3))

# 自定义 K 折(可打乱)
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, data.data, data.target, cv=kf)

# 分层 K 折(分类推荐)
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, data.data, data.target, cv=skf)
✅ 建议
小数据集务必用交叉验证;K 通常取 5 或 10。分类任务默认用分层 K 折。

正则化

正则化通过在损失函数中加入惩罚项抑制过拟合:

方法惩罚效果
L1(Lasso)Σ|w|稀疏权重,可做特征选择
L2(Ridge)Σw²权重趋小但非零,更平滑
ElasticNetL1+L2 组合兼有两者
from sklearn.linear_model import Ridge, Lasso
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split

X, y = make_regression(n_samples=100, n_features=20, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

ridge = Ridge(alpha=1.0)     # alpha 控制惩罚强度
lasso = Lasso(alpha=0.1)

for name, m in [('岭回归', ridge), ('Lasso', lasso)]:
    m.fit(X_train, y_train)
    print(name, 'R²:', m.score(X_test, y_test).round(3))

# Lasso 会把不重要的系数压成 0
print('Lasso 非零系数数:', (lasso.coef_ != 0).sum())
✅ 建议
alpha 越大惩罚越强,用交叉验证(RidgeCV/LassoCV)自动选 alpha。

数据泄漏

数据泄漏(Data Leakage)是建模中隐蔽而致命的错误:测试集信息混入训练,导致评估虚高、上线失效:

泄漏来源例子
预处理泄漏用全量数据做标准化/填充后再切分
特征泄漏使用未来信息或目标派生特征
重复样本同一用户多条记录出现在训练和测试
# 错误示范:先 fit 全量再切分(泄漏!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)      # 用了测试集信息
X_train, X_test = train_test_split(X_scaled)

# 正确做法:只 fit 训练集
X_train, X_test = train_test_split(X)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)       # 用训练集的参数
⚠️ 注意
检查技巧:训练/验证差异异常大时要警惕泄漏;时间序列必须按时间切分。

集成方法

集成方法实战对比:

from sklearn.ensemble import (RandomForestClassifier,
    GradientBoostingClassifier, VotingClassifier)
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score

data = load_iris()

# 三个基础模型
lr = LogisticRegression(max_iter=1000)
rf = RandomForestClassifier(n_estimators=100, random_state=42)
svm = SVC(probability=True, random_state=42)

# 硬投票:多数表决
voting_hard = VotingClassifier([('lr', lr), ('rf', rf), ('svm', svm)],
                               voting='hard')

# 软投票:概率加权平均
voting_soft = VotingClassifier([('lr', lr), ('rf', rf), ('svm', svm)],
                               voting='soft')

for name, m in [('逻辑回归', lr), ('随机森林', rf), ('硬投票', voting_hard), ('软投票', voting_soft)]:
    s = cross_val_score(m, data.data, data.target, cv=5).mean()
    print(f'{name}: {s:.3f}')
✅ 建议
软投票(soft)通常优于硬投票(hard);集成的模型要多样性才有效。

超参搜索

超参数搜索:模型之外的可调参数(树的深度、C、K)需要系统搜索:

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

data = load_iris()
model = RandomForestClassifier(random_state=42)

# 网格搜索(全组合穷举)
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 5, 10],
    'min_samples_split': [2, 5]
}
grid = GridSearchCV(model, param_grid, cv=5, n_jobs=-1)
grid.fit(data.data, data.target)
print('最优参数:', grid.best_params_)
print('最优得分:', grid.best_score_.round(3))

# 随机搜索(大数据量时更快)
random_search = RandomizedSearchCV(
    model, param_grid, n_iter=20, cv=5, random_state=42)
random_search.fit(data.data, data.target)
✅ 建议
先粗后细:随机搜索定位好区域,再网格搜索精细调;始终用交叉验证评分。

MLOps 概念

MLOps 是把机器学习模型从实验推向生产的工程实践:

环节工具/实践
版本管理代码 Git、数据 DVC、模型 MLflow
训练调度Airflow、Kubeflow
模型服务FastAPI、Triton、TorchServe
监控数据漂移、性能回退检测
CI/CD自动化测试与发布流水线
# 用 FastAPI 部署模型示例
from fastapi import FastAPI
import joblib

app = FastAPI()
model = joblib.load('model.pkl')   # 训练后保存的模型

@app.post('/predict')
def predict(features: list[float]):
    pred = model.predict([features])
    return {'prediction': int(pred[0])}

# 启动: uvicorn main:app --port 8000
💡 提示
训练好模型只是开始:上线后要持续监控数据漂移(线上分布 vs 训练分布)。

常见问题排查

常见问题排查清单:

症状可能原因解决
准确率≈多数类比例类别不平衡重采样/换指标
训练好测试差过拟合正则化/更多数据
训练测试都差欠拟合/特征差加特征/换模型
损失不下降学习率太大/数据未归一调学习率/归一化
结果不稳定随机种子未固定固定 random_state
预测为常数数据泄漏/特征无效检查泄漏与特征
✅ 建议
排查顺序:数据 → 特征 → 模型 → 调参,先确认数据没问题再谈模型。

可解释性问题

可解释性(Explainability):模型为什么这么预测?业务落地常需要解释:

# 1. 特征重要性(树模型自带)
rf.feature_importances_

# 2. SHAP 值(统一解释框架,推荐)
import shap
explainer = shap.TreeExplainer(rf)
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values, X_test)

# 3. LIME(局部解释单个样本)
from lime.lime_tabular import LimeTabularExplainer
explainer = LimeTabularExplainer(X_train, feature_names=feature_names)
exp = explainer.explain_instance(X_test[0], rf.predict_proba)
exp.show_in_notebook()
⚠️ 注意
金融风控、医疗等领域模型可解释性可能是监管要求,需权衡精度与可解释。

假设限制

机器学习模型的假设与限制:

假设限制
独立同分布数据漂移时失效
特征充分缺失关键特征则上限低
数据无偏抽样偏差导致模型偏差
平稳性环境变化需重训
# 检查数据分布漂移的简单方法
import numpy as np

# 训练集与线上新数据的特征分布对比
train_mean = np.mean(X_train, axis=0) axis=0)
drift = np.abs(train_mean - online_mean) / np.std(X_train, axis=0)

print('漂移程度(>2 需关注):', drift.round(2))
✅ 建议
"模型会过时"是常态:建立监控与定期重训机制比一次性调优更重要。

数据偏差

数据偏差(Bias)会让模型"学习"社会的偏见:

偏差类型例子
抽样偏差只采集某地区数据
标注偏差标注者主观标准不一
历史偏差过去数据含歧视
代理偏差用不完美代理变量
⚠️ 注意
AI 伦理是严肃议题:招聘、信贷、司法等场景中,模型偏见可能造成实际伤害。检查训练数据的代表性与公平性指标(如 demographic parity)是负责任的实践。

模型的现实成本

评估模型的现实成本,不只是准确率:

成本说明
误报成本把好人当坏人(客服投诉)
漏报成本放走坏人(资金损失)
训练成本GPU/时间/人力
推理成本线上 QPS 与延迟
# 用成本矩阵选择阈值(以风控为例)
import numpy as np
from sklearn.metrics import confusion_matrix

# 假设:漏报代价 100 元,误报代价 5 元
fn_cost, fp_cost = 100, 5
y_prob = model.predict_proba(X_test)[:, 1]

best_th, best_cost = 0.5, float('inf')
for th in np.arange(0.3, 0.8, 0.05):
    y_pred = (y_prob >= th).astype(int)
    tn, fp, fn, tp = confusion_matrix(y_test, y_pred).ravel()
    cost = fn * fn_cost + fp * fp_cost
    if cost < best_cost:
        best_cost, best_th = cost, th
print(f'最优阈值 {best_th:.2f}, 最小成本 {best_cost}')
💡 提示
业务决策应把模型输出(概率)映射为期望成本,而非只看硬分类。

泰坦尼克号生存预测

经典入门项目:泰坦尼克号生存预测(Kaggle 首战):

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# 加载数据(Kaggle 提供)
train = pd.read_csv('titanic_train.csv')

# 特征工程
train['Sex'] = train['Sex'].map({'male': 0, 'female': 1})
train['Age'].fillna(train['Age'].median(), inplace=True)
train['Embarked'].fillna('S', inplace=True)
train['Embarked'] = train['Embarked'].map({'S': 0, 'C': 1, 'Q': 2})
train['FamilySize'] = train['SibSp'] + train['Parch'] + 1

# 选择特征
features = ['Pclass', 'Sex', 'Age', 'Fare', 'Embarked', 'FamilySize']
X = train[features]
y = train['Survived']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

model = RandomForestClassifier(n_estimators=200, max_depth=5, random_state=42)
model.fit(X_train, y_train)
print('准确率:', model.score(X_test, y_test).round(3))

# 重要发现:女性/头等舱生存率更高
print(model.feature_importances_.round(3))
✅ 建议
完整流程:EDA → 清洗 → 特征 → 基线 → 调参 → 提交。这是最经典的数据科学入门项目。

房价预测

回归实战:房价预测(波士顿/加州房价):

import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 加州房价数据集(sklearn 内置)
from sklearn.datasets import fetch_california_housing
data = fetch_california_housing()
X, y = data.data, data.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42)

model = GradientBoostingRegressor(random_state=42)
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, y_pred) ** 0.5
print('RMSE:', rmse.round(3))
print('R²:', model.score(X_test, y_test).round(3))

# 特征重要性
for name, imp in sorted(zip(data.feature_names, model.feature_importances_),
                        key=lambda x: -x[1]):
    print(f'{name}: {imp:.3f}')
💡 提示
回归任务看 RMSE/R²;特征重要性帮你理解哪些因素影响房价。

机器学习 - 客户分群

无监督实战:客户分群(RFM 分析 + K-Means):

import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# 客户数据:最近购买(Recency)、频次(Frequency)、金额(Monetary)
df = pd.DataFrame({
    'customer_id': range(1, 101),
    'recency': [30 - i % 30 for i in range(100)],
    'frequency': [i % 10 + 1 for i in range(100)],
    'monetary': [(i % 20 + 1) * 100 for i in range(100)]
})

# 标准化(聚类对尺度敏感)
X = StandardScaler().fit_transform(df[['recency', 'frequency', 'monetary']])

# K-Means 分 4 群
model = KMeans(n_clusters=4, random_state=42, n_init=10)
df['segment'] = model.fit_predict(X)

# 各群特征画像
print(df.groupby('segment')[['recency', 'frequency', 'monetary']].mean().round(1))
✅ 建议
分群后为每群打标签(高价值/潜力/流失风险),配合运营策略落地。

PCA 可视化

降维可视化实战:PCA 可视化高维数据:

from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

digits = load_digits()   # 8x8=64 维手写数字
X_scaled = StandardScaler().fit_transform(digits.data)

pca = PCA(n_components=2)
X_2d = pca.fit_transform(X_scaled)

plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_2d[:, 0], X_2d[:, 1],
                      c=digits.target, cmap='tab10', s=10, alpha=0.7)
plt.colorbar(scatter)
plt.title('手写数字 PCA 二维可视化')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()

# 观察:同类数字在低维空间中聚集 => 数据本身可分
💡 提示
PCA 可视化是检查数据可分性的利器:同类别能聚在一起,说明特征有效。

强化学习示例

强化学习示例:用 Q-Learning 解决经典迷宫/网格世界问题:

import numpy as np

# 4x4 网格世界:从 (0,0) 走到 (3,3),-1 为障碍
# 状态 = 16,动作 = 4(上下左右)
n_states, n_actions = 16, 4
q = np.zeros((n_states, n_actions))

# 简单转移函数:state -> 新 state(含边界限制,省略细节)
def step(state, action):
    r, c = divmod(state, 4)
    nr, nc = r, c
    if action == 0: nr = max(0, r-1)   # 上
    if action == 1: nr = min(3, r+1)   # 下
    if action == 2: nc = max(0, c-1)   # 左
    if action == 3: nc = min(3, c+1)   # 右
    nxt = nr * 4 + nc
    reward = 1.0 if nxt == 15 else 0.0   # 到达终点奖励
    done = (nxt == 15)
    return nxt, reward, done

# Q-Learning 训练
alpha, gamma, epsilon = 0.1, 0.9, 0.1
for episode in range(500):
    state = 0
    while True:
        if np.random.random() < epsilon:
            action = np.random.randint(4)
        else:
            action = np.argmax(q[state])
        nxt, reward, done = step(state, action)
        q[state, action] += alpha * (reward + gamma * np.max(q[nxt]) - q[state, action])
        state = nxt
        if done: break

# 打印学到的策略(每个格子的最优动作)
print(q.argmax(axis=1).reshape(4, 4))
💡 提示
500 个回合后 Q 表收敛,智能体学会从任意格子走向终点。

机器 教程

机器学习教程总结与进阶路线:

已掌握下一步
数据清洗与 EDA数据竞赛实战(Kaggle)
经典算法全家桶深度学习(PyTorch 官方教程)
模型评估与调参AutoML、大模型微调
基础项目真实业务项目落地
✅ 建议
学习路径:理论(本教程)→ 复现(sklearn 示例)→ 实战(Kaggle/项目)→ 进阶(深度学习)。机器学习是"做的科学",动手比看更重要。
第 1 / 59 节