本文主要围绕扩充上下文窗口相关工作尽心介绍。

随着大规模模型的不断提出,怎么高效扩充上下文窗口是一个关键的问题,如果能够基于前者的一些工作再微调,不用再从头训练扩充LLM的本身的参数是一个比较需要的一个方案。

基于RoPE的Position Interpolation

https://arxiv.org/abs/2306.15595

  • 代码实现:https://github.com/ymcui/Chinese-LLaMA-Alpaca/pull/705
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import transformers
    def pi_forward(self, x, seq_len=None):
    if seq_len > self.max_seq_len_cached: # seq_len > 2048
    print(f"Perform position interpolation for length {seq_len}")
    t = torch.arange(seq_len, device=x.device, dtype=self.inv_freq.dtype)
    scale = self.max_seq_len_cached / seq_len
    t *= scale
    freqs = torch.einsum("i,j->ij", t, self.inv_freq)
    emb = torch.cat((freqs, freqs), dim=-1).to(x.device)
    cos_cached = emb.cos()[None, None, :, :]
    sin_cached = emb.sin()[None, None, :, :]
    return (
    cos_cached[:, :, :seq_len, ...].to(dtype=x.dtype),
    sin_cached[:, :, :seq_len, ...].to(dtype=x.dtype)
    )
    return (
    self.cos_cached[:, :, :seq_len, ...].to(dtype=x.dtype),
    self.sin_cached[:, :, :seq_len, ...].to(dtype=x.dtype)
    )
    transformers.models.llama.modeling_llama.LlamaRotaryEmbedding.forward = pi_forward

RoPE

绝对位置编码优点:实现简单、可提前计算好,速度快。外推性相对较差。

相对位置编码优点:相对位置信息对模型要更加有效,外推性更好,处理长文本能力更强。

RoPE通过绝对位置编码的方式实现相对位置编码,综合两者的优点。公式化就是:$\langle\boldsymbol{f}(\boldsymbol{q}, m), \boldsymbol{f}(\boldsymbol{k}, n)\rangle = g(\boldsymbol{q},\boldsymbol{k},m-n)$

具体方法

借助复数实现将绝对位置编码和相对位置编码结合,通过复数的指数形式就可以实现如上的效果。由于复数乘法的几何意义对应着向量的旋转,因此才成为旋转式位置编码
$$
\begin{equation}
\boldsymbol{f}(\boldsymbol{q}, m) =\begin{pmatrix}\cos m\theta & -\sin m\theta\ \sin m\theta & \cos m\theta\end{pmatrix} \begin{pmatrix}q_0 \ q_1\end{pmatrix}\end{equation}
$$

image-20230719233344737

image-20230719233432878

通过这种编码方式就能够在计算注意力的同时自动获得相对位置信息,且为了避免算力浪费可以直接采用矩阵乘法实现RoPE的计算。另外,这边的$\theta_i=10000^{-\frac{2i}{d}}$,是类似于transformer三角式的带远程衰减的。带了衰减之后的两两注意力得分计算就带设定了界限。

image-20230719234011066

线性场景应用

为了降低Transformer的计算量,线性attention的方案是通过只保留线性计算的部分,不再计算Softmax以此降低需要的计算量。

Scaled-Dot Attention:
$$
\begin{equation}
Attention(\boldsymbol{Q},\boldsymbol{K},\boldsymbol{V})i = \frac{\sum\limits{j=1}^n e^{\boldsymbol{q}_i^{\top}\boldsymbol{k}_j}\boldsymbol{v}j}{\sum\limits{j=1}^n e^{\boldsymbol{q}_i^{\top}\boldsymbol{k}_j}}
\end{equation}
$$
其中的主体计算就是一般函数$sim({q}_i,{k}_j)$,为了保持其非负,直接将原有的softmax去掉是不可行的,需要换用其他的函数计算进行替代。

由于RoPE没有对Attention矩阵本身做任何处理,因此可以直接应用到线性Attention中。

References

  1. Transformer升级之路:2、博采众长的旋转式位置编码

PI方法

直接压缩绝对位置m,将原有的m变成cur_len/max_len*m

Extending Context is Hard…but not Impossible

References

  1. Extending Context is Hard…but not Impossible
  2. 层次分解位置编码,让BERT可以处理超长文本

NTK

神经正切核Neural Tangent Kernel是一种核方法
直接作用于衰减$\theta$值

References

  1. NTK-Aware Scaled RoPE allows LLaMA models to have extended (8k+) context size without any fine-tuning and minimal perplexity degradation.

NBCE

在这里插入图片描述

在输出生成结果部分,改善Random Sample的效果,将Pooling方式改为直接输出不确定性最低的那个分布

模型训练以及推理中的显存占用计算与混精优劣

按照参数量来计算
当采用fp16训练得到的模型:
1个字节8bit,fp16=2个字节,10B的模型=20GB
n B模型 推理需要2n GB显存才能将模型加载;训练采用Adam优化器,则下限内存:2+2+12(4+4+4-模型参数
梯度、优化器状态)-16n GB

混精优劣:速度快,但容易溢出(fp16),并且计算softmax需要切回fp32;bf16 损失的精度被证明不怎么影响收敛-A100及以后的显卡

References

  1. 大模型面试八股答案(二)——训练框架

FlashAttention

相关简述

直接结论:速度更快,内存消耗更小

FlashAttention的运行速度比PyTorch标准注意力快 2-4 倍,所需内存减少5-20倍。

为了避免从HBM(High Bandwidth Memory)中读取和写入注意力矩阵,flashattention希望实现在不访问整个输入的情况下计算softmax的缩减,并且反向传播中不能存储中间注意力矩阵。

具体实现:

  1. 将输入分割成块,并在输入块上进行多次传递,从而以增量方式执行softmax缩减。
  2. 不使用中间注意力矩阵,通过存储归一化因子来降低HBM的内存消耗。在后向传播中快速重新计算片上注意力,虽然增加了计算量,但速度更快内存更高(大大降低HBM的访问)

代码实现

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
'''
FilePath: llama_flash_attn_monkey_patch.py
Author: jiangyihua
Date: 2023-07-21 09:39:02
LastEditors: Please set LastEditors
LastEditTime: 2023-07-21 12:56:27
Copyright: 2023 IEAD/jiangyihua. All Rights Reserved.
Descripttion:
'''
from typing import List, Optional, Tuple

import torch
from torch import nn

import transformers
from transformers.models.llama.modeling_llama import LlamaConfig, LlamaRotaryEmbedding, apply_rotary_pos_emb

from einops import rearrange

try:
from flash_attn.flash_attn_interface import flash_attn_qkvpacked_func
# from flash_attn.flash_attn_interface import flash_attn_unpadded_qkvpacked_func
from flash_attn.bert_padding import unpad_input, pad_input
except ImportError:
raise ImportError("Please install flash_attn to use this module")

class LlamaAttention(nn.Module):
"""Multi-headed attention from 'Attention Is All You Need' paper"""

