Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

TensorFlow——分布式训练之PS架构


整体说明

  • 深度学习的PS(Parameter Server,参数服务器)架构是一种分布式训练框架,用于高效管理大规模模型参数的更新与同步
  • 其核心思想是将参数存储和计算分离,通过一个或多个中心服务器(Parameter Server)集中维护模型参数,而工作节点(Worker)负责本地计算和梯度更新,并通过网络与服务器通信
  • PS 架构支持异步或同步训练,适合处理海量数据和超大规模模型,显著提升了分布式深度学习的扩展性和效率

角色介绍

Parameter Server(参数服务器,PS)

  • 角色 :
    • 负责存储和更新模型的全局参数(如神经网络的权重、梯度等)
    • 聚合来自不同Worker的梯度,应用优化算法(如SGD)更新参数
    • 提供参数的集中式管理,确保一致性
  • 机器类型 :
    • 通常是高性能的CPU服务器(因为参数更新是计算密集型操作,但不需要GPU的并行计算能力)
    • 可以是单台机器或多台机器组成的集群(根据模型规模横向扩展)

Worker(工作节点)

  • 角色 :
    • 负责计算 :读取训练数据、执行前向传播和反向传播,计算本地梯度
    • 将梯度发送给PS,或从PS拉取最新的参数(同步或异步更新)
    • 如果Worker包含Chief(主Worker),它还负责模型初始化、检查点保存、日志汇总等额外任务
  • 机器类型 :
    • 通常是配备GPU的机器(适合大规模矩阵运算)
    • 每个Worker可以独立处理一个数据分片(数据并行)

其他辅助角色:

  • Chief Worker(可选):
    • 一个特殊的Worker(通常编号为worker0),负责全局协调(如初始化参数、恢复训练、保存模型等)
    • 在TF 2.x中,这部分功能逐渐被整合到更高级的API(如tf.distribute.Strategy)中
  • Evaluator(评估器,可选):
    • 独立于训练过程,定期加载模型快照进行验证/测试

一次完整训练过程

  • 以下是包含 4个PS、8个Worker(含1个Chief Worker)和 1个Evaluator 的分布式TensorFlow训练过程的详细步骤

初始化阶段

  • Chief Worker(worker0) :
    • 构建计算图,定义模型结构(如神经网络层、损失函数、优化器等)
    • 生成参数的初始值(如随机初始化),并将这些参数分片推送到4个PS(每个PS存储部分参数)
    • 通知其他Worker和Evaluator初始化完成
  • PS :
    • 存储Chief Worker推送的初始参数(每个PS负责存储分配给自己的参数分片)
    • 等待Worker的梯度更新请求
  • 其他Worker(worker1~worker7) :
    • 等待Chief Worker完成参数初始化
    • 从PS拉取各自所需的参数分片
  • Evaluator :
    • 从PS拉取初始参数,准备后续的验证任务

训练阶段(同步更新示例)

步骤① Worker计算梯度
  • 每个Worker(包括Chief):
    • 从本地数据分片中读取一个batch的数据
    • 从PS拉取最新的参数(全量或分片)
    • 执行前向传播和反向传播,计算本地梯度
步骤② 梯度聚合与参数更新
  • 等待所有8个 Worker 完成梯度计算并上传梯度到 PS
  • PS 聚合所有 Worker 的梯度(求平均)
  • PS 应用优化器(如SGD)更新参数
  • 等待 PS 参数更新完成后,Worker 拉取新参数进入下一轮训练
步骤③ 循环迭代
  • 重复步骤①~②,直到达到最大训练步数或收敛

验证(由 Evaluator 并行执行)

  • 每隔 N 个训练步:
    • Evaluator 从 PS 拉取最新参数
    • 在独立的验证数据集上计算指标(如准确率、损失)
    • 将结果反馈给 Chief Worker(可选)

检查点保存(由 Chief Worker 负责)

  • 每隔 M 个训练步:
    • Chief Worker 将模型参数和训练状态保存到磁盘(Chief 可部分读取PS参数,增量写入 Checkpoint)
    • 如果训练中断,可从检查点恢复

关键交互流程说明

1
2
3
4
5
Chief -> PS : 初始化(推送)/保存模型(拉取)
Worker -> PS : 拉取参数
Worker -> PS : 推送梯度
PS -> PS : 内部同步参数分片(如需,一般怒需要这一步)
Evaluator -> PS : 拉取参数验证

角色分工总结

角色 数量 职责
PS 4 存储参数分片,接收梯度并更新参数。
Worker 8 计算梯度(worker0是Chief,负责初始化/保存模型)。
Evaluator 1 定期验证模型性能,不影响训练流程。

其他注意事项

  • PS 不需要 GPU,使用大内存 + CPU 即可
  • PS 的数量一般为1个即可,除非参数量很大(一个存不下),此外,如果 worker 数量太多时,也可以适当增加 PS 数量,防止网络带宽成为瓶颈
  • 可选择异步训练,此时Worker无需等待其他节点,直接推送梯度到PS并更新参数(但可能梯度冲突)
  • Worker不一定需要存储全部参数,每次可以仅拉去一个层或者某个特定参数进行计算
  • 在 TensorFlow 的 PS 架构中,训练过程默认是异步的 ,但也可以通过配置实现同步训练
  • PS 架构可以支持Torch,但需要结合特定的第三方工具或框架来实现分布式训练

