Skip to content

1 、监督学习


一、回归🧀

监督 非监督
有答案 没有答案
回归模型 分类模型
线性回归,预测输出 预测类别,有限可能输出

Tip

\(x\) 输入变量

\(y\) 输出变量

\((x,y)\) 单个训练样本

\((x^{i}, y^{i})\) 第几个训练样本(第几行)


1、回归模型🧀

Process.svg

  • \(ŷ\)\(y\) 的预测值

2、代价函数🧀

\[ J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} \left( f_{(w,b)}x^{(i)} - y^{(i)} \right)^2 \]
  • 模型: \(f=wx+b\) → 线性回归 \(f=wx,(b=0)\)
  • 参数: \(w,b\)
  • 损失函数:\(J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} \left( f_{(w,b)}x^{(i)} - y^{(i)} \right)^2\)
  • 目标: \(minimize \text{ } J(w,b)\)

3、梯度下降🧀

方法不止适用于线性回归,每次寻找能够下降最多的方向

方法不止适用于线性回归,每次寻找能够下降最多的方向

\(\alpha : 学习率,即步长,设置合适的学习率有助于更好的拟合\)

批量梯度下降指:每一次参数更新都使用全部 \(m\) 个训练样本 来计算代价函数的梯度。

给定代价函数:

\[ J(w,b)=\frac{1}{2m}\sum_{i=1}^{m}(f_{w,b}(x^{(i)})-y^{(i)})^2 \]

其梯度为:

\[ \frac{\partial J}{\partial w} =\frac{1}{m}\sum_{i=1}^{m}(f_{w,b}(x^{(i)})-y^{(i)})x^{(i)} \]
\[ \frac{\partial J}{\partial b} =\frac{1}{m}\sum_{i=1}^{m}(f_{w,b}(x^{(i)})-y^{(i)}) \]

每次迭代中使用全部训练数据更新参数:

\[ w := w - \alpha \frac{\partial J}{\partial w}, \qquad b := b - \alpha \frac{\partial J}{\partial b} \]
项目 含义
优点 梯度方向稳定、易于收敛到最小值
缺点 每次更新都要遍历全部数据,大数据集上速度慢
适用场景 小规模训练集、教学演示、理论分析
方法 每次更新所用样本 特点
批量梯度下降(BGD) 全部 m 个样本 稳定但慢
随机梯度下降(SGD) 单个样本 更新快但震荡大
小批量梯度下降(Mini-batch GD) 一组样本(例如 32 / 64) 速度快、稳定性高,深度学习默认选择

线性回归模型

$$ f_{w,b}(x) = wx + b $$

  • 代价方程 $$ J(w, b) = \frac{1}{2m} \sum_{i=1}^{m} \left( f_{w,b}(x^{(i)}) - y^{(i)} \right)^2 $$

  • 梯度下降算法

    • 重复直到收敛:

$$ w = w - \alpha \frac{\partial}{\partial w} J(w, b) $$

$$ b = b - \alpha \frac{\partial}{\partial b} J(w, b) $$

  • 梯度计算(代价方程的偏导) $$ \frac{\partial}{\partial w} J(w, b) = \frac{1}{m} \sum_{i=1}^{m} \left( f_{w,b}(x^{(i)}) - y^{(i)} \right) x^{(i)} $$

4、特征工程🧀

(1)向量化🧀

\(f(w,b)=w_1x_1+w_2x_2+w_3x_3+………+w_nx_n+b\) $$ f = \vec{w}· \vec{x} + b $$

1
2
3
4
5
#  向量化
f = np.dot(w,x) + b
#  无向量化
for j in range (0,16) : 
    f = f + w[j] * x[j]

Example

向量化能让计算同时在 CPU SIMD 或 NumPy 底层 BLAS 上运行,从 \(O(n)\) 加速到一次矩阵运算

np.random.seed(1)
a = np.random.rand(10000000)  # 超大数组
b = np.random.rand(10000000)
tic = time.time()  # 记录开始时间
c = np.dot(a, b)
toc = time.time()  # 记录结束时间