def __init__(
self,
config: LlamaConfig,
):
super().__init__()
hidden_size = config.hidden_size
num_heads = config.num_attention_heads
self.hidden_size = hidden_size
self.num_heads = num_heads
self.head_dim = self.hidden_size // num_heads

if (self.head_dim * num_heads) != self.hidden_size:
raise ValueError(
f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
f" and `num_heads`: {num_heads}).")
self.q_proj = nn.Linear(
hidden_size,
num_heads * self.head_dim,
bias=False,
)
self.k_proj = nn.Linear(
hidden_size,
num_heads * self.head_dim,
bias=False,
)
self.v_proj = nn.Linear(
hidden_size,
num_heads * self.head_dim,
bias=False,
)
self.o_proj = nn.Linear(
num_heads * self.head_dim,
hidden_size,
bias=False,
)
self.rotary_emb = LlamaRotaryEmbedding(self.head_dim)

def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
return tensor.view(bsz, seq_len, self.num_heads,
self.head_dim).transpose(1, 2).contiguous()

def forward(
self,
hidden_states: torch.Tensor,
past_key_value: Optional[Tuple[torch.Tensor]] = None,
attention_mask: Optional[torch.Tensor] = None,
position_ids: Optional[torch.LongTensor] = None,
output_attentions: bool = False,
use_cache: bool = False,
) -> Tuple[torch.Tensor, Optional[torch.Tensor],
Optional[Tuple[torch.Tensor]]]:
"""Input shape: Batch x Time x Channel

attention_mask: [bsz, q_len]
"""
bsz, q_len, _ = hidden_states.size()

query_states = self.q_proj(hidden_states).view(
bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
key_states = self.k_proj(hidden_states).view(
bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
value_states = self.v_proj(hidden_states).view(
bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
# [bsz, q_len, nh, hd]
# [bsz, nh, q_len, hd]

kv_seq_len = key_states.shape[-2]
if past_key_value is not None:
kv_seq_len += past_key_value[0].shape[-2]

cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
query_states, key_states = apply_rotary_pos_emb(query_states,
key_states,
cos,
sin,
position_ids)
# [bsz, nh, t, hd]
assert not output_attentions, "output_attentions is not supported"
assert not use_cache, "use_cache is not supported"
assert past_key_value is None, "past_key_value is not supported"

# Flash attention codes from
# https://github.com/HazyResearch/flash-attention/blob/main/flash_attn/flash_attention.py

# transform the data into the format required by flash attention
qkv = torch.stack([query_states, key_states, value_states], dim=2) # [bsz, nh, 3, q_len, hd]
qkv = qkv.transpose(1, 3) # [bsz, q_len, 3, nh, hd]
# We have disabled _prepare_decoder_attention_mask in LlamaModel
# the attention_mask should be the same as the key_padding_mask
key_padding_mask = attention_mask


if key_padding_mask is None:
qkv = rearrange(qkv, 'b s ... -> (b s) ...')
max_s = q_len
cu_q_lens = torch.arange(0, (bsz + 1) * q_len, step=q_len, dtype=torch.int32,
device=qkv.device)
output = flash_attn_qkvpacked_func(
qkv, cu_q_lens, max_s, 0.0,
softmax_scale=None, causal=True
)
# output = flash_attn_unpadded_qkvpacked_func(
# qkv, cu_q_lens, max_s, 0.0,
# softmax_scale=None, causal=True
# )
output = rearrange(output, '(b s) ... -> b s ...', b=bsz)
else:
nheads = qkv.shape[-2]
x = rearrange(qkv, 'b s three h d -> b s (three h d)')
x_unpad, indices, cu_q_lens, max_s = unpad_input(x, key_padding_mask)
x_unpad = rearrange(x_unpad, 'nnz (three h d) -> nnz three h d', three=3, h=nheads)
output_unpad = flash_attn_qkvpacked_func(
x_unpad, cu_q_lens, max_s, 0.0,
softmax_scale=None, causal=True
)
# output_unpad = flash_attn_unpadded_qkvpacked_func(
# x_unpad, cu_q_lens, max_s, 0.0,
# softmax_scale=None, causal=True
# )
output = rearrange(pad_input(rearrange(output_unpad, 'nnz h d -> nnz (h d)'),
indices, bsz, q_len),
'b s (h d) -> b s h d', h=nheads)
return self.o_proj(rearrange(output,
'b s h d -> b s (h d)')), None, None


# Copied from transformers.models.bart.modeling_bart.BartDecoder._prepare_decoder_attention_mask
def _prepare_decoder_attention_mask(self, attention_mask, input_shape,
inputs_embeds, past_key_values_length):
# [bsz, seq_len]
return attention_mask


def replace_llama_attn_with_flash_attn():
transformers.models.llama.modeling_llama.LlamaModel._prepare_decoder_attention_mask = _prepare_decoder_attention_mask
transformers.models.llama.modeling_llama.LlamaAttention = LlamaAttention

References

  1. FlashAttention图解(如何加速Attention)
  2. 论文分享:新型注意力算法FlashAttention
  3. FlashAttention2详解(性能比FlashAttention提升200%) - 知乎 (zhihu.com)

Multi-Query Attention

References

  1. FlashAttention与Multi Query Attention

vLLM:PagedAttention

背景:LLM模型在推理过程中,key、value通常会存在GPU中用于生成下一个token。这部分显存占用很大且由于大小是动态变化的,因此会出现过度预留显存导致显存浪费

  1. 借鉴:操作系统中的虚拟内存和分页经典思想
  2. 实现:将每个序列的KV cache进行分块,每个块中包含固定的tokens的key和value。分块之后这部分张量不再需要连续的内存,使得显存的利用率更高。
  3. 特性:memory sharing
    1. 当用单个 prompt 产出多个不同的序列时,可以共享计算量和显存。
    2. 通过将不同序列的 logical blocks 映射到同一个 physical blocks,可以实现显存共享。
    3. 为了保证共享的安全性,对于 physical blocks 的引用次数进行统计,并实现了 Copy-on-Write 机制。
    4. 这种内存共享机制,可以大幅降低复杂采样算法对于显存的需求(最高可下降55%),从而可以提升2.2倍的吞吐量。

References

  1. 大模型推理加速工具:vLLM

xformer

References

DeepSpeed

  1. 推理自适应并行性Inference-adapted parallelism):允许用户通过适应多 GPU 推理的最佳并行策略来有效地服务大型模型,同时考虑推理延迟和成本。

模型训练权重可以加载指定的并行度,另外会为模型插入需要的通信代码协助多GPU通信

  1. 针对推理优化的 CUDA 内核Inference-optimized CUDA kernels):通过深度融合和新颖的内核调度充分利用 GPU 资源,从而提高每个 GPU 的效率。

深度融合就是将多个运算符融合到一个内核中;针对推理优化了GEMM操作。

  1. 有效的量化感知训练Effective quantize-aware training):支持量化后的模型推理,如 INT8 推理,模型量化可以节省内存(memory)和减少延迟(latency),同时不损害准确性。