附录:训练代码示例

  • 一个简单的 PS 架构分布式训练代码Demo

    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
    import tensorflow as tf
    import os
    import argparse

    def build_model():
    """简单模型构建"""
    model = tf.keras.Sequential([
    tf.keras.layers.Dense(64, activation='relu', input_shape=(784,)),
    tf.keras.layers.Dense(10, activation='softmax')
    ])
    model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
    )
    return model

    def main(args):
    # 设置TF_CONFIG环境变量
    tf_config = {
    'cluster': {
    'chief': [args.chief],
    'worker': args.workers,
    'ps': args.ps_servers, # 参数服务器角色
    'evaluator': [args.evaluator]
    },
    'task': {
    'type': args.task_type,
    'index': args.task_index
    }
    }
    os.environ['TF_CONFIG'] = tf.constant(tf_config) # 所有任务的这个配置都是一样的

    # 根据任务类型选择不同的分布式策略
    if args.task_type in ['chief', 'worker', 'ps']:
    # 使用ParameterServerStrategy
    strategy = tf.distribute.experimental.ParameterServerStrategy()
    else:
    # Evaluator不需要分布式策略
    strategy = tf.distribute.get_strategy()

    # 数据加载和预处理
    (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
    x_train = x_train.reshape(-1, 784).astype('float32') / 255.0
    x_test = x_test.reshape(-1, 784).astype('float32') / 255.0

    # 创建数据集
    train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(64)
    test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(64)

    # 根据任务类型执行不同操作
    if args.task_type == 'chief':
    print("Running chief task...")
    with strategy.scope():
    # chief下,下面的语句会进行参数初始化
    model = build_model() # 上面指定的strategy策略会依据不同角色做不同的事情,这里 ParameterServerStrategy 策略会在首席节点(chief)对模型参数进行初始化,之后再把这些参数分发给各个工作节点(worker)和参数服务器(PS)

    callbacks = [
    tf.keras.callbacks.ModelCheckpoint(filepath='./checkpoints/model.ckpt'),
    tf.keras.callbacks.TensorBoard(log_dir='./logs')
    ]

    model.fit(train_dataset, epochs=10, callbacks=callbacks)
    print("Chief training completed.")

    elif args.task_type == 'worker':
    print(f"Running worker task {args.task_index}...")
    with strategy.scope():
    model = build_model() # strategy策略会依据不同角色做不同的事情

    model.fit(train_dataset, epochs=10)
    print(f"Worker {args.task_index} training completed.")

    elif args.task_type == 'ps':
    print(f"Running parameter server task {args.task_index}...")
    # 参数服务器不需要显式代码,策略会自动管理
    server = tf.distribute.Server(
    tf_config['cluster']['ps'][args.task_index],
    job_name="ps",
    task_index=args.task_index
    )
    server.join() # 参数服务器会一直运行直到训练结束

    elif args.task_type == 'evaluator':
    print("Running evaluator task...")
    model = build_model()
    model.load_weights('./checkpoints/model.ckpt') # 加载最新的模型,进行评估工作
    eval_results = model.evaluate(test_dataset)
    print(f"Evaluation results: {eval_results}")

    if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--chief', type=str, required=True, help='Chief address')
    parser.add_argument('--workers', type=str, nargs='+', required=True, help='Worker addresses')
    parser.add_argument('--ps_servers', type=str, nargs='+', required=True, help='Parameter server addresses')
    parser.add_argument('--evaluator', type=str, required=True, help='Evaluator address')
    parser.add_argument('--task_type', type=str, required=True, choices=['chief', 'worker', 'ps', 'evaluator'], help='Task type')
    parser.add_argument('--task_index', type=int, required=True, help='Task index')

    args = parser.parse_args()
    main(args)
  • 注:以上是TensorFlow 2.x版本(tf.distribute.experimental.ParameterServerStrategy()就是TensorFlow 2.x才有的)

    • 实际上,TensorFlow 1.x也可以类似实现(使用tf.train.Server)
    • 同时TensorFlow 1.x的 Estimator API提供了自己的一些自己的训练形式(tf.estimator)

启动脚本

  • 注:以下脚本均以localhost为例,实际使用时需要替换为对应不同服务器的IP

  • 启动chief节点:

    1
    2
    3
    4
    5
    6
    7
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2225" \
    --task_type="chief" \
    --task_index=0
  • 启动worker节点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # Worker 0
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2225" \
    --task_type="worker" \
    --task_index=0

    # Worker 1
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2225" \
    --task_type="worker" \
    --task_index=1
  • 启动evaluator节点:

    1
    2
    3
    4
    5
    6
    7
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2225" \
    --task_type="evaluator" \
    --task_index=0
  • 启动 PS 节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 启动参数服务器0
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2227" \
    --task_type="ps" \
    --task_index=0

    # 启动参数服务器1
    python distributed_training.py \
    --chief="localhost:2222" \
    --workers="localhost:2223" "localhost:2224" \
    --ps_servers="localhost:2225" "localhost:2226" \
    --evaluator="localhost:2227" \
    --task_type="ps" \
    --task_index=1

ML——对数似然及其变分下界


似然函数是什么?

  • 似然函数(Likelihood Function) :描述在给定模型参数下,观测数据出现的概率。对于一组独立同分布的观测数据 \(x_1, x_2, \cdots, x_n\) ,其似然函数 \(L(\theta)\) 可以表示为每个观测数据的概率密度函数的乘积 ,即:
    $$L(\theta)=\prod_{i = 1}^{n}p(x_i|\theta)$$
    • 其中 \(\theta\) 是模型的参数, \(p(x_i|\theta)\) 是在参数 \(\theta\) 下观测数据 \(x_i\) 出现的概率
  • 理解:似然的本质可以理解为概率(更准确说是描述概率值的函数),但一般来说,似然函数是关于参数 \(\theta\) 的函数(不同于普通的概率)

对数似然是什么?

  • 对数似然(Log Likelihood) :就是对似然函数取自然对数,得到:
    $$ll(\theta)=\ln L(\theta)=\sum_{i = 1}^{n}\ln p(x_i|\theta)$$
    • 取对数的主要原因是将乘积转化为求和,方便计算和分析,尤其是在处理大量数据时,乘积的计算可能会导致数值下溢,而对数运算可以避免这种情况

对数似然可以用来做什么?

  • 模型参数估计 :在最大似然估计中,通过最大化对数似然函数来估计模型的参数;因为对数函数是单调递增的,所以最大化似然函数等价于最大化对数似然函数

变分是什么?

  • 近似推断方法的目标是在难以直接计算概率分布的情况下,对目标分布进行近似求解
  • 常见近似推断方法有蒙特卡罗采样法(Monte Carlo Sampling)和变分推断法(Variational Inference, VI)两种
    • 蒙特卡罗采样法 :基于大数定律,通过从已知分布中进行大量随机采样,利用这些样本的统计特性来近似目标分布的期望、方差等统计量
      • 举例:要计算一个复杂函数在某个概率分布下的期望,可以通过从该分布中采样大量的点,计算函数在这些点上的值,然后求平均值来近似期望;
      • 方法:主要通过各种采样算法,如拒绝采样、重要性采样、马尔可夫链蒙特卡罗(MCMC)等方法来生成样本。以 MCMC 为例,它通过构建一个马尔可夫链,使其平稳分布为目标分布,然后从这个马尔可夫链中采样得到样本
    • 变分推断法 :一种基于优化的方法,通过定义一个分布族(比如高斯分布族),然后在这个分布族中寻找一个与目标分布最接近的分布(通常通过最小化两者之间的 KL 散度来实现)
      • 举例:对于一个难以直接处理的后验分布,我们可以假设一个具有特定形式(如高斯分布)的变分分布,然后通过调整变分分布的参数,使其尽可能接近真实的后验分布;
      • 方法:通过优化算法,如梯度下降、随机梯度下降等,来调整变分分布的参数,以最小化 KL 散度
  • 变分(Variational)这个词常常指隐含近似推断的思想,常常是通过优化函数(或分布)来近似复杂概率分布,解决复杂概率分布问题

对数似然的变分下界

  • 任意函数 \(F\) 的变分下界(Variational Lower Bound) :是一个用于估计函数 \(F\) 下界的函数 ,最大化变分下界可以间接实现最大化原始目标函数 \(F\)
  • 对数似然的变分下界(Variational Lower Bound) :是一个用于估计对数似然函数下界的函数 ,最大化变分下界可以间接实现最大化原始目标对数似然函数
  • 假设我们有一个概率模型,其中观测数据为 \(x\) ,隐变量为 \(z\) ,模型的参数为 \(\theta\) 。对数似然函数 \(\log p(x|\theta)\) 可以通过对联合概率 \(p(x,z|\theta)\) 进行积分得到,即:
    $$\log p(x|\theta)=\log\int_z p(x,z|\theta)dz$$
  • 变分推断的基本思想是引入一个变分分布 \(q(z)\) ,然后通过优化这个变分分布来逼近真实的后验分布 \(p(z|x,\theta)\) 。对数似然的变分下界 \(L(q)\) 定义为:
    $$L(q)=\mathbb{E}_{q(z)}[\log p(x,z|\theta)]-\mathbb{E}_{q(z)}[\log q(z)]$$
    • 其中 \(\mathbb{E}_{q(z)}\) 表示关于分布 \(q(z)\) 的期望

变分下界的推导

  • 根据 Jensen’s 不等式,对于凹函数 \(f\) 和随机变量 \(Y\) ,有 \(f(\mathbb{E}[Y])\geq\mathbb{E}[f(Y)]\)
  • 对于对数似然函数,我们有:
    $$
    \color{red}{\log p(x|\theta)}=\log\int_z p(x,z|\theta)dz=\log\mathbb{E}_{q(z)}\left[\frac{p(x,z|\theta)}{q(z)}\right]\color{red}{\geq}\mathbb{E}_{q(z)}\left[\log\frac{p(x,z|\theta)}{q(z)}\right]=\color{red}{L(q)}$$
    • 所以 \(L(q)\) 是对数似然 \(\log p(x|\theta)\) 的一个下界

变分下界的作用与应用

  • 近似推断 :通过最大化变分下界 \(L(q)\) ,可以找到一个最优的变分分布 \(q^*(z)\) ,使得它尽可能接近真实的后验分布 \(p(z|x,\theta)\)
    • 这样就可以用 \(q^*(z)\) 来近似计算后验分布的各种统计量,如均值、方差等,从而实现对隐变量的推断
  • 模型训练 :在一些基于概率模型的机器学习算法中,如变分自编码器(VAE),对数似然的变分下界被用作优化目标
    • 通过最大化变分下界 ,可以最大化对数似然函数 ,可以学习到模型的参数 \(\theta\)
  • 评估模型性能 :变分下界的值可以作为模型性能的一个评估指标
    • 当变分下界的值越大,说明模型对数据的拟合程度越好,同时也意味着变分分布 \(q(z)\) 对真实后验分布 \(p(z|x,\theta)\) 的近似效果越好

ML——归一化与标准化

本文总结归一化与标准化的理解和使用, 涉及到无量纲,中心化等知识, 但是并不完全


归一化

Normalization

  • 把数据变成[0,1]或[-1,1]的小数

  • 把有量纲表达式变成无量纲表达式,便于不同单位或量级的指标能够进行比较和加权

  • 归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为纯量

    • 无量纲的理解:
      • 通过某种数值变换去掉单位,的影响,比如”kg”和”g”都可以表示体重,但是前者的数字比后者小
      • 不管是”kg”还是”g”作为单位,无量纲后他们的数值应该是一样的
      • 无量纲的本质是说: 变换后, 单位不再影响数据的数值
  • 应用:

    • LR等用梯度下降时, 先使用数据归一化可以使得梯度下降速度加快(否则可能下降方向并不是最好方向)

归一化的不同方法

线性归一化
  • Min-Max Normalization
    $$ x_i’ = \frac{x_i-min(X)}{max(X)-min(X)}$$
  • 平均归一化
    $$ x_i’ = \frac{x_i-mean(X)}{max(X)-min(X)}$$
  • 上面两种归一化在新数据加入时最大最小值会变化,所以不能在线归一化
非线性归一化
  • 对数函数转换等

标准化

Standardization

  • 使每个特征中的数值平均变为0(将每个特征的值都减掉原始资料中该特征的平均)、标准差变为1
  • 数学描述
    $$x_i’ = \frac{x-mean(X)}{std(X)}$$

中心化

  • 平均值为0,对标准差无要求
  • 数学描述
    $$x_i’ = x-mean(X)$$

归一化 vs 标准化

不同点

  • 归一化是将样本的特征值转换到同一量纲下把数据映射到[0,1]或者[-1, 1]区间内,仅由变量的极值决定,因区间放缩法是归一化的一种
  • 标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,转换为标准正态分布,和整体样本分布相关,每个样本点都能对标准化产生影响

相同点

  • 都能取消由于量纲不同引起的误差
  • 都是一种线性变换(都是对向量X按照比例压缩再进行平移)
  • 个人理解: 标准化可以看作是一种特殊的归一化

中心化 vs 标准化

  • 标准化 = 中心化 + 数据除以标准差(使得数据标准差为1)
  • 有些地方也把零均值归一化(Z-Score Normalization)称为标准化,公式与标准化相同

总结

  • 一些模型一般需要归一化
    • LR: 加快梯度下降过程(因为不同维度使用相同的学习率,所以容易造成走弯路)
    • KNN: 防止计算距离时大数吃小数的情况发生
    • PCA: 归一化后 \(X^TX\) 才能表示数据的协方差矩阵
    • 神经网络

关于神经网络为什么需要归一化?

数值问题
  • 归一化可以避免很多不必要的数值问题
    • 我理解的一种情况: 输入太大时, 权重太小, 容易造成精度问题, 数值太小时同理
  • 归一化可以避免梯度爆炸等问题
    • 个人理解: 如果数值很大的话, 梯度一般也会对应很大, 连续乘以后就容易造成梯度爆炸, 数值太小, 同理, 容易造成梯度消失
  • 加快学习
    • 与LR一样, 使用梯度下降优化神经网络参数时, 如果数值差别太大, 可能造成优化时梯度优化走弯路(因为不同维度使用的是相同的学习率)
  • 避免某些数值小的神经元输出被数值大的输出吞掉的情况
    • 个人理解: 虽然说我们找到合适权重后,可以使得二者到下一个神经元的差值没那么大, 但是我的理解是初始化的时候不知道数值,所以权重是随机的,之后如果两个神经元数值差距太大的话,是否会大值吞小值很难说

关于LR为什么需要归一化?

不是必要的

  • 因为LR使用梯度下降法求解参数时, 特征之间差别太大容易影响收敛速度, 归一化可以提升LR的收敛速度, 同时不影响分类结果

关于SVM为什么需要归一化?

是必要的

  • 因为SVM寻找的是所谓的间隔(margin), 就是两个支持向量的间隔
  • 如果不归一化的话, 这个间隔会因为不同特征的单位等, 数值被放大或者缩小, 从而造成无法评估间隔 , 所以归一化对于SVM很重要

ML——归纳偏置概念理解


整体说明

  • 在机器学习和深度学习中,归纳偏置(Inductive Bias)是指学习算法在面对未知数据时所倾向的特定类型的假设或规律
  • 当模型去预测其未遇到过的输入的结果时,会做一些假设,而学习算法中的归纳偏置就是这些假设的集合
  • 归纳偏置是机器学习算法在学习过程中对某种类型假设的偏好

归纳偏置的作用

  • TLDR:没有归纳偏置的模型在面对新数据时无法有效泛化。归纳偏置通过引入合理的先验知识,缩小假设空间,提高学习效率
    • 例如“无免费午餐定理”指出,没有任何算法在所有问题上表现最优
  • 数据效率 :在少量数据下,合理的偏置能快速收敛到可行解
  • 泛化能力 :避免过拟合,例如奥卡姆剃刀原则(偏好简单假设)
  • 领域适配 :针对问题设计合适的偏置(如CNN对图像、RNN对序列)

有哪些常见归纳偏置?

  • 模型架构 :如卷积神经网络(CNN)的“局部性假设”(相邻像素关联性强),位移不变性
  • 正则化 :L1正则化偏好稀疏解,L2偏好小权重
  • 优化目标 :支持向量机(SVM)追求最大化分类间隔
  • 特征选择 :决策树优先选择信息增益高的特征
  • 一些算法自带归纳偏置 :
    • 线性回归 :假设数据关系是线性的
    • K近邻(KNN) :假设相似输入有相似输出
    • 贝叶斯模型 :依赖先验概率分布假设

归纳偏置带来的问题

  • 若偏置与真实数据分布不符(如用线性模型拟合非线性关系),会导致欠拟合。此时需调整模型假设

Sklearn——总体介绍

Sklearn 总体介绍


总结介绍图

Mac——环境变量配置.md


Mac环境变量配置文件

  • /etc/profile
    • 全局的
  • ~/.bash_profile
    • 用户自己的,可能需要自己生成
  • 生效方式
    1
    source ~/.bash_profile

Terminal自动导入环境变量

  • 默认Terminal打开后不会导入用户自定义的环境变量

  • 自动导入可以设置为

    • 在~/.zshrc(这个文件没有的话需要自己生成)中添加一行

      1
      source ~/.bash_profile
    • 也可直接在~/.zshrc中直接定义环境变量,使用~/.bash_profile是为了和Linux匹配且方便切换不同的Bash工具

    • 原理:Terminal打开的是zsh工具,这个工具启动时会自动执行~/.zshrc


Idea

  • Idea中Terminal打开后可能不会跟系统一样自动导入环境变量
    • 如果使用的Terminal是zsh的话,也会自动导入
  • 可以自己手动添加(一次添加,以后都可以自动使用)
  • 或者每次打开Terminal后执行source ~/.bash_profile

ML——MLE和MAP的区别举例说明

本文用一个简单的例子在直观上说明极大似然估计与最大后验估计的区别


举例说明

  • 事件定义

    • A = 好好学习
    • B = 作弊
    • C = 班级第一
  • 条件概率

    • P(C|A) = 0.1
    • P(C|B) = 0.5
  • 已知某同学考了年级第一

    • 此时可得概率:
      • P(C) = 1
    • ML(极大似然估计,找一个使得结果发生可能性最大的条件
      计算条件概率P(结果|条件)
      • 参数为e
      • P(C|e = A) = 0.1
      • P(C|e = B) = 0.5
      • 该同学更可能是作弊了
    • 若此时添加先验:
      • P(A) = 0.99
      • P(B) = 0.01
    • MAP(计算后验概率,在结果发生时,最可能是什么产生的?
      计算后验概率:P(条件|结果) ,令P(C)=1
      • P(A|C) = P(C|A)P(A)/P(C) = 0.1*0.99/1 = 0.099
      • P(B|C) = P(C|B)P(B)/P(C) = 0.5*0.01/1 = 0.005
      • 此时可发现该同学更可能是好好学习了

深入分析:MLE与MAP的区别

  • MAP比MLE多考虑了一个先验概率,这个先验概率指明了条件概率的条件(例如 P(C|A)的先验是P(A))
  • MAP的是比较后验概率,ML的是比较条件概率,但是两者本质上都是找一个使得结果发生的最可能的原因
  • MLE可以认为是特殊的MAP
    • ML是先验概率为均匀分布时的MAP(上例中: 若P(A) = P(B), 则MLE等价于MAP)

ML——参数估计MLE-MAP-BEP

极大似然估计(Maximum Likelihood Estimation,MLE)
最大后验概率估计(Maximum a posteriori Estimation,MAP)
贝叶斯估计(Bayesian Parameter Estimation,BPE)


一般理解

  • 极大似然估计(MLE): 频率学派(参数为固定的某个值)
  • 贝叶斯估计(BPE): 贝叶斯学派(参数服从某个分布)
  • 最大后验概率估计(MAP): 一般的书籍认为属于频率学派
    • 个人理解:MAP前半部分是贝叶斯学派,后半部分是频率学派
      • 前半部分认为参数 \(\theta\))有先验分布,此时参数服从一个分布,而不是确定的值,是贝叶斯学派的
      • 后半部分认为参数不是服从后验分布,而是一个具体的使得后验概率最大的值,这里是频率学派的做法
  • 三者的终极目标都是估计模型参数 \(\theta\),MAP和MLE估计参数 \(\theta\) 为具体某个值,BPE估计参数 \(\theta\) 为一个分布
  • 其他贝叶斯网络模型(有向图概率图模型)参数估计的方法还有吉布斯采样,变分推断,EM算法等

极大似然估计与最大后验概率估计

  • 比较MLE与MAP直观理解见我的另一篇博客:MLE-vs-MAP——一个简单的例子说明二者的区别
  • 都只关注参数的具体某个最优值
  • 极大似然估计相当于是参数 \(\theta\) 的先验分布 \(P(\theta)\) 为均匀分布的最大后验概率估计

最大后验概率估计与贝叶斯估计

  • 相似点:
    • 都考虑了参数的先验分布(贝叶斯学派)
    • 最大后验概率估计是贝叶斯估计的一种简化实现(认为 \(\theta\) 都是出现在最可能出现的地方,牺牲一点精度,不用求复杂的分母积分)
    • 二者都围绕下面的公式进行估计
      $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
  • 区别:
    • 贝叶斯估计 :求得的结果估计参数 \(\theta\) 服从一个分布,不能忽略归一化因子 \(P(X)\),此时 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\),贝叶斯估计要计算后验分布,所以需要计算归一化因子,虽然对不同参数值,分母积分结果是相同的,但是计算分布时需要这个归一化因子,否则后续得到的不是分布,也无法求取参数的期望等
    • 最大后验概率估计 :求得的结果估计参数 \(\theta\) 是一个具体的值,把分母 \(P(X)\) 给忽略了,直接对分子极大化求得最优的参数 \(\theta^{\star}\),由于跟贝叶斯估计一样,对不同参数值,分母积分结果是相同的,所以 \(P(X)\) 的值不影响最优参数值的选取【不求参数 \(\theta\) 的分布,所以不用求分母,分母是不影响求参数最优值的】,不用计算归一化因子(很复杂,需要积分),速度会快很多
  • 最大后验概率估计相当于是参数后验分布 \(P(\theta|X)\) 被最可能的参数值 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\) 替代的贝叶斯估计