print(f"np.dot(a, b) =  {c:.4f}")
print(f"Vectorized version duration: {1000*(toc-tic):.4f} ms ")

tic = time.time()  # 记录开始时间
c = my_dot(a,b)
toc = time.time()  # 记录结束时间

print(f"my_dot(a, b) =  {c:.4f}")
print(f"loop version duration: {1000*(toc-tic):.4f} ms ")

del(a);del(b)  # 释放大数组占用的内存

(2)多元线性回归🧀

特征数 权重更新公式 偏置项更新公式
单变量 \(w = w - \alpha \frac{1}{m} \sum\limits_{i=1}^{m} ( f_{w,b}(x^{(i)}) - y^{(i)} ) x^{(i)}\) \(b = b - \alpha \frac{1}{m} \sum\limits_{i=1}^{m} ( f_{w,b}(x^{(i)}) - y^{(i)} )\)
多变量 \(w_j = w_j - \alpha \frac{1}{m} \sum\limits_{i=1}^{m} ( f_{\vec{w},b}(\vec{x}^{(i)}) - y^{(i)} ) x_j^{(i)}\) \(b = b - \alpha \frac{1}{m} \sum\limits_{i=1}^{m} ( f_{\vec{w},b}(\vec{x}^{(i)}) - y^{(i)} )\)
正规方程
  • 正规方程是一种 不需要梯度下降、可以直接一次性求解线性回归参数 \(w,b\) 的解析方法。

对于线性模型:

\[ f(x)=w^Tx+b \]

将偏置并入特征向量后定义:

\[ X_b = \begin{bmatrix} 1 & x^{(1)}_1 & \dots & x^{(1)}_n \\ 1 & x^{(2)}_1 & \dots & x^{(2)}_n \\ \vdots & \vdots & \ddots & \vdots \\ 1 & x^{(m)}_1 & \dots & x^{(m)}_n \end{bmatrix} \]

正规方程直接给出最优参数:

\[ \theta = (X_b^T X_b)^{-1} X_b^T y \]

其中

  • \(\theta\) 包含 \(b\) 和全部权重 \(w_j\)
  • 不需要选择学习率,也不需要迭代