通过量化混合和INT8推理内核实现,量化混合就是简单地将 FP32 参数值转换为较低精度(INT4INT8 等),然后在权重更新期间将它们存储为 FP16 参数(FP16数据类型,但值映射到较低精度);高性能INT8推理就是加载INT8参数到主存中,加载到共享内存中就会转换成FP16

另外为了减少大模型的训练时间,框架提供了三种技术:

  1. 新的压缩训练策略:大模型训练期间,通过 Progressive Layer Dropping 利用 Transformer 层中粗粒度的稀疏性来降低训练成本,从而在不影响准确性的情况下使收敛速度提高 2.8 倍。
  2. 1 bit 的 LAMB:实现了大模型训练的高效通信,通信量减少 4.6 倍,即使在具有低带宽互连的集群中也能加速大型模型的训练。
  3. DeepSpeed Profiler 性能工具:通过显示模型复杂性和训练效率,以帮助用户识别性能瓶颈。

DeepSpeed 通过系统优化加速大模型推理 - 知乎 (zhihu.com)

ZeRO-零冗余优化器

总体:ZeRO1是优化器切分到各卡,ZeRO2是梯度切分到各卡,ZeRO3是模型参数切分到各卡。OFFLOAD是用一部分内存来补充显存的不足。

ZeRO:Zero Redundancy Optimizer

深度学习模型的大部分内存消耗可以归结为以下三种(文中称为OPG状态):

  1. O:优化器状态(例如Aadam优化器中的的momemtum、variance)
  2. G:梯度
  3. P:参数

ZeRO通过在数据并行进程之间划分OGP模型状态而不是复制它们来消除数据并行进程之间的内存冗余,在训练过程中采用动态通信调度,保持了和数据并行基本一致的计算粒度和通信量,从而保持了计算/通信效率。

具体实现是对OPG状态分别进行优化:

优化器优化每个GPU都保存全部的参数和梯度,但只保存1/Nd的优化器变量

优化器+梯度优化:只保存1/Nd的梯度和优化器变量

优化器+梯度+参数优化: 只保存1/Nd的参数、梯度和优化器变量

论文解读系列第十三篇:ZeRO——面向万亿级参数的模型训练方法 - 知乎 (zhihu.com)

使用说明

在Transformers中集成DeepSpeed - 知乎 (zhihu.com)

应用实例

通过使用HuggingFace的accelerate库实现deepspeed方法

LLM-tuning/llama_tuning/lora_deepspeed at master · jiangxinyang227/LLM-tuning (github.com)

推理加速

Getting Started with DeepSpeed for Inferencing Transformer based Models - DeepSpeed

Refs

  1. DeepSpeed之ZeRO系列:将显存优化进行到底 - 知乎 (zhihu.com)

Sparse Attention

自注意力机制的计算量$O(n^2)$-需要对任意两个向量计算相关度;因此,为了节省现存,基本的思路就是减少关联性的计算.

self-attn

Atrous self attention

类似于膨胀卷积,要求每个元素只跟它相对距离为k,2k,3k,…
的元素关联.相当于每个元素只跟大约n/k
个元素算相关性,这样一来理想情况下运行效率和显存占用都变成了$O(n^2/k)$,也就是说能直接降低到原来的1/k.

Local self attention

就直接是字面意思,将相对距离超过k的注意力全部都设为0.

对于Local Self Attention来说,每个元素只跟2k+1
个元素算相关性,这样一来理想情况下运行效率和显存占用都变成了O((2k+1)n)∼O(kn)了,也就是说随着n而线性增长,这是一个很理想的性质——当然也直接牺牲了长程关联性。
Local Self Attention的注意力矩阵(左)和关联图示(右)

sparse self attention

相当于是atrous+local,实现了除了相对距离不超过k的、相对距离为k,2k,3k,…的注意力都设为0,这样一来Attention就具有“局部紧密相关和远程稀疏相关”的特性,这对很多任务来说可能是一个不错的先验,因为真正需要密集的长程关联的任务事实上是很少的。

Sparse Self Attention的注意力矩阵(左)和关联图示(右)

deepspeed-sparse attention

随机、局部、全局三种注意力的随机组合

image-20230813143710826

Refs

  1. 为节约而生:从标准Attention到稀疏Attention - 科学空间|Scientific Spaces (kexue.fm)
  2. DeepSpeed Sparse Attention - DeepSpeed

本文主要介绍CoT相关的一些方法和技术

CoT

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models

CoT
简单来说就是将原本的问题,经过多个中间步骤最终获取答案,实现更好的推理。

具体实现效果:常识推理能力赶超人类;数学逻辑推理能力大幅度提升;LLM可解释性更强。

  • Zero-shot-CoT

zsCoT

零样本思维链通过引入与样本无关指示,来实现自我增强

  • 多数投票提高CoT性能——自洽性(Self-consistency)

其实核心就是对生成的多个结果选择取多数的答案,这一个可以直接通过控制temprature和Top-K来实现,很显然这会使得时间会变长。

  • LtM(Least to Most prompting)

LtM

将问题按步骤拆分成多个子问题,解决完多个子问题后回答最终问题。具体训练就是分为多个CoT阶段实现。

  • Flan-PaLM/T5:CoT + Finetuning

Flan-T5:在超大规模的任务上对模型进行微调,使得单个模型在1800多个NLP任务上都能够有很好的表现。

微调方法就是在加入CoT数据。其核心是对多任务数据的统一。

实现流程:

  1. 收集带有标签的数据,将每个任务定义为<数据,任务类型>
  2. 对数据的形式进行改写,比如改写成CoT的形式;并对是否需要CoT和few-shot,进行组合构造
  3. 训练过程:恒定的学习率以及 Adafactor 优化器;同时将多个训练样本打包成一个训练样本,通过特殊结束token进行分割。

结论:

  1. 微调有效果,模型越大越好,任务越多越好
  2. 混杂CoT很重要
  • 提升小模型的推理能力:Fine-tune-CoT

旨在利用大模型思维链推理能力指导小模型解决复杂问题。

FuCoT

简单的说就是用ChatGPT这类大模型生成CoT数据,然后再喂给小模型进行微调。同时该方法需要生成尽可能多的数据。

CoT的局限性

  1. 思维链只有在模型规模足够大的时候才适用,如何实现小模型的思维链应用是值得探索的方向
  2. 应用领域有限,当前的实验结果只是在部分领域有所评估。另外,思维链只是提高模型的推理能力,但不代表模型真正理解内在的逻辑

References

  1. 【他山之石】大模型思维链(Chain-of-Thought)技术原理

集成学习概念

  1. bagging与boosting

Bagging和Boosting都是将已有的分类或回归算法通过一定方式组合起来,形成一个性能更加强大的分类器,即将弱分类器组装成强分类器的方法。

  • boosting

串行的方式训练基分类器,各分类器之间有依赖。每次训练时,对前一层基分类器分错的样本给与更高的权重

  • bagging

