激活函数

参考:

类型:

  • 线性激活函数

    • 易训练
    • 不适合复杂任务
  • 非线性激活函数

    • sigmoid, tanh, ReLU
    • 难训练
    • 适合复杂任务

sigmoid, tanh, ReLU 比较

参考:

  1. 易训练性:

    • 线性激活函数 > ReLU > tanh > sigmoid
  2. ReLU 相比 sigmoid、 tanh 的优势

    • sigmoid, tanh 难训练

      • 值域饱和问题
      • 错误不能在深层神经网络传播
      • 导致梯度消失问题

梯度消失问题解决手段

  1. 使用更容易训练的激活函数 ReLU
  2. 波尔兹曼机器
  3. 分层训练
  4. 无监督的预训练

ReLU 激活函数

别名:

  • linear rectified function
  • 分段线性函数 piecewise linear function

实现:

  • python: max(0, x)

适合模型:

  • ReLU 不适合 RNN
  • 适合 MLPs、CNNs

    • MLPs (multiple layer perceptrons) 多层感知机
    • CNN (convolutional neural network) 卷积神经网络

激活函数 sigmoid Vs. softmax

特点:

  1. 他们都是激活函数
  2. sogmoid:

    • 值域: [0, 1]
    • 用途:

      • 二分类
      • 公式: $\dfrac{1}{1+ e^{x}}$
  3. softmax:

    • 值域: [0, 1]

      • 多分类

交叉熵损失函数 Cross Entropy Loss

参考:

交叉熵

概念:

  1. 信息量

    • 肯定发生的事件发生,信息量少

      • 例如:今天早上太阳升起
    • 不太可能发生的事件发生,信息量大

      • 例如:今天早上有日食
    • 定义:

      \begin{equation} I(x_i) = - log P(X = x_i) \end{equation}
    • 性质

      • 信息量和概率是负相关的
  2. 信息熵

    • 香农熵,简称熵
    • 整个概率分布的熵
    \begin{equation} H(X) = - [ \sum_{i=1}^{n}P(X=x_i)logP(X=x_i) ] \end{equation}
  3. 相对熵(KL 散度)

    • 引入相对概率分布 Q(X)

    img/2024-03-19_16-41-49_screenshot.png

  4. 交叉熵

    • 使用 P(X)的分布 Q(X)来建模
    \begin{equation} H(P, Q) = H(P) + D_{KL}(P||Q) = - [ \sum_{i=1}^{n}x_i logQ(X_i) ] \end{equation}
    • 只和与近似分布 Q 相关
    • P 表示真实概率
    • Q 表示近似概率(预测的概率)

交叉熵损失函数的意义:

  1. 值越大,表明模型的预测结果和实际情况的差距越大
  2. 值越小,预测结果越接近实际情况

神经网络模型和近似概率分布:

  • sigmoid 函数得到的值,可以用作 Q(X)
  • 标签的值[0, 1] 可以用来作为随机变量 X 的值域
  • 实际运算: -ylogy'

    • y: 真实值, 例如 [0, 1] 表示 target 向量 [其他类型,猫]
    • y': 表示模型输出的 logits, 即 sigmoid 函数的输出向量,例如: [0.1, 0.9]
    • y 和 y' 是相同维度的
    • 实际运算数据: - target*log(logits)

损失函数

MSE 均方误差损失函数

即平均平方误差: $(x_n - y_n)^2$

Cross Entropy Loss 交叉熵损失函数

反向传播

参考:

公式:

  1. wi 的梯度
\begin{equation} \dfrac{\partial L}{\partial w_i} = \dfrac{\partial L}{\partial y_{i+1}} \cdot w_i \end{equation}
  1. bi 的梯度
\begin{equation} \dfrac{\partial L}{\partial b_i} = \dfrac{\partial L}{\partial y_{i+1}} \end{equation}

梯度下降 gradient descent

SGD, Stochastic Gradient Descent, 随机梯度下降

参考:

使用步骤:

  1. 创建优化器 optimizer(即 SGD)

    optimizer = torch.optim.SGD(..., lr=rate_learning, momentum=0.9)
    
  2. 前向传播,获取模型预测的 loss

    y_predict = model(X_input)
    loss = loss_fun(predict_y, real_y)
    
  3. 梯度归零

    • 把梯度的值,设置为零
    optimizer.zero_grad()
    
  4. 反向传播

    • 通过损失函数计算权重参数等(可学习的参数)的梯度
    • 计算梯度 $\frac{\partial L}{\partial w_i}$ 和 $\frac{\partial L}{\partial b_i}$
    loss.backward()
    
  5. 更新权重

    • 即梯度下降的移动一个 tiny step
    • 计算和更新新的 weight bias 等
    optimizer.step()
    

Adam 优化器

训练过程 pytorch Dataloader

batch_count, batch_size, dataset size, epoch

概念:

  1. 总样本:

    • 用来做训练的所有样本
  2. 样本总数:

    • 总样本中包含的样本数量
  3. epoch:

    • 把所有的数据重复使用的次数
  4. batch:

    • 所有样本被分成多个批次用来做训练
  5. batch_size:

    • 一个批次的样本数
  6. batch_count:

    • 总样本被分成了几个批次用来做训练

torch 中的实际对应关系:

  1. dataloader.dataset length 是样本的总数
  2. dataloader length 是 batch_count 数量,即分成了几个 batch
  3. dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

    • batch_size: 是一个 batch 包含几个样本

训练例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
     # * 用一个批次的数据做训练
    for batch, (X, y) in enumerate(dataloader):
        # - `batch` 是第几批,
        # - `(X,y)` 是这一批的多个样本,数量是 batch_size
        # - `dataloader` 的长度是 batch_count


        # 把 tensor 放到 gpu 上
        X, y = X.to(device), y.to(device)

        # * 前向传播(预测)
        # Compute prediction error
        pred = model(X)

        # * 损失函数计算(一整批数据的loss)
        loss = loss_fn(pred, y) # <---- loss是一个标量的tensor, eg: `torch.tensor(3.56)`

        # * 后向传播,
        # Backpropagation
        # - 计算梯度
        loss.backward()

        # - 更新参数
        optimizer.step()

        # - 梯度置零
        optimizer.zero_grad()

        # * 一整批样本的预测损失函数 loss_one_batch
        if batch % 100 == 0:
            # `loss.item()`: 把标量 tensor 中的数据取出来
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

测试例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
  • 这里一个 for 循环,每一次循环返回的 X,y 的是一个 batch 的数据
  • len(X) == batch_size
  • size 是样本总数
  • num_batches 是 ceiling(sample_count/batch_sze) == batch_count
  • test_loss 获得的是一个 bach 的 loss
  • correct / size 是 (总预测正确数/样本总数), 即总体样本的平均预测 Accuracy

模型网络

参考:

定义网络常见问题:

  1. 梯度爆炸

    • 反向传播中,梯度过大,导致梯度爆炸
  2. 梯度消失

    • 使用 sigmoid 激活函数,反向传播,层数越多,梯度越小,真正有效的只有后面几层,更多的层参数不能更新

序列

参考:

模型:

  1. 自回归模型
  2. 隐自回归模型(latent autoregression model)
  3. 隐马尔可夫模型

线性回归

知识点:

  1. 噪声项

神经网络基础常识

层数计算

  • 输入层不纳入层数计算

    • eg: 输入层X3 –> 输出层 y1 ==> 实际统计层数的结果时1层(单层神经网络)

全连接层

  • 线性回归(输入层X3 –> 输出层 y1),每个输入都和每个输出连接,这种变换称为全连接层(full-connected layter) 或者稠密层(dense layer)