项目 描述
优点 无需梯度下降、无需调参、可直接得到最优解
缺点 需要计算矩阵逆,时间复杂度高(\(O(n^3)\)
适用场景 特征数量较少(\(n < 10^3\))、小规模数据集
import numpy as np

# 假设你有一个特征矩阵 X 和目标向量 y
# X 的每一行代表一个样本,每一列代表一个特征
# y 是目标变量的值

def normal_equation(X, y):
    # 在特征矩阵 X 的前面加一列全为 1 的列,以便计算偏置项
    X_b = np.c_[np.ones((X.shape[0], 1)), X]

    # 计算正规方程的解
    theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
    return theta

# 示例数据
X = np.array([[1, 2], [2, 3], [3, 4]])  # 特征矩阵
y = np.array([5, 7, 9])  # 目标变量

theta = normal_equation(X, y)
print("模型的参数:", theta)

(3)特征缩放🧀

让多个变量范围类似,重新缩放特征可以加快梯度下降速度(数据预处理

Ⅰ.区间缩放(Min-Max Scaling)🧀
  • \(x_{normalized}=\frac{x-μ}{max(x)−min(x)}\)

其中:

  • \(μ\) 是特征 \(x\) 的均值。
from sklearn.preprocessing import MinMaxScaler
import numpy as np

# 示例数据:特征矩阵 X
X = np.array([[1, 2], [2, 3], [3, 4]])

# 创建 MinMaxScaler 对象,指定特定的范围 (默认范围是 [0, 1])
scaler = MinMaxScaler(feature_range=(-1, 1))

# 拟合并转换数据
X_normalized = scaler.fit_transform(X)

# 输出归一化后的数据
print("均值归一化后的数据:")
print(X_normalized)

Ⅱ.标准化(Z-Score Standardization)🧀
  • \(z=\frac{x-μ}{\sigma}\)

其中:

  • \(\mu\) 是数据的均值,
  • \(\sigma\) 是数据的标准差。
1
2
3
4
5
6
7
8
9
import numpy as np
from scipy import stats

# 示例数据
X = np.array([10, 20, 30, 40, 50])

# 计算 Z-score
z_scores = stats.zscore(X)
print("Z-scores:", z_scores)
方法 适合场景
Min-Max 分布不稳定、有界特征、神经网络
Z-Score 近似高斯分布、线性模型、SVM

(4)多项式回归🧀

为了让线性模型能拟合非线性曲线,我们添加高次特征 \(x^n\)

Example

x = np.arange(0,20,1)
y = np.cos(x/2)

X = np.c_[x, x**2, x**3,x**4, x**5, x**6, x**7, x**8, x**9, x**10, x**11, x**12, x**13]
X = zscore_normalize_features(X) 

model_w,model_b = run_gradient_descent_feng(X, y, iterations=1000000, alpha = 1e-1)

plt.scatter(x, y, marker='x', c='r', label="Actual Value"); plt.title("Normalized x x**2, x**3 feature")
plt.plot(x,X@model_w + model_b, label="Predicted Value"); plt.xlabel("x"); plt.ylabel("y"); plt.legend(); plt.show()

二、分类🧀

1、逻辑(Logistic)回归🧀

二元分类

false - 0
true - 1

这时线性回归不再适用,需要选择新的函数来划分


2、\(Sigmoid\) 函数🧀

# Plot sigmoid(z) over a range of values from -10 to 10
z = np.arange(-10,11)

fig,ax = plt.subplots(1,1,figsize=(5,3))
# Plot z vs sigmoid(z)
ax.plot(z, sigmoid(z), c="b")

ax.set_title("Sigmoid function")
ax.set_ylabel('sigmoid(z)')
ax.set_xlabel('z')
draw_vthresh(ax,0)

Sigmoid.svg

\[ z= \vec w·\vec x + b \]
\[ g(z) = \frac{1}{1 + e^{-z}}=\frac{1}{1+e^{-(\vec w· \vec x +b)}} \]
  • 输出为是 \(1/0\) 的可能性大小
  • \(P(y=0)+P(y=1)=1\)
1
2
3
4
5
6
7
8
import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 示例
x = np.array([-2, -1, 0, 1, 2])
print(sigmoid(x))

3、决策边界🧀

\(z=\vec w· \vec x +b = 0\)

可以是线性的也可以是多项式函数,最后的边界也相应的是直线或者其他形状

# 选择 0 到 6 的取值
x0 = np.arange(0,6)

x1 = 3 - x0
fig,ax = plt.subplots(1,1,figsize=(5,4))
# 绘制决策边界
ax.plot(x0,x1, c="b")
ax.axis([0, 4, 0, 3.5])

# 填充直线下方区域
ax.fill_between(x0,x1, alpha=0.2)

# 绘制原始数据
plot_data(X,y,ax)
ax.set_ylabel(r'$x_1$')
ax.set_xlabel(r'$x_0$')
plt.show()

4、代价函数🧀

线性回归 逻辑回归
模型 \(f(\vec x )=\vec w ·\vec x +b\) \(f(\vec x )=\frac{1}{1+e^{-(\vec w· \vec x +b)}}\)
代价函数 \(J(w, b) = \frac{1}{2m} \sum_{i=1}^{m} \left( f_{w,b}(x^{(i)}) - y^{(i)} \right)^2\) \(J(w, b) = \frac{1}{m} \sum_{i=1}^{m} L(f_{\vec w,b}(\vec x^{(i)}),y^{(i)})\)
形状 凹函数 凹函数
是否可以梯度下降
\[ f(\vec x )=\frac{1}{1+e^{-(\vec w· \vec x +b)}} \]
\[ L\left(f_{\vec{w},b}(\vec{x}^{(i)}), y^{(i)}\right) = \begin{cases} -\log \left( f_{\vec{w},b}(\vec{x}^{(i)}) \right), & \text{if } y^{(i)} = 1 \\ -\log \left(1 - f_{\vec{w},b}(\vec{x}^{(i)}) \right), & \text{if } y^{(i)} = 0 \end{cases} \]

Bug

如果在逻辑回归中使用原来的模型函数,得到的并非凹函数,也无法使用梯度下降法寻找最小值

线性回归函数 逻辑回归函数
JLinear.png JLogistic.png

Tip

  • 紧凑表达
\[ L\left(f_{\vec{w},b}(\vec{x}^{(i)}), y^{(i)}\right) = -y^{(i)} \log \left( f_{\vec{w},b}(\vec{x}^{(i)}) \right) -(1 - y^{(i)}) \log \left(1 - f_{\vec{w},b}(\vec{x}^{(i)}) \right) \]

5、梯度下降🧀

思路和回归模型一样,区别在于\(f\) 的选择不同

import torch
import torch.nn as nn
import torch.optim as optim

X = torch.tensor([[0.5], [1.5], [2.5]])
y = torch.tensor([[0], [1], [1]]).float()

class LogisticModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)
        self.sigmoid = nn.Sigmoid()
    def forward(self, x):
        return self.sigmoid(self.linear(x))

model = LogisticModel()
criterion = nn.BCELoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)