bagging是Bootstrap aggregating的意思,各分类器之间无强依赖(有放回随机采样训练),可以并行。

  1. 方差与偏差

    • 偏差:描述模型输出结果的期望与样本真实结果的差距

    • 方差:描述模型对于给定值的输出稳定性

  • 基分类器的错误,是偏差和方差之和;

  • boosting方法通过逐步聚焦分类器分错的样本,减少集成分类器的偏差

  • Bagging采用分而治之的策略,通过对样本多次采样,分别训练多个模型,减少方差

  • 为什么决策树是常用的基分类器

可以方便地将样本权重整合到训练过程中,不需要使用过采样的方法来调整样本权重-自带样本权重

决策树的表达能力和泛化能力,可以通过调节树的层数来做折中-易调节

数据样本扰动对决策树影响较大,因此不同子样本集生成的基分类器随机性就较大。这样的不稳定学习器更适合作为基分类器。

神经网络也适合做基分类器

模型

Adaboost

核心点:

  1. 对分类正确的样本降低权重
  2. 对错误分类的样本升高或者保持全都不变
  3. 在模型融合过程中,根据错误率对基分类器器进行加权融合,错误率低的分类器拥有更大的“话语权”

GBDT

优点:

  1. 预测阶段的计算速度快,树与树之间可并行化计算
  2. 分布稠密的数据集上,泛化能力和表达能力都很好。
  3. 采用决策树作为弱分类器使得GBDT模型具有较好的解释性和鲁棒性,能够自动发现特征间的高阶关系,并且也不需要对数据进行特殊的预处理如归一化等。

缺点:

  1. GBDT在高维稀疏的数据集上,表现不如支持向量机或者神经网络。
  2. GBDT在处理文本分类特征问题上,相对其他模型的优势不如它在处理数值特征时明显。
  3. 训练过程需要串行训练,只能在决策树内部采用一些局部并行的手段提高训练速度

XGBoost

  1. GBDT是机器学习算法,XGBoost是该算法的工程实现。
  2. 在使用CART作为基分类器时,XGBoost显式地加入了正则项来控制模型的复杂度,有利于防止过拟合,从而提高模型的泛化能力。
  3. GBDT在模型训练时只使用了代价函数的一阶导数信息,XGBoost对代价函数进行二阶泰勒展开,可以同时使用一阶和二阶导数。
  4. 传统的GBDT采用CART作为基分类器,XGBoost支持多种类型的基分类器,比如线性分类器。
  5. 传统的GBDT在每轮迭代时使用全部的数据,XGBoost则采用了与随机森林相似的策略,支持对数据进行采样,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
  6. 传统的GBDT没有设计对缺失值进行处理,XGBoost可以自动学习出它的分裂方向。XGBoost对于确实值能预先学习一个默认的分裂方向。
  7. Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)

LightGBM

比较:

  1. XGBoost使用基于预排序的决策树算法,每遍历一个特征就需要计算一次特征的增益,时间复杂度为O(datafeature)。
    而LightGBM使用基于直方图的决策树算法,直方图的优化算法只需要计算K次,时间复杂度为O(Kfeature)
  2. XGBoost使用按层生长(level-wise)的决策树生长策略,LightGBM则采用带有深度限制的按叶子节点(leaf-wise)算法。在分裂次数相同的情况下,leaf-wise可以降低更多的误差,得到更好的精度。leaf-wise的缺点在于会产生较深的决策树,产生过拟合。
  3. 支持类别特征,不需要进行独热编码处理
  4. 优化了特征并行和数据并行算法,除此之外还添加了投票并行方案
  5. 采用基于梯度的单边采样来保持数据分布,减少模型因数据分布发生变化而造成的模型精度下降
  6. 特征捆绑转化为图着色问题,减少特征数量

缺点:

  1. 处理缺失值,会先计算分割点,然后将缺失值样本分配给增益高的一侧ref

References

  1. 一篇文章搞定GBDT、Xgboost和LightGBM的面试
  2. GBDT、XGBoost、LightGBM的区别和联系

机器学习一些基础内容的简单整理和归纳。

模型评估与选择

​ 怎么判断一个模型的好坏是一个重要的内容,为此提出了许多相关的指标来对模型进行判断,但总的来说好的模型可以归纳为:错误率低,精度高,泛化能力强

泛化误差:未见过的样本上的误差

经验误差:训练集上的误差

经验误差过小会导致过拟合;泛化误差最小化才是我们的目标

过拟合就是简单来说就是模型的复杂度远高于数据的复杂度,使得训练时模型会尽可能贴合训练数据,但也导致对于未见过的测试数据不能很好的预测,多少有些“中看不中用”的意味。因此,后续也会介绍正则化等手段处理过拟合的情况。

​ 以上的需求总的来说还是十分的抽象,具体到训练模型、测试模型来说,我们判断一个模型的好坏总的流程是:训练模型根据不同的方法我们可以获得模型的预测结果;根据预测结果、样本数,可以对模型进行一个性能评估;训练后获得的模型性能并不能直接根据训练评估获得,需要进一步的判断模型的泛化能力。针对这一流程,接下来将对评估方法、性能度量、比较检验、泛化能力这几部分展开说明。

评估方法

常用的一些方法有:留出法、交叉验证法、自助法

留出法hold-out :就是直接将数据集划分成训练集、验证集、测试集。

交叉验证法k-fold:将当前数据集划分成k个大小一样的数据集,每次用k-1个数据集作为训练集,剩下的一个数据集作为验证集,然后将k次的验证结果做平均得到的结果就是当前基于该数据集模型的性能。

自助法:基于自助采样,即有放回的采样。该方法具体是:先将包含m个样本的数据集进行重复采样获得一个新的数据集,

参考文献

[1] [A Survey of Deep Reinforcement Learning in RecommenderSystems: A Systematic Review and Future Directions](A Survey of Deep Reinforcement Learning in RecommenderSystems: A Systematic Review and Future Directions)

[2] A Survey on Reinforcement Learning for Recommender Systems

[3] Reinforcement Learning based Recommender Systems: A Survey

梯度下降算法(优化器)

BGD&SGD

image-20230528230020032

实现:https://gitee.com/Jonny-Jaia/ready-blog/blob/master/3-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/GradientDescent.py

批量梯度下降相当于直接对所有数据一次性梯度下降;

随机梯度下降则是在BGD的基础上增加随机打乱输入的数据;

Sharpness-Aware Minimization (SAM)

SAM:Sharpness-Aware Minimization for Efficiently Improving Generalization

研究背景

主要工作

1.

References

  1. 不同梯度下降算法的比较及Python实现
  2. Sharpness-Aware Minimization (SAM): 簡單有效地追求模型泛化能力
  3. davda54/sam - Sharpness-Aware Minimization (PyTorch)

机器学习模型

线性函数与非线性函数的区别

通过增加非线性去拟合线性不可分的数据。如果不增加非线性操作,多层线性的操作链接等价于一层线性操作。

非线性函数使得映射更加复杂进而更容易拟合到对应的空间中去。

逻辑回归

Logistic Regression 虽然被称为回归,但其实际上是分类模型,并常用于二分类。