估计模型 目标值 关心对象 求值方式
MLE $$\theta^{\star}=\mathop{\arg\max}_{\theta}(P(X\mid \theta)$$ \(P(X\mid \theta)\) 最大化似然函数 \(P(X\mid \theta)\)
MAP $$\theta^{\star}=\mathop{\arg\max}_{\theta}(P(\theta\mid X)$$ \(P(X\mid \theta)P(\theta)\) 最大化后验概率 \(P(\theta\mid X)=\frac{P(X\mid \theta)P(\theta)}{P(X)}\)
只需最大化分子 \(P(X,\theta)=P(X\mid \theta)P(\theta)\)
BPE \(P(\theta\mid X)\)
(\(\theta\) 的后验概率分布)
\(\frac{P(X\mid \theta)P(\theta)}{P(X)}\) 求参数 \(\theta\) 的后验概率分布 \(P(\theta\mid X)\)
\(P(\theta\mid X)=\frac{P(X\mid \theta)P(\theta)}{\int_{\theta}P(X\mid\theta)P(\theta)d_{\theta}}\)

一个容易理解的角度

  • 参考博客: https://blog.csdn.net/liu1194397014/article/details/52766760

问题描述

  • 已知数据集为 \(X=(x_{1}, x_{2},,,x_{n})\)

  • 极大似然估计

    • 已知数据集 \(X\) 的情况下,求参数最优值 \(\theta^{\star}\),使得似然函数 \(P(X|\theta)\) 最大
  • 最大后验概率估计

    • 已知数据集 \(X\) 的情况下,求参数最优值 \(\theta^{\star}\),使得后验概率 \(P(\theta|X)\) 最大,实际只需使得 \(P(X,\theta)=P(X|\theta)P(\theta)\) 最大
  • 贝叶斯估计

    • 已知数据集 \(X\) 的情况下,求参数 \(\theta\) 的后验分布 \(P(\theta|X)\)

极大似然估计(MLE)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 的取值与参数 \(\theta\) 无关【认为每个参数 \(\theta\) 出现的概率相等】
      • \(P(\theta)\) 与参数 \(\theta\) 无关可以理解为参数 \(\theta\) 服从均匀分布 : 假设参数 \(\theta\) 有k个离散取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(P(\theta_{1})=P(\theta_{2})=…=P(\theta_{k})=\frac{1}{k}\)
    • \(P(X)\) 的取值与 \(\theta\) 无关,设置为 \(P(X)=1\) 即可
    • 所以得到下面的表达式
      $$\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)$$
      • 式子中 \(P(X|\theta)\) 被称为似然函数
  • 结论
    • 极大似然估计: \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)\)
    • 文字解释: 极大似然估计的目标是找一个参数 \(\theta\),使得在参数 \(\theta\) 对应的概率分布模型下,数据集 \(X\) 出现的概率最大(似然函数最大)