for epoch in range(200):
    outputs = model(X)
    loss = criterion(outputs, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

print('预测(1.0):', model(torch.tensor([[1.0]])).item())

6、模型评估指标🧀

(1)二分类核心概念🧀

预测:正类 预测:负类
真实:正类 TP(真正)模型说“是”,现实也“是” FN(假负)模型说“否”,现实其实“是”
真实:负类 FP(假正)模型说“是”,现实其实“否” TN(真负)模型说“否”,现实也“否”
\[ \text{Accuracy} = \frac{TP + TN}{TP + FP + TN + FN} \]
\[ \text{Precision} = \frac{TP}{TP + FP}\quad\quad\text{Recall} = \frac{TP}{TP + FN} \]
\[ \text{F1} = \frac{2\cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} \]
评估指标
预测:正类 预测:负类 合计
真实:正类(60) TP = 45 FN = 15 60
真实:负类(40) FP = 5 TN = 35 40
列合计 50 50 100
\[ \text{Accuracy} = \frac{TP + TN}{TP+FP+TN+FN} = \frac{45 + 35}{100} = 0.80 \]
\[ \text{Precision} = \frac{TP}{TP + FP} = \frac{45}{45 + 5} = 0.90 \]
\[ \text{Recall} = \frac{TP}{TP + FN} = \frac{45}{45 + 15} = 0.75 \]
\[ F1 = \frac{2PR}{P + R} = \frac{2 \times 0.90 \times 0.75}{0.90 + 0.75} = 0.82 \]

Tip

不平衡数据更应关注 Recall/F1PR/AUC-PRAccuracy 容易误导。

(2)ROC/AUC 与 PR/AUC-PR🧀

\[ \text{TPR} = \frac{TP}{TP+FN}\quad\quad\text{FPR} = \frac{FP}{FP+TN} \]

ROC 曲线以 TPRFPR 绘制;AUC 为曲线下的面积。PR 曲线以 PrecisionRecall 绘制;AUC-PR 在极端不平衡任务更具参考价值。

阈值选择需结合业务代价(假阳性/假阴性),可依据 PR 或 ROC 曲线挑选。

(3)多分类扩展🧀

  • macro:对每类独立计算后平均,强调每类同等权重
  • micro:汇总全局 TP/FP/FN/TN 计算,强调样本级整体表现
Macro/Micro F1
A 40 10 20
B 30 20 10
C 10 10 30
类别 TP FP FN
  • Precision_A = 40 / (40 + 10) = 0.80
  • Recall_A = 40 / (40 + 20) = 0.67
  • F1_A = 2 × 0.80 × 0.67 / (0.80 + 0.67) = 0.73

  • Precision_B = 30 / (30 + 20) = 0.60

  • Recall_B = 30 / (30 + 10) = 0.75
  • F1_B = 2 × 0.60 × 0.75 / (0.60 + 0.75) = 0.67

  • Precision_C = 10 / (10 + 10) = 0.50

  • Recall_C = 10 / (10 + 30) = 0.25
  • F1_C = 2 × 0.50 × 0.25 / (0.50 + 0.25) = 0.33

Macro-F1(不考虑类别样本量,简单平均) $$ \text{Macro-F1}=\frac{0.73 + 0.67 + 0.33}{3} = 0.577 $$ Micro-F1(微平均):先把所有 TP/FP/FN 加总,再算 Precision/Recall/F1

  • TP_total = 40 + 30 + 10 = 80
  • FP_total = 10 + 20 + 10 = 40
  • FN_total = 20 + 10 + 30 = 60
\[ \text{Precision}\_{micro}=\frac{TP}{TP+FP} =\frac{80}{80+40}=0.667 \]
\[ \text{Recall}\_{micro}=\frac{TP}{TP+FN} =\frac{80}{80+60}=0.571 \]
\[ F1\_{micro}=\frac{2PR}{P+R} =\frac{2\times 0.667\times 0.571}{0.667+0.571}=0.615 \]
指标 计算方式 含义
Macro-F1 各类 F1 平均 平等看待每个类别(适合数据不平衡)
Micro-F1 汇总 TP/FP/FN 后整体计算 反映整体样本级表现(常用于竞赛)

三、过拟合和正则化🧀

1、过拟合问题🧀

泛化能力 对应问题
欠拟合 高偏差(high bias)
泛化(generalization)
过拟合 高方差(high variance)

解决:

  • 收集更多数据
  • 选择合适的特征
  • 使用正则化减小某些参数的值

2、正则化🧀

带正则化项的均方误差(MSE)损失函数

\[ J(\vec{w}, b) = \frac{1}{2m} \sum_{i=1}^{m} (f_{\vec{w},b}(\vec{x}^{(i)}) - y^{(i)})^2 + \frac{\lambda}{2m} \sum_{j=1}^{n} w_j^2 \]

(1) 误差项(均方误差 MSE)🧀

  • 最小二乘误差,用于衡量预测值与真实值的差距
\[ \frac{1}{2m} \sum_{i=1}^{m} (f_{\vec{w},b}(\vec{x}^{(i)}) - y^{(i)})^2 \]

(2) L2 正则化(Ridge 正则化)🧀

\[ \frac{\lambda}{2m} \sum_{j=1}^{n} w_j^2 \]
  • 这部分的作用是 惩罚过大的权重 \(w_j\),从而让模型更简单,避免过拟合。

  • λ(lambda) 控制正则化强度:

  • 如果 λ 太大,模型可能会欠拟合(underfitting)。
  • 如果 λ 太小,正则化效果不明显,可能会过拟合(overfitting)。

(3)L1 正则化(Lasso 正则化)🧀

\[ J(\mathbf{w}) = \sum_{i=1}^{n}(y_i - \mathbf{w}^T\mathbf{x}_i)^2 + \lambda \sum_{j=1}^{p}|w_j| \]
  • L1 惩罚项可将部分系数压到 0,实现特征选择与稀疏建模。
  • L2 正则只会让权重“变小”,但不会产生真正的 0;因为它的梯度在 0 附近平滑且趋近于 0。
  • L1 的梯度是常量,会强力把小权重推到 0,从而形成稀疏性,实现特征选择。
1
2
3
4
5
from sklearn.linear_model import Lasso

lasso_model = Lasso(alpha=0.1)
lasso_model.fit(X_train, y_train)
y_pred_lasso = lasso_model.predict(X_test)

Info

特性 岭回归(Ridge) Lasso 回归(Lasso)
正则化类型 L2 正则化 L1 正则化
参数收缩 权重缩小但不为零 权重可被压缩为零
主要作用 降低方差、稳定模型 特征选择、稀疏建模
适用场景 高维共线特征 高维冗余特征
是否可解释 较弱 较强(因可筛选特征)