Logistic 回归的本质是:假设数据服从这个分布,然后使用极大似然估计做参数的估计。

逻辑回归是在线性回归的基础上加了一个 Sigmoid 函数(非线性)映射。

逻辑回归的思路是,先拟合决策边界(不局限于线性,还可以是多项式),再建立这个边界与分类的概率联系,从而得到了二分类情况下的概率。

本质上来说,两者都属于广义线性模型,但他们两个要解决的问题不一样,逻辑回归解决的是分类问题,输出的是离散值,线性回归解决的是回归问题,输出的连续值。

优点

  • 直接对分类的概率建模,无需实现假设数据分布,从而避免了假设分布不准确带来的问题(区别于生成式模型);
  • 不仅可预测出类别,还能得到该预测的概率,这对一些利用概率辅助决策的任务很有用;
  • 对数几率函数( Sigmoid 函数)是任意阶可导的凸函数,有许多数值优化算法都可以求出最优解。

代价函数

极大似然估计求解。在逻辑回归模型中,我们最大化似然函数和最小化损失函数实际上是等价的。

References

  1. 【机器学习】逻辑回归(非常详细)

朴素贝叶斯分类器

References

  1. 机器学习—朴素贝叶斯分类器(Machine Learning Naive Bayes Classifier) - HuZihu - 博客园 (cnblogs.com)

LSTM&GRU

LSTM:记忆单元+门控单元(遗忘门-sigmoid,会与旧的记忆相乘;输入门-分别用sigmoid和tanh调节输入-上一时刻隐特征+输入,加上上面的记忆单元;输出门-经过sigmoid,然后把记忆单元经过tanh在与其乘积得到输出)

LSTM避免梯度消失和梯度爆炸

一般梯度爆炸可以通过裁剪解决优化,针对梯度消失由于当前的状态是通过累加形式实现,不再是复合形式,使得梯度也不再是乘积的形式。进而解决梯度消失情况

GRU:

重置门&更新门

References

  1. 25. 簡介LSTM 與GRU - Programming with Data - Medium

正则化

L1、L2正则化

L1范数:曼哈顿距离
L2范数:欧氏距离

数值理解

L1正则化是指权重矩阵中各个元素的绝对值之和,为了优化正则项,会减少参数的绝对值总和,所以L1正则化倾向于选择稀疏(sparse)权重矩阵(稀疏矩阵指的是很多元素都为0,只有少数元素为非零值的矩阵)。L1正则化主要用于挑选出重要的特征,并舍弃不重要的特征。

L2正则化是指权重矩阵中各个元素的平方和,为了优化正则项,会减少参数平方的总和,所以L2正则化倾向于选择值很小的权重参数(即权重衰减),主要用于防止模型过拟合。是最常用的正则化方法。一定程度上,L1也可以防止过拟合。

分布理解

我们可以分别假设权重的先验分布,进而得到当前的正则化效果,具体来说:

  • L1正则化:先验分布-拉普拉斯分布
  • L2正则化:先验分布-高斯分布

直观视觉

两种正则化就是在不同的范数球上更新权重

L1
L2

References

  1. L1、L2正则化和过拟合
  2. 深入理解L1、L2正则化

损失函数

分类问题用 Cross-entropy,回归问题用 mean squared error。

  • 问题1:

均方差损失计算

image-20230527150851699

对于当前是逻辑回归算法的计算,当结果为0,1梯度都为0

当输入较大或者较少的时候会使得训练出现梯度消失的情况

交叉熵损失计算

image-20230527151058196

与均方差损失计算不同,就不会出现以上的情况

只取决于输出结果的偏差大小,梯度越大,训练速度越快

交叉熵

  1. 二分类:
    $$ loss=-\frac{1}{N} \sum_{i=1}^{N} [y_i log(f(x_i)) + (1-y_i)log(1-f(x_i))] $$

  2. 多分类:
    $$ loss=-\frac{1}{N} \sum_{k=1}^{N} \sum_{i=0}^{C-1}y_ilog(p_i) $$

交叉熵是用来评估当前训练得到的概率分布与真实分布的差异情况。 它刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近。

用交叉熵计算损失,当前问题依旧是凸优化问题

优点:

  • loss结果直接由误差控制优化

缺点:

  • 采用了类内竞争机制

    只关心对于正确标签预测概率的准确性,忽略了其他非正确标签的差异,导致学习到的特征比较散。
    基于这个问题的优化有很多,比如对softmax进行改进,如L-Softmax、SM-Softmax、AM-Softmax等。

均方差损失(MSE)

$$ loss=\frac{1}{2}(y-\hat{y})^{2} $$

一个batch中n个样本的n个输出与期望输出的差的平方的平均值.

缺点:

  • 当梯度比较小的时候,没办法判断当前是否在目标附近(很远的时候梯度也比较小)-梯度消失

KL散度

References

  1. 【超详细公式推导】关于交叉熵损失函数(Cross-entropy)和 平方损失(MSE)的区别

Focal loss

image-20230828224830807
相当于当$\gamma=0$时,loss就是交叉熵带正负样本比例调节的版本。

GHM

Focal loss过于关注那些难分的样本也是有问题的,样本中存在离群点,过分关注反倒会使得性能下降。并且这一损失的计算由两个超参数同时调控,靠经验调优,是比较难实验得到好的效果的。

Refs

  1. 5分钟理解Focal Loss与GHM——解决样本不平衡利器 - 知乎 (zhihu.com)

HMM与CRF

区别

  • 类型:

CRF:判别模型,对问题的条件概率分布建模;

HMM:生成模型,对联合概率分布建模;

HMM可以看成是CRF的特殊情况。

  • 特征选择:

CRF:可以用前一时刻和当前时刻的标签构成的特征函数,加上对应的权重来表示

HMM中的转移概率:可以用当前时刻的标签和当前时刻对应的词构成的特征函数,加上权重来表示 HMM 中的发射概率

  • CRF的优势:

CRF 相比 HMM 能够利用更加丰富的标签分布信息

  1. HMM只能使用局部特征,转移概率只依赖前一时刻和当前时刻,发射概率只依赖当前时刻,CRF 能使用更加全局的特征
  2. HMM 中的概率具有一定的限制条件,如0到1之间、概率和为1等,而 CRF 中特征函数对应的权重大小没有限制,可以为任意值

判别式模型与生成式模型

  1. 判别式

直接对$P(Y|X)$建模;对所有样本只构建一个模型,确认总体判别边界;对于输入的特征预测最有可能的label(在已知label里面挑选);

优点:对数据量没有生成式严格,速度快,小数据量下准确率也会好些

  1. 生成式

直接对$P(X,Y)$建模;要对每一个label都建模,选择最优概率label为结果;中间生成联合分布,可生成采样数据;包含信息十分齐全,因此需要比较充足的数据量,但速度相对更慢。

BiLSTM-CRF

CRF的引入

  • 定义

线性条件随机场

在序列标注中,分别计算发射概率(x-yi)和转移概率(yi-1-yi),具体来说需要维护转移矩阵;