最大后验概率估计(MAP)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 为的取值与参数 \(\theta\) 相关,是关于 \(\theta\) 的一个先验概率【不同的参数 \(\theta\) 出现的概率可能不同】
      • \(P(\theta)\) 与参数 \(\theta\) 相关可以理解为: 假设参数 \(\theta\) 有k个取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(\sum_{i=1}^{k}P(\theta_{i})=1\),但 \(P(\theta_{1}),P(\theta_{2}),,,P(\theta_{k})\) 的取值不能确定,也不一定相等
    • \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 积分结果与 \(\theta\) 不相关,分母的值不影响后验概率最大值的参数值,直接忽略(设置为 \(P(X)=1\))即可
    • 所以得到
      $$\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)=\mathop{\arg\max}_{\theta}P(X,\theta)$$
  • 结论
    • 最大后验概率估计: \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)\)
    • 文字解释: 最大后验概率估计的目标是找一个参数 \(\theta\),使得在参数 \(\theta\) 服从已知先验分布 \(P(\theta)\) 和数据集 \(X\) 的情况下,对应的后验概率 \(P(\theta|X)\) 最大(等价于 \(P(X,\theta)=P(X|\theta)P(\theta)\) 最大)

贝叶斯估计(BPE)

  • 推导
    $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{P(X)}$$
    • \(P(\theta)\) 为的取值与参数 \(\theta\) 相关,是关于 \(\theta\) 的一个先验概率
      • \(P(\theta)\) 与参数 \(\theta\) 相关可以理解为: 假设参数 \(\theta\) 有k个取值 \(\theta_{1}, \theta_{2},,,\theta_{k}\),那么 \(\sum_{i=1}^{k}P(\theta_{i})=1\),但 \(P(\theta_{1}),P(\theta_{2}),,,P(\theta_{k})\) 的取值不确定,也不一定相等
    • \(P(X)\) 的取值与 \(\theta\) 本身不相关,但是为了求出后验分布 \(P(\theta|X)\), \(P(X)\) 作为归一化因子需要计算
      • \(P(X)\) 的值与参数的先验分布,模型的定义(高斯分布还是贝塔分布等)和数据集 \(X\) 有关系
      • 没有分母作为归一化因子的话单独的分子是联合分布 \(P(X,\theta)\),这个分布对 \(\theta\) 积分结果不为1(而是 \(P(X)\)),联合分布不能确定 \(\theta\) 的后验分布
      • \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\)
    • 所以得到
      $$P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}$$
  • 结论
    • 贝叶斯估计: \(P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}\)
    • 文字解释: 贝叶斯估计的目标是求参数的后验分布 \(P(\theta|X)\),参数 \(\theta\) 服从先验分布 \(P(\theta)\),在已知数据集 \(X\) 修正后,参数 \(\theta\) 的后验概率分布为 \(P(\theta|X)\)
  • 缺点
    • 计算 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 比较耗时

