算法学习常用函数详解

本文面向算法入门者,详细介绍深度学习和机器学习中常用的各种函数,包括其数学定义、核心作用、应用场景和实现细节。


目录

  1. 激活函数
  2. 线性变换函数
  3. 归一化函数
    • [Batch Normalization](#Batch Normalization)
    • [Layer Normalization](#Layer Normalization)
    • [Group Normalization](#Group Normalization)
  4. 损失函数
    • [交叉熵损失(Cross Entropy Loss)](#交叉熵损失(Cross Entropy Loss))
    • [均方误差损失(MSE Loss)](#均方误差损失(MSE Loss))
    • [二元交叉熵损失(Binary Cross Entropy)](#二元交叉熵损失(Binary Cross Entropy))
  5. 池化函数
    • [Max Pooling](#Max Pooling)
    • [Average Pooling](#Average Pooling)
    • [Global Average Pooling](#Global Average Pooling)
  6. 优化器相关函数
    • [梯度裁剪(Gradient Clipping)](#梯度裁剪(Gradient Clipping))
    • 学习率调度
  7. 正则化函数
  8. 注意力机制函数
    • [Scaled Dot-Product Attention](#Scaled Dot-Product Attention)
    • [Multi-Head Attention](#Multi-Head Attention)
  9. 其他重要函数

激活函数

激活函数是神经网络中的核心组件,它们引入非线性,使神经网络能够学习复杂的模式。

ReLU

全称:Rectified Linear Unit(线性整流单元)

数学定义

复制代码
f(x) = max(0, x) = {
    x,  if x > 0
    0,  if x ≤ 0
}

导数

复制代码
f'(x) = {
    1,  if x > 0
    0,  if x ≤ 0
}

核心作用

  1. 引入非线性:使神经网络能够学习非线性关系
  2. 计算高效:只需要简单的阈值操作,计算速度快
  3. 缓解梯度消失:在正区间梯度恒为1,避免了深层网络的梯度消失问题

优点

  • 计算简单,训练速度快
  • 在正区间不会出现梯度消失
  • 稀疏激活(约50%的神经元输出为0)

缺点

  • 死亡ReLU问题:如果输入始终为负,神经元永远不会被激活,梯度永远为0
  • 输出不是零中心的

应用场景

  • 卷积神经网络(CNN)的隐藏层
  • 深度前馈网络
  • 大多数现代深度学习架构的默认选择

Python实现

python 复制代码
import numpy as np

def relu(x):
    return np.maximum(0, x)

def relu_derivative(x):
    return (x > 0).astype(float)

Sigmoid

数学定义

复制代码
σ(x) = 1 / (1 + e^(-x))

值域:(0, 1)

导数

复制代码
σ'(x) = σ(x) * (1 - σ(x))

核心作用

  1. 将输入压缩到(0,1)区间:适合表示概率
  2. 平滑可微:处处可导,梯度连续
  3. 单调递增:保证输入越大,输出越大

优点

  • 输出范围有限,适合概率输出
  • 函数平滑,梯度计算稳定

缺点

  • 梯度消失:当输入很大或很小时,梯度接近0,导致深层网络难以训练
  • 输出不是零中心的:可能导致梯度更新效率低
  • 计算涉及指数:计算成本较高

应用场景

  • 二分类问题的输出层
  • 逻辑回归
  • 门控机制(如LSTM、GRU)

Python实现

python 复制代码
import numpy as np

def sigmoid(x):
    # 防止溢出
    x = np.clip(x, -500, 500)
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    s = sigmoid(x)
    return s * (1 - s)

Tanh

全称:Hyperbolic Tangent(双曲正切)

数学定义

复制代码
tanh(x) = (e^x - e^(-x)) / (e^x + e^(-x))
       = 2 * σ(2x) - 1

值域:(-1, 1)

导数

复制代码
tanh'(x) = 1 - tanh²(x)

核心作用

  1. 零中心输出:输出范围(-1,1),均值接近0
  2. 更强的梯度:相比Sigmoid,梯度更大,训练更快
  3. 平滑可微:类似Sigmoid的平滑特性

优点

  • 零中心输出,梯度更新更高效
  • 比Sigmoid梯度更大,训练更快

缺点

  • 仍然存在梯度消失问题(虽然比Sigmoid好)
  • 计算涉及指数

应用场景

  • RNN的隐藏层
  • 需要零中心输出的场景
  • 某些分类问题的输出层

Python实现

python 复制代码
import numpy as np

def tanh(x):
    return np.tanh(x)

def tanh_derivative(x):
    return 1 - np.tanh(x) ** 2

Softmax

数学定义

对于输入向量 x = [x₁, x₂, ..., xₙ],Softmax函数定义为:

复制代码
softmax(x_i) = e^(x_i) / Σⱼ e^(x_j)

其中,分母是所有元素的指数和。

核心作用

  1. 将任意实数向量转换为概率分布:输出所有元素和为1,每个元素在[0,1]区间
  2. 多分类问题的标准输出:适合多分类任务
  3. 保持相对大小关系:输入越大,输出概率越大

数学性质

  • 输出和为1:Σᵢ softmax(xᵢ) = 1
  • 所有输出非负:softmax(xᵢ) ≥ 0
  • 可微且单调

数值稳定性

为了避免指数溢出,通常使用以下技巧:

复制代码
softmax(x_i) = e^(x_i - max(x)) / Σⱼ e^(x_j - max(x))

应用场景

  • 多分类问题的输出层
  • 注意力机制中的注意力权重计算
  • 任何需要概率分布输出的场景

Python实现

python 复制代码
import numpy as np

def softmax(x, axis=-1):
    # 数值稳定版本
    x_shifted = x - np.max(x, axis=axis, keepdims=True)
    exp_x = np.exp(x_shifted)
    return exp_x / np.sum(exp_x, axis=axis, keepdims=True)

# 示例
x = np.array([1.0, 2.0, 3.0])
print(softmax(x))  # [0.09003057 0.24472847 0.66524096]

与交叉熵损失的关系

Softmax通常与交叉熵损失函数配合使用,形成softmax交叉熵损失,这是多分类问题的标准组合。


Leaky ReLU

数学定义

复制代码
f(x) = {
    x,      if x > 0
    αx,     if x ≤ 0
}

其中 α 是一个小的正数(通常为0.01)。

核心作用

  1. 解决死亡ReLU问题:在负区间给予小的梯度,避免神经元完全死亡
  2. 保持ReLU的优点:计算简单,正区间梯度为1

优点

  • 解决了ReLU的死亡问题
  • 保持了ReLU的计算效率
  • 在负区间有小的梯度,允许信息流动

缺点

  • 需要选择超参数α
  • 输出仍然不是零中心的

变体

  • Parametric ReLU (PReLU):将α作为可学习参数
  • Randomized ReLU (RReLU):在训练时α随机采样

应用场景

  • 需要避免死亡ReLU问题的场景
  • GAN(生成对抗网络)
  • 某些CNN架构

Python实现

python 复制代码
import numpy as np

def leaky_relu(x, alpha=0.01):
    return np.where(x > 0, x, alpha * x)

def leaky_relu_derivative(x, alpha=0.01):
    return np.where(x > 0, 1, alpha)

ELU

全称:Exponential Linear Unit(指数线性单元)

数学定义

复制代码
f(x) = {
    x,              if x > 0
    α(e^x - 1),     if x ≤ 0
}

其中 α 通常为1。

核心作用

  1. 结合ReLU和Sigmoid的优点:正区间类似ReLU,负区间平滑
  2. 零中心输出:负区间的输出均值接近-α,有助于梯度更新
  3. 更强的梯度:负区间梯度不会消失

优点

  • 负区间平滑,梯度连续
  • 零中心特性
  • 避免死亡神经元问题

缺点

  • 计算涉及指数,比ReLU慢
  • 需要选择超参数α

应用场景

  • 需要平滑激活的场景
  • 某些深度网络架构

Python实现

python 复制代码
import numpy as np

def elu(x, alpha=1.0):
    return np.where(x > 0, x, alpha * (np.exp(x) - 1))

def elu_derivative(x, alpha=1.0):
    return np.where(x > 0, 1, elu(x, alpha) + alpha)

GELU

全称:Gaussian Error Linear Unit(高斯误差线性单元)

数学定义

复制代码
GELU(x) = x * Φ(x)

其中 Φ(x) 是标准正态分布的累积分布函数(CDF):

复制代码
Φ(x) = 0.5 * (1 + erf(x / √2))

近似公式

复制代码
GELU(x) ≈ 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³)))

核心作用

  1. 平滑的非线性:比ReLU更平滑
  2. 概率视角:可以理解为根据输入的概率进行门控
  3. 在Transformer中表现优异:BERT、GPT等模型使用

优点

  • 平滑且可微
  • 在自然语言处理任务中表现优异
  • 概率解释更直观

缺点

  • 计算比ReLU复杂
  • 需要近似计算

应用场景

  • Transformer模型(BERT、GPT等)
  • 自然语言处理任务
  • 需要平滑激活的深度网络

Python实现

python 复制代码
import numpy as np

def gelu(x):
    # 使用近似公式
    return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x**3)))

def gelu_exact(x):
    # 精确版本(需要scipy)
    from scipy.special import erf
    return 0.5 * x * (1 + erf(x / np.sqrt(2)))

Swish

数学定义

复制代码
Swish(x) = x * σ(x) = x / (1 + e^(-x))

其中 σ(x) 是Sigmoid函数。

核心作用

  1. 自门控机制:输入自己作为门控信号
  2. 平滑且非单调:在小负值区域有小的负输出
  3. 在深度网络中表现优异:Google研究发现性能优于ReLU

优点

  • 平滑可微
  • 在深层网络中表现好
  • 无上界,有下界

缺点

  • 计算涉及Sigmoid,比ReLU慢
  • 在浅层网络中优势不明显

变体

  • Hard-Swish:使用分段线性函数近似,计算更快

应用场景

  • 移动端神经网络(MobileNet等)
  • 某些高效的CNN架构

Python实现

python 复制代码
import numpy as np

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

def swish_derivative(x):
    sigmoid_x = 1 / (1 + np.exp(-x))
    return sigmoid_x * (1 + x * (1 - sigmoid_x))

线性变换函数

Affine(仿射变换)

数学定义

对于输入向量 x,仿射变换定义为:

复制代码
y = Wx + b

其中:

  • W 是权重矩阵(weight matrix)
  • b 是偏置向量(bias vector)
  • x 是输入向量

矩阵形式

如果输入是 n 维向量,输出是 m 维向量,则:

  • W 的形状为 (m, n)
  • b 的形状为 (m,)
  • y 的形状为 (m,)

核心作用

  1. 线性变换:通过矩阵乘法进行线性变换
  2. 维度变换:可以改变向量的维度
  3. 特征组合:将输入特征进行线性组合
  4. 偏置调整:通过偏置项调整输出

与线性变换的区别

  • 线性变换:y = Wx(无偏置)
  • 仿射变换:y = Wx + b(有偏置)

在神经网络中的应用

  • 全连接层(Dense Layer):就是仿射变换
  • 卷积层:可以看作特殊的仿射变换
  • 注意力机制:包含多个仿射变换

前向传播

python 复制代码
def affine_forward(x, W, b):
    """
    x: (N, D) - N个样本,每个样本D维
    W: (M, D) - 权重矩阵
    b: (M,)   - 偏置向量
    返回: (N, M)
    """
    out = x.dot(W.T) + b  # 广播
    cache = (x, W, b)
    return out, cache

反向传播

python 复制代码
def affine_backward(dout, cache):
    """
    dout: (N, M) - 上游梯度
    cache: 前向传播的缓存
    返回: dx, dW, db
    """
    x, W, b = cache
    dx = dout.dot(W)      # (N, M) @ (M, D) -> (N, D)
    dW = dout.T.dot(x)    # (M, N) @ (N, D) -> (M, D)
    db = np.sum(dout, axis=0)  # (M,)
    return dx, dW, db

参数数量

对于输入维度 D,输出维度 M:

  • 权重参数:D × M
  • 偏置参数:M
  • 总参数:D × M + M

应用场景

  • 全连接神经网络层
  • 线性分类器
  • 特征变换
  • 几乎所有深度学习架构的基础组件

注意事项

  • 仿射变换本身是线性的,需要配合激活函数引入非线性
  • 参数初始化很重要,影响训练稳定性
  • 在深层网络中,仿射变换的参数数量可能非常大

归一化函数

归一化技术是现代深度学习的核心,它们通过标准化中间层的输入分布来加速训练并提高稳定性。

Batch Normalization

全称:批量归一化

数学定义

对于一个小批量(batch)的数据 x

  1. 计算均值和方差

    μ_B = (1/m) Σᵢ xᵢ
    σ²_B = (1/m) Σᵢ (xᵢ - μ_B)²

  2. 归一化

    x̂ᵢ = (xᵢ - μ_B) / √(σ²_B + ε)

  3. 缩放和平移

    yᵢ = γ * x̂ᵢ + β

其中:

  • m 是batch大小
  • ε 是小的常数(防止除零,通常为1e-5)
  • γβ 是可学习的参数

核心作用

  1. 内部协变量偏移:减少训练过程中各层输入分布的变化
  2. 允许更大的学习率:归一化后的输入更稳定
  3. 正则化效果:有一定的正则化作用,可以减少过拟合
  4. 加速训练:通常可以加快收敛速度

训练和推理的区别

  • 训练时:使用当前batch的统计量
  • 推理时:使用训练时累积的移动平均统计量

优点

  • 允许更大的学习率
  • 减少对初始化的依赖
  • 有正则化效果
  • 加速训练

缺点

  • 依赖batch大小,小batch时效果差
  • 在RNN中应用困难
  • 推理时需要额外存储统计量

应用场景

  • CNN的卷积层和全连接层
  • 大多数现代CNN架构(ResNet、Inception等)

Python实现

python 复制代码
import numpy as np

def batch_norm_forward(x, gamma, beta, bn_param):
    """
    x: (N, D) - N个样本,D个特征
    gamma: (D,) - 缩放参数
    beta: (D,)  - 平移参数
    """
    mode = bn_param['mode']  # 'train' or 'test'
    eps = bn_param.get('eps', 1e-5)
    momentum = bn_param.get('momentum', 0.9)
    
    N, D = x.shape
    running_mean = bn_param.get('running_mean', np.zeros(D, dtype=x.dtype))
    running_var = bn_param.get('running_var', np.ones(D, dtype=x.dtype))
    
    if mode == 'train':
        # 计算batch统计量
        sample_mean = np.mean(x, axis=0)
        sample_var = np.var(x, axis=0)
        
        # 归一化
        x_normalized = (x - sample_mean) / np.sqrt(sample_var + eps)
        
        # 更新移动平均
        running_mean = momentum * running_mean + (1 - momentum) * sample_mean
        running_var = momentum * running_var + (1 - momentum) * sample_var
        
        out = gamma * x_normalized + beta
        
        cache = (x, x_normalized, sample_mean, sample_var, gamma, eps)
    else:
        # 推理时使用移动平均
        x_normalized = (x - running_mean) / np.sqrt(running_var + eps)
        out = gamma * x_normalized + beta
        cache = None
    
    bn_param['running_mean'] = running_mean
    bn_param['running_var'] = running_var
    
    return out, cache

Layer Normalization

全称:层归一化

数学定义

对于单个样本的特征向量 x

  1. 计算均值和方差

    μ = (1/D) Σᵢ xᵢ
    σ² = (1/D) Σᵢ (xᵢ - μ)²

  2. 归一化

    x̂ᵢ = (xᵢ - μ) / √(σ² + ε)

  3. 缩放和平移

    yᵢ = γ * x̂ᵢ + β

与Batch Normalization的区别

  • Batch Norm:在batch维度上归一化(跨样本)
  • Layer Norm:在特征维度上归一化(跨特征)

核心作用

  1. 不依赖batch大小:对单个样本进行归一化
  2. 适合序列模型:在RNN、Transformer中表现优异
  3. 稳定训练:减少内部协变量偏移

优点

  • 不依赖batch大小
  • 适合RNN和Transformer
  • 训练和推理一致

缺点

  • 在CNN中效果不如Batch Norm
  • 计算成本略高

应用场景

  • Transformer模型(BERT、GPT等)
  • RNN和LSTM
  • 小batch或在线学习场景

Python实现

python 复制代码
import numpy as np

def layer_norm(x, gamma, beta, eps=1e-5):
    """
    x: (N, D) - N个样本,D个特征
    gamma: (D,) - 缩放参数
    beta: (D,)  - 平移参数
    """
    # 在特征维度上计算统计量
    mean = np.mean(x, axis=-1, keepdims=True)
    var = np.var(x, axis=-1, keepdims=True)
    
    # 归一化
    x_normalized = (x - mean) / np.sqrt(var + eps)
    
    # 缩放和平移
    out = gamma * x_normalized + beta
    return out

Group Normalization

全称:组归一化

核心思想

将通道(channels)分成若干组,在每组内进行归一化。

数学定义

对于特征图 x 的形状 (N, C, H, W):

  1. 将C个通道分成G组,每组C/G个通道
  2. 对每组内的特征进行归一化

与Batch/Layer Norm的区别

  • Batch Norm:在(N, H, W)维度归一化
  • Layer Norm:在(C, H, W)维度归一化
  • Group Norm:在(H, W)和部分C维度归一化

应用场景

  • 小batch训练
  • 目标检测(batch size通常为1或2)
  • 某些CNN架构

损失函数

损失函数衡量模型预测与真实值之间的差距,是训练优化的目标。

交叉熵损失(Cross Entropy Loss)

数学定义

对于多分类问题,给定真实标签 y (one-hot编码)和预测概率 ŷ

复制代码
L = -Σᵢ yᵢ * log(ŷᵢ)

对于单个样本:

复制代码
L = -log(ŷ_k)

其中 k 是真实类别。

与Softmax的组合

通常与Softmax结合使用:

复制代码
L = -log(softmax(logits)[k])

数值稳定性

为了避免数值问题,通常直接计算:

复制代码
L = -logits[k] + log(Σⱼ exp(logits[j]))

核心作用

  1. 概率解释:适合分类问题
  2. 梯度特性:当预测错误时梯度大,正确时梯度小
  3. 信息论基础:衡量两个概率分布的差异

优点

  • 适合多分类问题
  • 梯度特性好,训练稳定
  • 有概率解释

缺点

  • 假设类别互斥
  • 对异常值敏感

应用场景

  • 多分类问题
  • 与Softmax配合使用
  • 大多数分类任务

Python实现

python 复制代码
import numpy as np

def cross_entropy_loss(y_pred, y_true):
    """
    y_pred: (N, C) - N个样本,C个类别,已通过softmax
    y_true: (N,)   - 真实类别索引
    """
    N = y_pred.shape[0]
    # 获取每个样本真实类别的预测概率
    correct_logprobs = -np.log(y_pred[range(N), y_true])
    loss = np.sum(correct_logprobs) / N
    return loss

def softmax_cross_entropy_loss(logits, y_true):
    """
    数值稳定的版本
    logits: (N, C) - 未归一化的分数
    y_true: (N,)   - 真实类别索引
    """
    N, C = logits.shape
    # 数值稳定:减去最大值
    logits_shifted = logits - np.max(logits, axis=1, keepdims=True)
    exp_logits = np.exp(logits_shifted)
    probs = exp_logits / np.sum(exp_logits, axis=1, keepdims=True)
    
    # 计算损失
    correct_logprobs = -np.log(probs[range(N), y_true])
    loss = np.sum(correct_logprobs) / N
    return loss

均方误差损失(MSE Loss)

全称:Mean Squared Error

数学定义

复制代码
MSE = (1/n) Σᵢ (yᵢ - ŷᵢ)²

核心作用

  1. 回归问题:适合连续值预测
  2. 惩罚大误差:平方项使大误差被更严重惩罚
  3. 可微性:处处可微,梯度计算简单

优点

  • 数学性质好,易于优化
  • 适合回归问题
  • 计算简单

缺点

  • 对异常值敏感(平方项放大)
  • 假设误差服从高斯分布

变体

  • RMSE(Root MSE):√MSE,与目标值同量纲
  • MAE(Mean Absolute Error):|y - ŷ|,对异常值更鲁棒

应用场景

  • 回归问题
  • 图像重建
  • 数值预测

Python实现

python 复制代码
import numpy as np

def mse_loss(y_pred, y_true):
    """
    y_pred: (N, D) - 预测值
    y_true: (N, D) - 真实值
    """
    return np.mean((y_pred - y_true) ** 2)

def mse_loss_derivative(y_pred, y_true):
    """梯度"""
    return 2 * (y_pred - y_true) / y_pred.size

二元交叉熵损失(Binary Cross Entropy)

数学定义

对于二分类问题:

复制代码
L = -(y * log(ŷ) + (1-y) * log(1-ŷ))

其中:

  • y 是真实标签(0或1)
  • ŷ 是预测概率(0到1之间)

核心作用

  1. 二分类专用:专门用于二分类问题
  2. 概率解释:适合输出概率的场景
  3. 梯度特性:预测接近真实值时梯度小,远离时梯度大

应用场景

  • 二分类问题
  • 多标签分类(每个标签独立使用BCE)
  • 与Sigmoid配合使用

Python实现

python 复制代码
import numpy as np

def binary_cross_entropy_loss(y_pred, y_true, eps=1e-15):
    """
    y_pred: (N,) - 预测概率
    y_true: (N,) - 真实标签(0或1)
    """
    # 防止log(0)
    y_pred = np.clip(y_pred, eps, 1 - eps)
    loss = -(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
    return np.mean(loss)

池化函数

池化操作用于降低特征图的空间维度,减少参数数量,增加感受野。

Max Pooling

数学定义

在池化窗口内取最大值:

复制代码
y = max(x₁, x₂, ..., xₙ)

核心作用

  1. 降维:减少特征图尺寸
  2. 平移不变性:对小的平移具有鲁棒性
  3. 减少参数:降低计算量
  4. 特征选择:保留最显著的特征

常见配置

  • 2×2 Max Pooling:stride=2,将尺寸减半
  • 3×3 Max Pooling:stride=2,常用于某些架构

优点

  • 计算简单
  • 保留最显著特征
  • 对平移鲁棒

缺点

  • 丢失空间细节
  • 不可微(但可以通过近似实现反向传播)

应用场景

  • CNN的标准组件
  • 大多数现代CNN架构

Python实现

python 复制代码
import numpy as np

def max_pool_forward(x, pool_param):
    """
    x: (N, C, H, W)
    pool_param: {'pool_height': 2, 'pool_width': 2, 'stride': 2}
    """
    N, C, H, W = x.shape
    pool_h = pool_param['pool_height']
    pool_w = pool_param['pool_width']
    stride = pool_param['stride']
    
    out_h = (H - pool_h) // stride + 1
    out_w = (W - pool_w) // stride + 1
    
    out = np.zeros((N, C, out_h, out_w))
    
    for i in range(out_h):
        for j in range(out_w):
            h_start = i * stride
            h_end = h_start + pool_h
            w_start = j * stride
            w_end = w_start + pool_w
            
            out[:, :, i, j] = np.max(x[:, :, h_start:h_end, w_start:w_end], 
                                     axis=(2, 3))
    
    cache = (x, pool_param)
    return out, cache

Average Pooling

数学定义

在池化窗口内取平均值:

复制代码
y = (1/n) Σᵢ xᵢ

核心作用

  1. 降维:减少特征图尺寸
  2. 平滑特征:对噪声更鲁棒
  3. 全局信息:保留整体信息而非局部最大值

与Max Pooling的对比

  • Max Pooling:保留最显著特征,更常用
  • Average Pooling:保留平均信息,对噪声更鲁棒

应用场景

  • 某些CNN架构
  • 全局平均池化(Global Average Pooling)
  • 需要平滑特征的场景

Global Average Pooling

全称:全局平均池化

数学定义

对整个特征图取平均:

复制代码
y = (1/(H×W)) Σᵢⱼ xᵢⱼ

核心作用

  1. 全局信息:将整个特征图压缩为单个值
  2. 减少参数:避免全连接层的大量参数
  3. 防止过拟合:减少模型复杂度

应用场景

  • ResNet等现代架构
  • 替代全连接层
  • 减少模型参数

优化器相关函数

梯度裁剪(Gradient Clipping)

数学定义

限制梯度的大小:

按值裁剪

复制代码
g = {
    g,           if |g| ≤ threshold
    threshold,   if g > threshold
    -threshold,  if g < -threshold
}

按范数裁剪

复制代码
g = {
    g,                    if ||g|| ≤ threshold
    g * threshold / ||g||, if ||g|| > threshold
}

核心作用

  1. 防止梯度爆炸:限制梯度大小,稳定训练
  2. 稳定训练:特别是在RNN中非常重要
  3. 允许更大学习率:通过限制梯度,可以使用更大的学习率

应用场景

  • RNN和LSTM训练
  • 深层网络
  • 训练不稳定时

Python实现

python 复制代码
import numpy as np

def clip_gradients(grads, max_norm):
    """
    按范数裁剪梯度
    grads: 梯度列表
    max_norm: 最大范数
    """
    total_norm = 0
    for grad in grads:
        total_norm += np.sum(grad ** 2)
    total_norm = np.sqrt(total_norm)
    
    clip_coef = max_norm / (total_norm + 1e-6)
    if clip_coef < 1:
        for grad in grads:
            grad *= clip_coef
    
    return grads

学习率调度

常见策略

  1. 固定学习率:整个训练过程保持不变
  2. 阶梯衰减:每隔一定epoch降低学习率
  3. 指数衰减:lr = lr₀ * decay^epoch
  4. 余弦退火:lr = lr_min + (lr_max - lr_min) * (1 + cos(π * epoch / max_epoch)) / 2
  5. Warmup:训练初期逐渐增加学习率

核心作用

  1. 加速收敛:初期大学习率快速学习
  2. 精细调优:后期小学习率精细调整
  3. 避免震荡:防止训练后期震荡

正则化函数

Dropout

数学定义

训练时,以概率 p 随机将神经元输出置为0:

复制代码
y = {
    x / (1-p),  if 保留(概率1-p)
    0,          if 丢弃(概率p)
}

推理时,所有神经元都保留,但输出要乘以 (1-p)。

核心作用

  1. 防止过拟合:随机丢弃神经元,减少模型复杂度
  2. 集成效果:相当于训练多个子网络的集成
  3. 提高泛化:强制模型学习更鲁棒的特征

优点

  • 简单有效
  • 计算开销小
  • 广泛适用

缺点

  • 训练时间可能增加
  • 需要调整dropout率

应用场景

  • 全连接层
  • 某些CNN架构
  • 防止过拟合

Python实现

python 复制代码
import numpy as np

def dropout_forward(x, dropout_param):
    """
    x: 输入
    dropout_param: {'mode': 'train', 'p': 0.5, 'seed': None}
    """
    p, mode = dropout_param['p'], dropout_param['mode']
    
    if mode == 'train':
        mask = (np.random.rand(*x.shape) > p) / (1 - p)
        out = x * mask
        cache = mask
    else:
        out = x
        cache = None
    
    return out, cache

def dropout_backward(dout, cache):
    """
    dout: 上游梯度
    cache: 前向传播的mask
    """
    if cache is not None:
        dx = dout * cache
    else:
        dx = dout
    return dx

L1/L2正则化

L2正则化(权重衰减)

复制代码
L_total = L_data + λ * Σᵢ wᵢ²

L1正则化

复制代码
L_total = L_data + λ * Σᵢ |wᵢ|

核心作用

  1. 防止过拟合:惩罚大权重
  2. 特征选择:L1可以产生稀疏权重
  3. 模型简化:鼓励模型使用更少的特征

区别

  • L2:平滑,权重接近0但不为0
  • L1:产生稀疏解,某些权重为0

注意力机制函数

Scaled Dot-Product Attention

数学定义

复制代码
Attention(Q, K, V) = softmax(QK^T / √d_k) * V

其中:

  • Q:查询(Query)矩阵
  • K:键(Key)矩阵
  • V:值(Value)矩阵
  • d_k:键的维度

缩放因子 √d_k

防止点积过大导致softmax梯度消失。

核心作用

  1. 序列建模:捕捉序列中的依赖关系
  2. 并行计算:相比RNN可以并行计算
  3. 长距离依赖:直接建模任意距离的依赖

应用场景

  • Transformer模型
  • 机器翻译
  • 自然语言处理

Python实现

python 复制代码
import numpy as np

def scaled_dot_product_attention(Q, K, V, mask=None):
    """
    Q: (..., seq_len_q, d_k)
    K: (..., seq_len_k, d_k)
    V: (..., seq_len_v, d_v)
    """
    d_k = Q.shape[-1]
    
    # 计算注意力分数
    scores = np.matmul(Q, K.transpose(-2, -1)) / np.sqrt(d_k)
    
    # 应用mask(如果有)
    if mask is not None:
        scores = np.where(mask == 0, -1e9, scores)
    
    # Softmax
    attention_weights = softmax(scores, axis=-1)
    
    # 加权求和
    output = np.matmul(attention_weights, V)
    
    return output, attention_weights

Multi-Head Attention

核心思想

将Q、K、V分成多个头(heads),分别计算注意力,然后拼接。

数学定义

复制代码
MultiHead(Q, K, V) = Concat(head₁, ..., headₕ)W^O

其中:

复制代码
headᵢ = Attention(QWᵢ^Q, KWᵢ^K, VWᵢ^V)

核心作用

  1. 多视角:从多个角度捕捉信息
  2. 表达能力:增强模型的表达能力
  3. 并行计算:多个头可以并行计算

应用场景

  • Transformer的核心组件
  • BERT、GPT等模型

其他重要函数

One-Hot编码

定义

将类别索引转换为向量表示,只有对应位置为1,其他为0。

示例

复制代码
类别 0 -> [1, 0, 0, 0]
类别 1 -> [0, 1, 0, 0]
类别 2 -> [0, 0, 1, 0]
类别 3 -> [0, 0, 0, 1]

核心作用

  1. 类别表示:将离散类别转换为数值向量
  2. 损失计算:用于交叉熵损失
  3. 无大小关系:避免类别间的数值大小关系

Python实现

python 复制代码
import numpy as np

def one_hot_encode(labels, num_classes):
    """
    labels: (N,) - 类别索引
    num_classes: 类别数量
    返回: (N, num_classes)
    """
    N = len(labels)
    one_hot = np.zeros((N, num_classes))
    one_hot[np.arange(N), labels] = 1
    return one_hot

Embedding

核心思想

将离散的符号(如单词)映射到连续的向量空间。

数学定义

复制代码
e = E[i]

其中 E 是嵌入矩阵,i 是索引。

核心作用

  1. 语义表示:将符号转换为有意义的向量
  2. 可学习:嵌入向量可以通过训练学习
  3. 降维/升维:可以改变表示维度

应用场景

  • 词嵌入(Word Embedding)
  • 类别特征编码
  • 推荐系统

Python实现

python 复制代码
import numpy as np

class Embedding:
    def __init__(self, vocab_size, embed_dim):
        self.weight = np.random.randn(vocab_size, embed_dim) * 0.01
    
    def forward(self, indices):
        """
        indices: (N,) - 索引
        返回: (N, embed_dim)
        """
        return self.weight[indices]

Positional Encoding

核心思想

为序列中的每个位置添加位置信息,因为Transformer没有循环结构,无法感知位置。

数学定义(Transformer中的正弦位置编码):

复制代码
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

其中:

  • pos:位置
  • i:维度索引
  • d_model:模型维度

核心作用

  1. 位置信息:为序列添加位置信息
  2. 相对位置:可以表示相对位置关系
  3. 外推能力:可以处理比训练时更长的序列

应用场景

  • Transformer模型
  • 序列到序列任务

Python实现

python 复制代码
import numpy as np

def positional_encoding(seq_len, d_model):
    """
    seq_len: 序列长度
    d_model: 模型维度
    返回: (seq_len, d_model)
    """
    pe = np.zeros((seq_len, d_model))
    position = np.arange(seq_len).reshape(-1, 1)
    div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))
    
    pe[:, 0::2] = np.sin(position * div_term)
    pe[:, 1::2] = np.cos(position * div_term)
    
    return pe

总结

本文详细介绍了算法学习中常用的各种函数,包括:

  1. 激活函数:ReLU、Sigmoid、Tanh、Softmax等,引入非线性
  2. 线性变换:Affine变换,神经网络的基础
  3. 归一化:Batch Norm、Layer Norm等,稳定训练
  4. 损失函数:交叉熵、MSE等,衡量预测误差
  5. 池化函数:Max Pooling、Average Pooling等,降维
  6. 正则化:Dropout、L1/L2等,防止过拟合
  7. 注意力机制:Self-Attention、Multi-Head等,序列建模
  8. 其他函数:One-Hot、Embedding、Positional Encoding等

学习建议

  1. 理解每个函数的数学定义和几何意义
  2. 掌握前向传播和反向传播的实现
  3. 了解各函数的优缺点和适用场景
  4. 通过实践加深理解

进一步学习

  • 深入理解反向传播算法
  • 学习优化算法(SGD、Adam等)
  • 研究现代架构(ResNet、Transformer等)
  • 实践项目,应用这些函数

希望本文能帮助算法入门者更好地理解和掌握这些常用函数!


参考文献

  1. Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning. MIT Press.
  2. Vaswani, A., et al. (2017). "Attention is All You Need." Neural Information Processing Systems.
  3. Ioffe, S., & Szegedy, C. (2015). "Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift." ICML.

相关推荐
科技林总11 小时前
【系统分析师】2.3 预测与决策
学习
s090713611 小时前
连通域标记:从原理到数学公式全解析
图像处理·算法·fpga开发·连通域标记
@小码农11 小时前
6547网:202512 GESP认证 C++编程 一级真题题库(附答案)
java·c++·算法
q行11 小时前
java学习日志--IO流(使用)
java·学习·io流
头疼的程序员11 小时前
计算机网络:自顶向下方法(第七版)第二章 学习分享(一)
学习·计算机网络
先生沉默先11 小时前
TypeScript 学习_类型与语法(2)
学习·typescript
自然语11 小时前
人工智能之数字生命-特征类升级20260106
人工智能·算法
菜鸟233号11 小时前
力扣343 整数拆分 java实现
java·数据结构·算法·leetcode
赫凯11 小时前
【强化学习】第五章 时序差分算法
算法
leiming612 小时前
c++ find_if 算法
开发语言·c++·算法