计算完得分之后,需要进行Normalizer计算-需要对当前x所有可能的输出序列得分计算求和,因此采用DP复用计算结果,提高效率。

解码过程,采用序列最优路径Viterbi算法。

beam search 的操作属于贪心算法思想,不一定reach到全局最优解。因为考虑到seq2seq的inference阶段的搜索空间过大而导致的搜索效率降低,所以即使是一个相对的局部优解在工程上也是可接受的。

viterbi属于动态规划思想,保证有最优解。viterbi应用到宽度较小的graph最优寻径是非常favorable的,毕竟,能reach到全局最优为何不用!

image-20230606081022890

CRF矩阵的参数量

1
2
3
self.start_transitions = nn.Parameter(torch.empty(num_tags))
self.end_transitions = nn.Parameter(torch.empty(num_tags))
self.transitions = nn.Parameter(torch.empty(num_tags, num_tags))

CRF的更新

References

  1. 概率图模型体系:HMM、MEMM、CRF
  2. CRF 和 HMM 的区别与联系
  3. CRF条件随机场的原理、例子、公式推导和应用
  4. LSTM+CRF实现序列标注

常用的评价指标

分类任务:

  1. 准确率:预测正确样本占样本的个数
  2. 精确率:分类正确正样本占预测正样本个数
  3. 召回率:分类正确正样本占真实正样本个数
  4. P-R曲线:横轴召回、纵轴精确
  5. F1:精确率与召回率的调和平均值
  6. ROC曲线:横轴假阳性、纵轴真阳性
  7. AUC:ROC曲线下的面积大小

回归任务:

  1. 均方根误差

Refs

  1. AUC、ROC详解:原理、特点&算法-腾讯云开发者社区-腾讯云 (tencent.com)
  2. 模型评估指标AUC和ROC,这是我看到的最透彻的讲解-腾讯云开发者社区-腾讯云 (tencent.com)

归一化方法

将特征都归一化到大致相同的数值区间
使得算法更加稳定,加快算法的收敛速度
增加计算量、可能会导致信息丢失

机器学习:

  1. 最大最小归一化
  2. 线性归一化-直接除以最大值
  3. 零均值归一化-减去均值除以方差:消除量纲的同时也消除各变量的差异(方差一致)

机器学习中的应用

需要归一化:KNN(需要计算距离);线性回归、逻辑回归、SVM,NN(梯度下降求解,防止奇异值带来的影响)

不需要归一化:决策树、随机森林(树模型)-数值大小不影响条件概率以及对应的模型分裂点

深度学习:
尽可能保证输入的特征是独立同分布的,另外通过这种方式也能够降低结果在激活函数的非饱和区域出现梯度消失抑或是梯度爆炸等情况的出现。

  1. batchnorm

对batch数据计算均值和方差。

问题:

  • 一个batch里面的数据不能差异太大
  • 由于batch的并行计算,不适用于动态网络结构和RNN网络(序列化数据网络)
  • 适用于batch比较大,数据分布比较接近,且训练前经过充分的打乱
  • 只用于训练不用于推理
  1. layernorm

对样本单层输入做归一化处理,计算对应的均值和方差

  • 避免受batch大小的影响
  • 也可用于不同的场景
  • 也不需要保存每个batch的均值和方差,节省存储

参考

  1. 归一化方法总结 | 又名”BN和它的后浪们”
  2. 【关于 归一化】那些你不知道的事
  3. 【关于 BatchNorm vs LayerNorm】那些你不知道的事

多分类问题

机器学习中针对多分类问题,常用的解决办法就是训练多个分类器针对不同类别去分类。

可以直接是每个分类器针对单独类别进行识别;也可以是多个二分类器实现多分类的预测;

在深度学习中,其实可以直接设计多标签的形式进行模型训练,就不再采用softmax,采用binary_crossentropy损失函数函数。

高斯混合模型

Refs

  1. 高斯混合模型 | 机器之心 (jiqizhixin.com)

降维方法

降维动机

  1. 减少空间与训练用时,提高一些算法的可用性
  2. 删除冗余特征,有助于可视化分析

方法

  1. 删除
  • 缺失值比率较高的
  • 将低方差数据删除(说明数据基本一致,携带信息不足)
  • 将相关度较高的变量删除(说明数据携带相似的信息)
  • 采用随机森林选择小的特征子集
  • 比较删除某变量之后的模型性能-反向特征消除
  • 每次训练多个模型,将有性能提升的特征筛选出来
  1. 新变量
  • 因子分析-从多个变量中提取共性因子,将变量按照相关性分组,特定组内所有变量相关性较高,组间相关性低
  • PCA
  • 独立分量分析ICA-PCA寻找不相关的因素,而ICA寻找独立因素。
  • 流形学习-解决非线性:UMAP、ISOMAP、t-SNE

Refs

  1. 12种降维方法终极指南(含Python代码) - 知乎 (zhihu.com)

梯度消失问题缓解

GPT4

  1. 使用ReLU激活函数:ReLU(Rectified Linear Unit)及其变种(如Leaky ReLU、Parametric ReLU和Exponential Linear Unit)是非饱和激活函数,它们在正区间内的梯度为1,因此不容易遭受梯度消失问题。

  2. 使用更好的权重初始化方法:例如,使用He初始化或Glorot初始化可以帮助减少梯度消失或梯度爆炸问题。

  3. 批量归一化(Batch Normalization):批量归一化可以使每一层的输入都保持相同的尺度,从而减少梯度消失问题。

  4. 使用残差网络(Residual Networks,ResNet):ResNet通过引入跳跃连接(或称为残差连接)来避免梯度消失。这些连接允许梯度直接反向传播到较早的层。

  5. 使用门控单元:在递归神经网络(RNN)中,使用长短时记忆网络(LSTM)或门控循环单元(GRU)可以帮助减少梯度消失问题。

  6. 梯度剪裁(Gradient Clipping):虽然这主要是为了避免梯度爆炸问题,但在某些情况下,它也可以帮助减少梯度消失。

  7. 使用更浅的网络:减少网络的深度可以直接减少梯度消失问题,但这可能会牺牲模型的表示能力。

  8. 使用其他优化器:某些优化器,如Adam、RMSprop等,已经内置了梯度的缩放机制,这可以在某种程度上减少梯度消失问题。

  9. 正则化技术:如Dropout,虽然其主要目的是防止过拟合,但在某些情况下,它也可以帮助减少梯度消失。

  10. 使用注意力机制:在序列到序列的模型中,使用注意力机制可以帮助模型关注输入序列的重要部分,从而减少梯度消失问题。

优化器

优化框架

概述:计算梯度之后的更新,需要考虑之前更新的一些情况,比如之前更新的幅度大小以及过去的更新累积。通过一阶动量的引入,减少梯度的震荡;通过二阶动量的引入,调控参数的更新频率,实现自适应的效果。最后,利用优化后的梯度量去更新参数。

  1. 计算目标函数对应的梯度:$g_t = \nabla f(w)$
  2. 根据历史梯度计算一阶动量与二阶动量 $m_t = \phi(g_1,g_2,..),V_t = \Phi(g_1,g_2,..)$
  3. 计算当前时刻的梯度下降大小:$\eta = \alpha \times m_t /\sqrt{V_t}$
  4. 参数更新:$w = w-\eta$