一个更深入的理解

问题描述

  • 已知数据集为 \(X=(x_{1}, x_{2},,,x_{n})\),新数据集为 \(D=(d_{1}, d_{2},,,d_{m})\)
  • 求已知数据集 \(X\) 的情况下,假设数据集 \(X\) 由某个模型M(参数为 \(\theta\))生成,那么数据集 \(D\) 也由模型M生成的概率 \(P(D|X)\)
    • 模型M的确定因素:
      • 由三个因素唯一确定
        • 参数 \(\theta\) 的先验分布 \(P(\theta)\)
        • 模型的类型定义 \(f(\theta)\) (高斯分布,贝塔分布,二项分布还是其他什么分布)
        • 模型的已知观察数据集 \(X\)
      • 由两个因素唯一确定
        • 模型的类型定义 \(f(\theta)\) (高斯分布,贝塔分布,二项分布还是其他什么分布)
        • 参数 \(\theta\) 的后验分布 \(P(\theta|X)\)
  • 另一种表述: 用模型M(参数为 \(\theta\))生成数据,在已观察到模型M生成了数据集 \(X\) 后,预测模型M接下来生成数据集 \(D\) 的概率

极大似然估计(MLE)

  • 特点:假设模型M(参数 \(\theta\))没有先验分布

  • 模型参数估计

    • 模型参数为一个确定的最优值
    • \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(X|\theta)\)
  • 概率计算

    • \(P(D|X)=P(D|\theta^{\star})\)
  • 优点

    • 计算速度快
  • 缺点

    • 不够精确,特别是当观察到的数据集 \(X\) 太小时,这种情况不考虑参数的先验分布可能会造成过拟合
      • 举例: 判断一个学校男女比例,在观察到两个男生,一个女生走出校门后就判断男女比例为2:1显然不合适
        • 注意:单个同学是男生或者女生的概率服从伯努利分布,多个同学中男生的数量服从二项分布,整个学校的某个学生是男生的概率服从贝塔分布

贝叶斯估计(BPE)

  • 特点:假设模型M(参数 \(\theta\))有先验分布 \(P(\theta)\),计算观察到数据集 \(X\) 后 \(\theta\) 的后验分布 \(P(\theta|X)\),然后求 \(P(D|\theta)\) 关于后验分布 \(P(\theta|X)\) 的期望(这个期望也就是模型M生成数据集 \(D\) 的概率)
    • 这里可以理解为观察到的数据集是对先验分布的修正,修正后的后验分布会更符合模型实际情况(因为先验分布很可能是瞎猜的)
  • 模型参数估计
    • 模型参数为一个分布
    • \(P(\theta|X)=\frac{P(X|\theta)P(\theta)}{\int_{\theta}P(X|\theta)P(\theta)d_{\theta}}\)
    • 分子为归一化因子 \(P(X)\)
      • 必须计算,该值与参数的先验分布 \(P(\theta)\),模型的类型定义(\(f(\theta)\))以及数据集 \(X\) 有关系,不计算 \(P(X)\) 的话后面计算得到的 \(P(D|X)\) 也将是一个不确定的值(不是概率值,是 \(P(X)\) 的函数)
  • 概率计算
    • \(P(D|X)=\int_{\theta}P(D,\theta|X)d_{\theta}=\int_{\theta}P(D|\theta,X)P(\theta|X)d_{\theta}=\int_{\theta}P(D|\theta)P(\theta|X)d_{\theta}\)
      • 式子中 \(P(D|\theta,X)=P(D|\theta)\),在通过 \(X\) 确定 \(\theta\) 后模型也就确定了, \(X\) 不会继续影响 \(D\) 的生成
    • 这里 \(P(D|X)\) 相当于 \(P(D|\theta)\) 关于后验分布 \(P(\theta|X)\) 的期望
  • 优点
    • 计算结果最精确,能根据参数的先验分布和数据集 \(X\) 的知识,准确计算模型生成数据集 \(D\) 的概率
  • 缺点
    • 计算 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\) 比较耗时,不常用