SGD

$m_t = g_t,\eta = \alpha \times g_t$

SGD with Momentum

为了抑制震荡,SGDM相当于加入了惯性,一阶动量$m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t$

SGD with Nesterov Acceleration

防止提前陷入局部点,优化梯度计算,不采用当前位置的梯度方向,而是按照累积动量走了一步的下降方向进行更新。

$g_t = \nabla f(w_t-\alpha \cdot m_{t-1})$

AdaGrad

自适应学习率的第一次引入,借助二阶动量。由于经常更新的参数累积了大量的知识,我们不希望其会受到单个样本的影响过大,使得其学习率要小一些,而相反更新较少的参数则需要设置较大的学习率.
为了度量过去更新的频率,采用二阶动量-即是所有梯度值的平方和具体如下:
$V_t= \sum_{\tau=1}^{t}g_{\tau}^{2}$

那么梯度大小:
$\eta = \alpha \times m_t /\sqrt{V_t}$,其中分母会加上一个小值避免为0.

问题:由于二阶动量是递增的,会使得学习率单调递减至0,可能会使得训练提前结束。

AdaDelta/RMSProp

改进二阶动量的计算策略,不累积全部历史梯度,而只关注过去一段时间窗口的下降梯度。

新的二阶动量计算:
$V_t= \beta_2 \cdot V_{t-1} + (1-\beta_2)\cdot g_{t}^{2}$ 避免了二阶动量持续累积、导致训练过程提前结束的问题了。

Adam

Adam——Adaptive + Momentum-将一阶动量和二阶动量结合起来

SGD一阶动量$m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t$

AdaDelta二阶动量$V_t= \beta_2 \cdot V_{t-1} + (1-\beta_2)\cdot g_{t}^{2}$

缺点:

  1. 当前这种窗口二阶动量会随着时间窗口变化,导致二阶动量时大时小,在训练后期会引起学习率的震荡导致模型无法收敛

修正:
$V_t= \max(\beta_2 \cdot V_{t-1} + (1-\beta_2)\cdot g_{t}^{2},V_{t-1})$ 保证学习率单调递减

  1. 自适应算法可能会对前期出现特征过拟合的情况,后期由于学习率太低等原因,会出现特征难以纠正前期的拟合效果,并最终影响收敛性能。

修正:
Adam+SGD

Nadam

Nesterov + Adam = Nadam

引入Nesterov 提前考虑下一步动作的梯度
$g_t = \nabla f(w_t-\alpha \cdot m_{t-1}/\sqrt{V_{t-1}})$

AdamW

AdamW就是Adam优化器加上L2正则

Ref

  1. 深度学习优化算法,从 SGD 到 AdamW 原理和代码解读
  2. 一个框架看懂优化算法之异同 SGD/AdaGrad/Adam - 知乎 (zhihu.com)
  3. Adam那么棒,为什么还对SGD念念不忘 (2)—— Adam的两宗罪 - 知乎 (zhihu.com)
  4. Adam那么棒,为什么还对SGD念念不忘 (3)—— 优化算法的选择与使用策略 - 知乎 (zhihu.com)

学习率衰减策略

字面意思直接控制学习率的变化

img

Refs

  1. pytorch必须掌握的的4种学习率衰减策略 - 知乎 (zhihu.com)

kmeans聚类算法

  1. 初始化,随机选择k个样本点最为初始聚类中心;
  2. 对样本进行聚类,计算每个样本到类中心距离,将样本分类到最近中心;
  3. 按照聚类的结果,重新计算新的聚类中心;
  4. 若迭代收敛或者符合停止条件则返回聚类中心

算法复杂度:O(mnk),m样本维度,n样本个数,k类别个数

类别k选择:尝试不同的k检验推测;聚类质量可以通过类的平均直径判断,类别超过一定值之后平均直径不会发生改变这时就是最优的k值

对比学习相关基础

梯度回传方法

端到端

memory bank

MoCo方法

MoCo

研究背景

主要工作

1.

References

  1. 无监督学习: Kaiming一作 动量对比(MoCO)论文笔记
  2. Self-Supervised Learning 超详细解读 (四):MoCo系列解读 (1)

Simcse

背景:bert模型词向量在空间中的分布不均匀,高频词分布紧凑,低频词分布稀疏

对比学习-拉近相似样本距离,推开不相似样本的距离

损失函数:
$l_i = log \frac{e^{sim(h_i,h^+i)/\tau}}{\sum{j=1}^N e^{sim(h_i,h^+_j)/\tau}}$

Refs

  1. SimCSE论文解读 - 知乎 (zhihu.com)
  2. 论文分享 | EMNLP-21 | 句子嵌入的一种简单对比学习方法_哔哩哔哩_bilibili

TRPO 与 PPO

TRPO:Trust Region Policy Optimization

PPO:Proximal Policy Optimization

研究背景

策略梯度方法以及存在的缺点:策略梯度方法

TRPO相关内容

TRPO研究思路

TRPO算法尽量通过能提高状态价值的方式来更新策略。它通过在新旧策略之间增加约束,将整个参数空间的变化限制在一个小范围之内,从而避免了错误决策导致Value的崩塌,尽可能的保持快速而单调的提升。

TRPO更新与实现

  1. 在原有问题上增加约束项,两个策略的KL散度计算
  2. 引入 trust region方法去优化找到最优解
  3. 对当前优化问题做了一定的简化,减小计算量。具体有:平均KL散度代替最大KL散度对约束问题二次近似非约束问题一次近似

更新流程

PPO相关内容

PPO研究思路

TRPO中的二阶计算量还是非常大,因此基于此有了PPO算法。为了让当前策略上进行有效更新时不至于导致Value的崩溃,PPO可以看成是TRPO的一阶近似方案,其试用范围更广、计算效率更高、更容易实现。

v1:修改了KL散度的约束方式,它不再添加硬约束,而是通过在目标函数中加入KL散度的正则项的方式来处理约束问题。

v2:则删除了约束,直接使用强制剪裁的暴力方式来让$\theta$的更新保持在一定范围之内。

v2-目标函数实现:
$$
\mathcal{L}(s, a,\theta_k, \theta) = min(\frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)} A_{\pi_{\theta_k}}(s,a) , clip( \frac{\pi_\theta(a|s)}{\pi_{\theta_k}(a|s)}, 1-\epsilon, 1+ \epsilon) A_{\pi_{\theta_k}}(s,a))
$$

拆分讲解:

image-20230605150906170

GAE:PPO的实现

GAE:generalized advantage estimator

核心思路:优势函数用类似于multi-step td去实现,获得优势函数的指数加权移动平均,这可以让优势估计更加平滑和稳定。

具体实现:

n步的Adventage的$\hat{A}t^{(n)}$估计
$$
\begin{align} \hat{A}t^{(1)} &= \delta_t^V = -V(s_t)+r_t+\gamma V(s{t+1}) \ \hat{A}t^{(2)} &= \delta_t^V + \gamma \delta{t+1}^V = -V(s_t)+r_t+ \gamma r
{t+1} +\gamma^2 V(s_{t+2}) \ \hat{A}t^{(3)} &= \delta_t^V + \gamma \delta{t+1}^V + \gamma^2 \delta_{t+2}^V = -V(s_t)+r_t+ \gamma r_{t+1} + \gamma^2 r_{t+2} +\gamma^3 V(s_{t+3}) \ … \ \hat{A}t^{(k)} &= \sum^{k-1}{l=0}\gamma^l\delta_{t+l}^V = -V(s_t)+r_t+\gamma r_{t+1} + … + \gamma^{k-1}r_{t+k-1}+ \gamma^kV(s_{t+k})\ \end{align}
$$

在并不知道取哪几步优势最好的情况下,并不能确定一个最好的n,GAE则是取附近值的指数加权移动平均,加权系数$\lambda$:
$$
\hat{A}_t^{GAE(\gamma, \lambda)} = (1-\lambda)(\hat{A}_t^{(1)}+ \lambda \hat{A}_t^{(2)} + \lambda^2\hat{A}_t^{(3)}+…)
$$
当$\lambda = 0$ 时, $\hat{A}_t = \delta_t$ , 相当于one-step的TD。

当$\lambda = 1$ 时, $\hat{A}t = \sum^{\inf}{l=0}\gamma^l\delta_{t+l}$ , 相当于玩完整局才更新。

References

  1. 深入理解TRPO和PPO算法

DPG、DDPG与TD3

DPG

DPG是确定性的策略输出,也就是说相对于随机策略输出,DPG算法面对同一个状态时将输出同一个动作,而随机策略比如说PPO,它在面对连续的动作空间时,将输出一个高斯分布的均值mu和方差sigma,并利用这个高斯分布进行采样,每一次输出的动作将不同。

在随机策略的更新中(PPO等),loss=neg_log_prob(a)*A(s,a),其中就需要得到动作a的选择概率。因此,随机策略更新可以直接采用策略梯度的目标函数进行梯度更新。

确定性策略中的动作输出代表当前的概率始终为1,所以确定性策略最大的问题在于如何去更新:

actor的目标就是采取动作a之后获取更高的后续价值,因此通过TD-target实现这一更新梯度

$loss = -Q(s,\mu_{\theta}(s))$

DDPG

DDPG主要是做了两方面改进,主要是源自于DQN的trick,Replay Buffer 和 target network

target network则是在计算loss的target部分时,为了避免Q值更新波动,采用另外的网络来计算更新的方法;其中,target网络是采用滑动更新的

TD3

TD3基于DDPG的改进主要有3方面,分别是 double Q、 Delayed update、
target policy smoothing regularization

  • double Q:

在DQN中,因为DQN也有target网络,所以DQN干脆直接让target网络作为第二个Q的计算网络。可以看到这个target的Q是用目标网络来算的。

在TD3中,作者没有延续DQN使用target网络作为第二个Q的方案,而是又弄了两个网络,直接用最小的Q来作为target Q了,然后每一次更新当然也把两个Q都更新一遍。因此,相当于有6个Q网络。

  • Delayed update:

延迟更新是指在更新actor网络的时候,延迟几次

  • target policy smoothing regularization

作者认为相似的动作应该会有相似的值,由此提出了在目标动作的小范围拟合值的方法

image-20230810000932103

References

  1. 强化学习基础7:从DPG、DDPG到TD3

AC、A2C与A3C

AC框架
策略梯度一般可以写为:

image-20230810130747866

其中的$\phi_t$可以分别采用累计回报(总回报、动作开始后回报、带基线回报-回报的累计会导致方差大),值函数估计(动作值函数、优势函数、TD偏差-近似代替累计回报会导致偏差较大)

经典AC方法:actor-策略梯度,critic-值函数

image-20230810182145467

  • A2C

常常通过增加基线,降低模型的方差使得输出值能够标准化限制在一定范围;
值函数转换成用优势函数代替:$Q^\pi(s_t^{n},a_t^{n})-V^\pi(s_t^{n})$。评估网络只能实现一个值的评估,因此Critic变为估计状态价值V的网络,具体的更新loss:

img

  • A3C

核心思路就是异步结构,通过多个不同状态的a2c网络更新,结合多个进程实现整体的更新
img

References

  1. 强化学习(十三 )–AC、A2C、A3C算法
  2. Actor-Critic算法小结
  3. 强化学习AC、A2C、A3C算法原理与实现! - 知乎 (zhihu.com)

SAC

背景

  • 随机策略PPO:重要度采样方法在应用于训练与交互policy差异过大的情况无法处理。
  • 确定性策略DDPG:超参数敏感

工作

核心:最大熵算法,也采用随机分布式策略,并且是off-policy,ac算法。

实现不同:优化策略获得更高累计收益的同时也会最大化策略的熵

表现:稳定,有较强的抗干扰能力

最大熵作用:可以让策略尽可能随机,实现更充分的探索,避免策略过早落入局部最优点

熵公式:$H(P)=\underset{x \sim P}{\mathrm{E}}[-\log P(x)]$,其中x服从分布P

最大化熵强化学习:

  1. 目标函数:$\pi_{\text {MaxEnt }}^{*}=\arg \max {\pi} \sum{t} \mathbb{E}{\left(s{t}, a_{t}\right) \sim \rho_{\pi}}\left[r\left(s_{t}, a_{t}\right)+\alpha H\left(\pi\left(\cdot \mid s_{t}\right)\right)\right]$

    $\rho_{\pi}$ 表示在策略$\pi$ 控制下,智能体(agent)会遇到的状态动作对(state-action pair)所服从的分布。 $\alpha$ 是名为温度系数的超参数,用于调整对熵值的重视程度。

Soft Value Function and Energy Based Policy

SVF:

image-20230814151301079

EBP:

image-20230814152114142

References

  1. SAC(Soft Actor-Critic)阅读笔记 - 知乎 (zhihu.com)

CQL

主要思想是在Q值基础上增加一个regularizer,学习一个保守的Q函数,作者从理论上证明了CQL可以产生一个当前策略的真实值下界,并且是可以进行策略评估和策略提升的过程。

References

  1. 离线强化学习(Offline RL)系列3: (算法篇) CQL(Conservative Q-Learning)算法详解与实现_cql算法_@RichardWang的博客-CSDN博客

REM

References

  1. 离线强化学习(Offline RL)系列3: (算法篇) REM(Random Ensemble Mixture)算法详解与实现_offline强化学习方法有哪些_@RichardWang的博客-CSDN博客

BCQ

References

  1. 离线强化学习(Offline RL)系列3: (算法篇)策略约束-BCQ算法详解与实现_连续状态下的基于策略的算法_@RichardWang的博客-CSDN博客
0%