关于 \(P(X)\) 是否需要计算?
  • 无需计算的情况
    • 判断两个数据集 \(D_{1},D_{2}\) 由同一个模型M生成的概率谁大,可以不用计算 \(P(X)\)
      • 因为对于同一模型M, \(P(X)\) 相同大小,此时只需要比较 \(P(D_{1},X)\) 和 \(P(D_{2},X)\) 谁大即可知道 \(P(D_{1}|X)\) 和 \(P(D_{2}|X)\) 谁大
  • 必须计算的情况
    • 判断数据集 \(D\) 由两个模型 \(M_{1},M_{2}\) 生成的概率谁大,必须计算 \(P(X)\)
      • 因为对于不同模型 \(M_{1},M_{2}\), \(P(X)\) 不相同【每个模型生成 \(X\) 的概率不同】,此时仅仅比较 \(P(D_{1},X)\) 和 \(P(D_{2},X)\) 谁大不能确定 \(P(D_{1}|X)\) 和 \(P(D_{2}|X)\) 谁大
    • 利用模型M采样生成新数据(预测问题),必须计算 \(P(X)\)
      • 这时候每次采样时需要根据参数 \(\theta\) 的后验分布采样生成 \(\theta_{i}\),然后再根据 \(\theta_{i}\) 确定的模型 \(M_{i}\) 采样生成观测数据,两次采样的过程都必须知道准确的分布(积分为1,也就是归一化后的),所以此时必须计算 \(P(X)\)

最大后验概率估计(MAP)

  • 特点:假设模型M(参数 \(\theta\))有先验分布 \(P(\theta)\),但不计算模型的后验分布 \(P(\theta|X)\),只用最可能的 \(\theta\) 代替后验分布来确定模型M

  • 模型参数估计

    • 模型参数为一个确定的最优值
    • \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)=\mathop{\arg\max}_{\theta}P(X|\theta)P(\theta)\)
      • 这里与贝叶斯估计作对比可以发现,MAP相当于把参数后验分布简化为最可能的那个参数值,用最可能的参数值代替参数后验分布 ,这样做对最终预测结果 \(P(D|X)\) 可能有点误差,但是不用计算复杂的积分 \(P(X)=\int_{\theta}P(X|\theta)P(\theta)d_{\theta}\)
      • 这里能够用最优值替代分布的前提是分布是很集中的(也就是要 \(P(\theta|X)\) 方差小,比如贝塔分布,狄利克雷分布和高斯分布等钟型分布的塔尖要尖),不然误差可能会比较大
      • 注意后验分布 \(P(\theta|X)\) 最可能值的参数值是概率最大的地方 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\),而不是参数 \(\theta\) 关于后验分布的期望 \(\mathbb{E}_{P(\theta|X)}[\theta]=\int_{\theta}\theta P(\theta|X)d_{\theta}\) (期望对应平均值,而不是最可能的值 ,特例:对称钟型分布的期望同时也是它最可能的值)
  • 概率计算

    • \(P(D|X)=P(D|\theta^{\star})\)
  • 计算速度和精确度都介于MLE和BPE之间


总结

  • 贝叶斯估计可以退化成最大后验概率估计
    • 最大后验概率估计相当于是参数后验分布 \(P(\theta|X)\) 被最可能的参数值 \(\theta^{\star}=\mathop{\arg\max}_{\theta}P(\theta|X)\) 替代的贝叶斯估计
  • 最大后验概率估计可以退化成极大似然估计
    • 极大似然估计相当于是参数 \(\theta\) 的先验分布 \(P(\theta)\) 为均为分布的最大后验概率估计

LaTex——排版

vspace

  • 增加或减少行间距
  • 例如,减少图片和正文的间距0.1cm采用下面的表达,单位可以是cm,pt,mm等
    1
    2
    3
    4
    5
    6
    7
    8
    \begin{figure}[h]
    \centering
    \vspace{-0.1cm}
    \includegraphics[width=\linewidth]{Q-Network-Page-2}
    \caption{Q-Network of RL-MPCA}
    \Description{}
    \label{fig:Q-Network}
    \end{figure}

列表缩进

  • 参考链接:
    • https://tex.stackexchange.com/questions/170525/itemize-left-margin
    • https://www.cxyzjd.com/article/robert_chen1988/83179571
  • 缩进设置
    1
    2
    % \usepackage{enumitem}
    % \setlist{leftmargin=5.5mm}

footnote编号

  • \footnote{}默认会自动编号,整片文章按照顺序排列编号
  • \footnote[3]{}则允许手动设置编号,可以按照自己的意愿随意设置编号

超链接

  • 参考链接:
  • 文档内部超链接
    1
    2
    3
    \usepackage{hyperref}
    \hyperlink{thesentence}{[1]}
    \hypertarget{thesentence}{[1]}.

Mac——HomeBrew简介


HomeBrew是什么?

  • HomeBrew是一个Mac OS上的软件包管理器,命令是brew,类似于Ubuntu上的DPKG(apt-get)或者Centos上的RPM(yum)等

HomeBrew的安装

  • 安装命令

    1
    /usr/bin/ruby -e"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 查看安装结果

    1
    brew -v

HomeBrew管理软件包

  • HomeBrew的安装的软件包默认在/usr/local/Cellar下
  • HomeBrew用@指明版本号

搜索云端软件

返回结果中可以看到版本号,后续安装可指定版本号安装

1
brew search key_str

安装

1
brew install pkg_name

卸载

1
brew remove pkg_name

更新

1
brew upgrade pkg_name

列出所有已安装软件

1
brew list

查看某个云端软件包信息

1
brew info pkg_name

HomeBrew管理服务

启动服务

1
brew services start service_name

停止服务

1
brew services stop service_name

重启服务

1
brew services restart service_name

列出所有HomeBrew管理的服务

1
brew services list
1…575859…61
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

608 posts
49 tags
GitHub E-Mail
© 2026 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4