[{"content":"论文翻译笔记 Deep Unsupervised Learning using Nonequilibrium Thermodynamics 2015\nGenerative Modeling by Estimating Gradients of the Data Distribution 2019\n论文阅读笔记 White-box Membership Inference Attacks against Diffusion Models 2025\nClavaDDPM: Multi-relational Data Synthesis with Cluster-guided Diffusion Models 2024\n","date":"2026-02-06T14:55:22+08:00","image":"https://ruheyun.github.io/p/paper-reading/123_hu_8363674b9232922a.jpg","permalink":"https://ruheyun.github.io/p/paper-reading/","title":"论文阅读汇总"},{"content":"学习类 菜鸟教程\nLeetCode\nKaggle\n洛谷\n牛客\nHuggingFace\nHello 算法：动画图解、一键运行的数据结构与算法教程。\n小林图解：图解计算机网络、操作系统、计算机组成、MySQL、Redis，让天下没有难懂的八股文！\n算法通关手册：一本系统讲解算法与数据结构、涵盖 LeetCode 题解的中文学习手册\n工具类 iLoveIMG TinyPNG Windows 自带照片 ","date":"2026-02-09T10:26:11+08:00","image":"https://ruheyun.github.io/p/website-recommend/website-img_hu_987df53ff918e80e.jpg","permalink":"https://ruheyun.github.io/p/website-recommend/","title":"网站/软件推荐"},{"content":"扩散模型表格生成阅读笔记\n论文基本信息 论文标题：ClavaDDPM: Multi-relational Data Synthesis with Cluster-guided Diffusion Models\n出版期刊：NeurIPS 2024\n论文作者：Wei Pang, Masoumeh Shafieinejad, Lucy Liu, Stephanie Hazlewood, Xi He\n学校机构：University of Waterloo, Vector Institute, Royal Bank of Canada\n研究问题 （1）多表数据生成能力不足，不可扩展、难以建模跨多跳\n（2）现有研究集中在单表生成，而单表生成无法扩展到真实数据库\n（3）在多关系表中，外键约束会导致复杂依赖\n如何在复杂外键约束下，高效建模多表数据并捕获长距离依赖？\n研究内容 （1）提出 ClavaDDPM 模型：基于扩散模型的表格生成模型，并用聚类标签建模两个表之间的关系\n（2）用 latent 变量替代外键条件：降维、提升条件建模稳定性、捕捉跨表依赖\n（3）三阶段生成流程：一，通过 GMM 聚类标签得到 latent 标签 c；二，父表基于标签 c 增强的数据训练扩散模型，子表用正常的数据训练扩散模型，并训练一个分类器；三，生成阶段自顶向下生成表格\n（4）用最近邻匹配解决多父表冲突问题\n研究假设 H1：父表行 i.i.d\nH2：子表条件独立\nH3：latent 变量使得条件独立\nH4：聚类可表达跨表关系\nH5：多父表中，用最近邻匹配可近似联合分布\n具体实现细节 研究局限性 （1）在多表中仅考虑外键约束\n（2）强假设：条件独立\n（3）未深入隐私分析\n","date":"2026-03-31T09:29:20+08:00","permalink":"https://ruheyun.github.io/p/clavaddpm/","title":"ClavaDDPM"},{"content":"MathType安装 下载安装包，资源来自网络，这里提供的是7.4版本（内含安装说明）的：百度云\nMathType是一款数学公式编辑器，大多数用于在word和ppt中插入公式（对于写论文和做论文阅读汇报时）。它的主要优势就是所见即所得，通过鼠标点击就可以完成公式的编辑，无需书写Latex代码。\n问题 这个错误是因为 MathType 的 MathPage.WLL 文件丢失或未正确放置到 Office 的启动目录中。以下是解决方法：\n1. 找到 MathType 安装目录\n右键点击 MathType 桌面图标，查看属性找到安装位置 2. 定位 MathPage.WLL 文件 根据以下路径找到文件：\n\\MathType\\MathPage\\64\\MathPage.wll（64位系统） \\MathType\\MathPage\\32\\MathPage.wll（32位系统） 3. 复制文件到 Office 目录 将找到的 MathPage.wll 文件复制到以下目录：\nOffice 2016/2019/365：C:\\Program Files\\Microsoft Office\\root\\Office16 Office 2013: C:\\Program Files\\Microsoft Office\\Office15 Office 2010: C:\\Program Files\\Microsoft Office\\Office14 4. 重启 Word 关闭所有 Word 文档，重新启动 Word 即可。\n如果文件已存在，直接替换即可\n按照以上步骤操作后，错误应该就能解决了！\n","date":"2026-02-25T11:09:36+08:00","permalink":"https://ruheyun.github.io/p/mathtype/","title":"MathType使用笔记"},{"content":"Git和Github 注册GitHub，下载安装git\n使用git bash，设置用户名和邮箱\n1 2 3 4 git config --global user.name \u0026#34;github上注册的用户名\u0026#34; # 配置用户名 git config --global user.email \u0026#34;github上注册的邮箱\u0026#34; # 配置用户邮箱 git config --global user.name # 查看配置的用户名 git config --global user.email # 查看配置的用户邮箱 获取ssh密钥，一直回车即可\n1 ssh-keygen -t rsa -C \u0026#34;GitHub上注册时的邮箱 \u0026#34; 登录github，然后在设置里找到ssh keys，将获取的公钥粘贴进去。\n先在本地一个文件夹初始化为一个仓库 1 git init 将这个文件夹里更改的文件添加到仓库暂存区（在文件夹里的文件称为工作区） 1 2 3 4 5 6 7 8 # 添加某一个修改文件 git add updata.txt # 或者添加所有修改的文件 git add . # 查看哪些文件在暂存区（不是必须操作） git status 将暂存区的文件提交到本地仓库 1 2 3 4 git commit -m \u0026#34;提示信息\u0026#34; # 查看提交历史 git log 上面步骤完成本地操作后，下面准备上传github，在github里创建一个仓库，将用于保存本地上传的文件，github仓库名和本地仓库名不用一样，然后检查是否远程添加了本地了公钥 1 ssh -T git@github.com 如果成功添加了，之后可以连接github远程仓库 1 2 3 4 5 # 假设仓库名为：git@github.com:ruheyun/python_leetcode.git git remote add origin git@github.com:ruheyun/python_leetcode.git # 查看当前仓库的远程仓库配置 git remote -v 连接了远程仓库后,，将远程仓库main分支下所有文件拉取到本地和本地文件合并，防止本地文件上传远端后覆盖了远端已经存在的文件 1 git pull origin main --rebase 上传本地仓库 1 git push -u origin main 当你第一次上传时需要经过上面步骤，以后只有本地仓库和远程仓库不变使用下面命名即可 1 2 3 git add . git commit -m \u0026#34;xxx\u0026#34; git push 13.两台电脑协作时\n1 2 3 4 5 6 7 8 9 # 本地有文件的电脑，按照上面步骤执行 # 另一台电脑，按照下面执行 1.下载git 2.设置相同的用户名和邮箱 3.获取ssh密钥，添加到github 4.使用 git clone https... 5.改成ssh推拉代码 git remote set-url origin git@github.com:... 6.查看远程连接使用的方式 git remote -v 14.注意使用两台电脑协作时\n1 2 3 4 5 6 # 两台电脑都要养成先 pull 再 push 的习惯 git pull origin main git add . git commit -m \u0026#34;\u0026#34; git push origin main q:本地电脑有两个仓库，连接到同一个Github账号中的两个远程仓库，每次都需要输入git remote add origin吗，还是只需要输入一次，以后直接git push就行?\na:各自只需配置一次远程地址，之后就可以直接 git push 了。\nq:当使用另一台电脑提交代码时，GitHub不会计入个人贡献次数（绿色方块）。\na:GitHub 通过提交记录中的邮箱地址来识别贡献者。如果新电脑上配置的 Git 邮箱与 GitHub 账户中绑定的邮箱不一致，贡献将不会显示。\nq:GitHub 私有仓库克隆失败：密码认证已停用，这个错误是因为 GitHub 从 2021 年起已不再支持使用账户密码进行 HTTPS 的 Git 操作，必须使用 Personal Access Token (PAT) 或 SSH 密钥 进行认证。\na:方法1，使用ssh下载代码，但是国内可能下载很慢。方法2，登录 GitHub → 右上角头像 → Settings -\u0026gt; 左侧菜单 → Developer settings → Personal access tokens → Tokens (classic) 点击 Generate new token (classic) 填写信息： Note: Laptop-Q6JPM115（便于识别设备） Expiration: 建议选 30~90 天（更安全） Select scopes: 勾选 repo（完整控制私有仓库） 点击 Generate token，立即复制生成的 token（⚠️ 只显示一次！） 然后使用git clone https://\u0026hellip; 然后将远程连接协议改为ssh，把生成的token删除即可，以后通过ssh拉取和推送。\n15.回退代码\n1 2 3 4 5 6 7 8 # 查看提交历史，按 q 退出，enter 翻滚 git log --pretty=oneline # 找到目标 commit 的 hash，例如 a1b2c3d git reset --hard a1b2c3d # 如果之前已 push，强制同步远程 git push origin main --force ","date":"2026-02-19T17:33:17+08:00","permalink":"https://ruheyun.github.io/p/github-note/","title":"Github 笔记"},{"content":"扩散模型阅读笔记\n论文基本信息 论文标题：White-box Membership Inference Attacks against Diffusion Models\n出版期刊：PoPETs 2025\n论文作者：Yan Pang, Tianhao Wang, Xuhui Kang, Mengdi Huai, Yang Zhang\n学校机构：University of Virginia, Iowa State University, CISPA Helmholtz Center for Information Security\n目标/贡献 设计针对扩散模型的白盒成员推理攻击（MIA），利用梯度信息提升攻击效果；\n提出 GSA 框架及实例，验证梯度作为攻击特征的优越性，多数据集/模型验证有效性\n研究背景 扩散模型现状 优势：图像生成性能超 GANs/VAEs，应用于图形设计等领域\n分类：无条件（DDPM）、条件（Imagen、Stable Diffusion）\n隐患：依赖敏感训练数据，存在隐私泄露风险\n成员推理攻击（MIA）基础 定义：一种隐私攻击方法，旨在判断某个特定数据样本是否曾被用于训练目标模型，从而泄露训练数据的隐私信息。\n现有方法局限：分类模型依赖输出向量，GANs依赖判别器，扩散模型无判别器需新方法\n黑盒/白盒攻击 White-box（白盒）：指攻击者能够完全访问模型的内部参数、结构和训练过程，与“黑盒”（仅能通过输入输出接口交互）相对。\n我们发现白盒攻击在现实世界中非常适用，目前最有效的攻击是白盒。\n现有扩散模型 MIA 不足 主流攻击模型依赖损失值/阈值，信息单一易误判\n白盒攻击为当前最有效类型，但现有方法计算成本高\n攻击方法设计（GSA 框架） 思想 用梯度替代损失作为攻击特征，梯度含更高维模型响应信息\n理论基础 梯度公式：$∇_θL_t(θ,x) = 2(ε_θ(x_t,t)-εt)⊤∇_θε_θ(x_t,t)$\n优势：即使损失相同，梯度可通过 $∇θεθ(xt,t)$ 区分成员/非成员样本\n梯度降维策略 时间步层面：等距采样（平衡效果与效率）、有效采样（需预计算黄金区间）、泊松采样（随机）\n模型层层面：选择性提取各层梯度，聚合有用信息\n层内梯度层面：将梯度视为集合，避免顺序依赖\n具体实例 本文只实现了时间步层面，并将等距采样作为主要的采样方式，提出以下两个实例：\nGSA₁：先求多时间步损失均值，再反向传播求梯度（效率高，Imagen耗时\u0026lt;2小时）\nGSA₂：逐时间步求梯度，再取均值（效果优，耗时约6小时）\n实验 代码 Github。\n","date":"2026-02-13T16:18:06+08:00","permalink":"https://ruheyun.github.io/p/gsa/","title":"GSA"},{"content":"基本使用命令 以下命令（代码）需要再 cmd 里输入。\n查看 conda 版本 1 conda --version 更新 conda 1 conda update conda 查看已创建的虚拟环境 1 conda env list 星号（*）代表当前激活的环境\n创建新环境 1 conda create --prefix path python=version path 是包含新环境名的绝对路径\n1 conda create -n name python=version 如果在默认路径下创建新环境，则常用这个命令\nname 新环境名字\n激活环境（切换环境） 1 conda activate name 回退到默认根环境 1 conda deactivate 删除环境 1 2 3 4 5 # 先退出要删除的环境，再用下面命令，path 指包含环境名字的绝对路径 conda env remove -p path # 或者使用下面命令，name 指环境名字 conda remove -n name --all 对模块进行操作 模块的增删改查是根据当前激活的虚拟环境进行的，即带星号的环境。（这里的模块指的是 Python 中的包）\n搜索模块 1 2 conda search name # 比如：conda search requests 下载模块 1 2 3 4 5 6 7 8 9 10 conda install name # 或者指定版本 conda install name=version # 不过更建议使用 pip 安装 Python 包 pip install name # 或者指定版本 pip install name==version 查看当前环境已下载模块 1 2 3 4 conda list # pip 命令 pip list 升级模块 1 2 3 4 5 6 7 conda update name # 或者升级所有模块 conda update --all # 或使用 pip 升级模块 pip install --upgrade name 删除模块 1 conda remove name 其他操作 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 # 更新基础环境中的conda conda update -n base -c defaults conda # 显示conda环境的安装源 conda config --show-sources # 添加国内镜像源 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/nvidia http://mirrors.aliyun.com/pypi/simple # add（添加到前面） 可以用 append（添加到最后）替换 # 移除某一个安装源 conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge # 移除所有源 conda config --remove-key channels # conda安装较慢，使用mamba加速，安装mamba conda install -n base -c conda-forge mamba # 将mamba加入环境配置 mamba shell init --shell bash --root-prefix=~/.local/share/mamba mamba shell init --root-prefix=/root/miniconda3 --shell=bash source ~/.bashrc # 将以上环境设置好后，重新加载一下配置 source ~/.bashrc # 使用mamba激活环境 mamba activate /root/autodl-tmp/envoriment/RAPID # 将conda安装源从上到下的严格顺序改为灵活选择 conda config --set channel_priority flexible conda config --show | grep channel_priority conda config --set show_channel_urls yes # 所有环境安装好后可以使用pip check检查是否有包冲突 pip check # 如下面两个包冲突，使用下面命令让pip自选择适合的包 pip install \u0026#34;altair\u0026lt;5.4.1\u0026#34; \u0026#34;typing-extensions==4.5.0\u0026#34; #清除所有缓存 sudo conda clean --all jupter 使用 1 2 3 4 5 6 # jupter notebook使用 pip install jupyterlab # 如果想要在浏览器打开jupter notebook使用conda环境需要注册内核（kernel） pip install ipykernel python -m ipykernel install --user --name myenv --display-name \u0026#34;Python (myenv)\u0026#34; ","date":"2026-02-08T22:47:18+08:00","permalink":"https://ruheyun.github.io/p/conda-note/","title":"Conda笔记"},{"content":"扩散模型阅读笔记(2) 论文基本信息 论文名称：Generative Modeling by Estimating Gradients of the Data Distribution\n出版期刊：NeurIPS 2019\n学校机构：Stanford University\n论文翻译 标题 基于数据分布梯度估计的生成模型\n摘要 我们提出了一种新型生成模型，该模型通过朗之万动力学（Langevin dynamics）进行采样，所用梯度通过对数据分布进行分数匹配（score matching）来估计。由于当数据位于低维流形上时，梯度可能难以定义且难以准确估计，我们采用不同强度的高斯噪声对数据进行扰动，并联合估计对应各噪声层级的分数（score），即所有噪声水平下扰动后数据分布的梯度向量场。在采样阶段，我们提出了一种退火朗之万动力学（annealed Langevin dynamics）：随着采样过程逐渐逼近真实数据流形，我们逐步使用对应更低噪声水平的梯度进行迭代更新。代码实现Github。\n引言 生成模型在机器学习中具有广泛的应用。举例而言，它们已被用于生成高保真图像、合成逼真的语音与音乐片段、提升半监督学习的性能、检测对抗样本及其他异常数据、模仿学习，以及在强化学习中探索具有潜力的状态空间。近年来的进展主要由两类方法推动：基于似然的方法（likelihood-based methods）与生成对抗网络（GAN）。前者以对数似然（或合适的代理目标）作为训练目标，而后者则通过对抗训练来最小化模型分布与数据分布之间的 f 散度（f-divergences）或积分概率度量（integral probability metrics）。\n尽管基于似然的模型与生成对抗网络（GAN）已取得显著成功，但它们各自存在一些固有局限。例如，基于似然的模型要么必须采用特定架构以构建归一化的概率模型（如自回归模型、流模型），要么需借助代理损失函数进行训练（如变分自编码器中使用的证据下界 、基于能量模型中的对比散度）。GAN 在一定程度上规避了基于似然模型的部分局限，但其对抗训练过程往往导致训练不稳定。此外，GAN 的目标函数并不适合用于不同 GAN 模型之间的评估与比较。尽管生成建模领域还存在其他目标函数，例如噪声对比估计（noise contrastive estimation）与最小概率流（minimum probability flow），但这些方法通常仅适用于低维数据，在高维场景下表现欠佳。\n本文探索了一种基于估计与采样数据对数密度（logarithmic data density）的（Stein）分数的新型生成建模原理。该分数定义为输入数据点处对数密度函数的梯度，构成一个指向对数数据密度增长最快方向的向量场。我们采用基于分数匹配（score matching）训练的神经网络，从数据中学习这一向量场，并进一步利用朗之万动力学（Langevin dynamics）生成样本：其基本原理是将随机初始样本沿着（估计得到的）分数向量场逐步移向高密度区域。然而，该方法面临两大主要挑战：首先，若数据分布支撑于低维流形上——这在许多真实世界数据集中是常见假设——则在环境空间（ambient space）中分数将无法良好定义，导致分数匹配无法提供一致的分数估计器。其次，在低数据密度区域（例如远离流形的区域）训练数据稀缺，这不仅制约了分数估计的准确性，也延缓了朗之万动力学采样的混合（mixing）过程。由于朗之万动力学通常在数据分布的低密度区域进行初始化，这些区域中不准确的分数估计将对采样过程产生负面影响。此外，为实现在分布不同模态（modes）之间的转移，采样过程往往需要穿越低密度区域，这也使得混合过程变得困难。\n为应对上述两大挑战，我们提出对数据施加不同强度的随机高斯噪声进行扰动。添加随机噪声可确保所得分布不会坍缩至低维流形。较大的噪声强度将在原始（未扰动）数据分布的低密度区域产生样本，从而改善分数估计效果。关键在于，我们训练一个以噪声强度为条件的单一分数网络（score network），并联合估计所有噪声层级下的分数。进而，我们提出一种退火版本的朗之万动力学：采样初始阶段使用对应最高噪声强度的分数，随后逐步降低噪声强度，直至其小到与原始数据分布难以区分为止。我们的采样策略受模拟退火（simulated annealing）启发，后者通过启发式方法有效改善了多模态景观下的优化性能。\n我们的方法具备若干理想特性。首先，该目标函数对几乎所有分数网络的参数化形式均易于处理，无需特殊约束或架构设计，且可在训练过程中避免对抗训练、MCMC 采样或其他近似方法。此外，该目标函数还可用于对同一数据集上的不同模型进行定量比较。我们在 MNIST、CelebA 和 CIFAR-10 数据集上通过实验验证了该方法的有效性。结果表明，所生成的样本质量可与现代基于似然的模型及生成对抗网络（GAN）相媲美。在 CIFAR-10 数据集上，我们的模型在无条件生成模型中取得了 8.87 的全新最优 Inception Score，并获得了具有竞争力的 25.32 FID 分数。通过图像修复（inpainting）实验，我们进一步证明该模型能够学习到数据的有意义表征。\n基于分数的生成模型 假设我们的数据集由来自未知数据分布 $ p_{\\text{data}}(\\mathbf{x}) $ 的独立同分布样本 $\\{ \\mathbf{x}_i \\in \\mathbb{R}^D \\}_{i=1}^N$ 构成。我们定义概率密度 $ p(\\mathbf{x}) $ 的分数（score）为 $ \\nabla_{\\mathbf{x}} \\log p(\\mathbf{x}) $。分数网络 $ s_\\theta : \\mathbb{R}^D \\to \\mathbb{R}^D $ 是一个由参数 $ \\theta $ 参数化的神经网络，该网络将被训练以近似 $ p_{\\text{data}}(\\mathbf{x}) $ 的分数。生成建模的目标是利用数据集学习一个模型，从而从 $ p_{\\text{data}}(\\mathbf{x}) $ 中生成新的样本。基于分数的生成建模框架包含两个核心组成部分：分数匹配 与 朗之万动力学。\n分数估计的分数匹配 分数匹配（score matching）最初设计用于基于独立同分布样本学习非归一化统计模型。我们将其重新用于分数估计。通过分数匹配，我们可直接训练分数网络 $\\mathbf{s}_\\theta(\\mathbf{x})$ 以估计 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$，无需预先训练模型来估计 $p_{\\text{data}}(\\mathbf{x})$。与分数匹配的典型用法不同，我们选择不使用基于能量模型的梯度，以避免因高阶导数带来的额外计算开销。该目标函数最小化 $\\frac{1}{2} \\mathbb{E}_{p_{\\text{data}}(\\mathbf{x})} \\left[ \\|\\mathbf{s}_\\theta(\\mathbf{x}) - \\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})\\|_2^2 \\right]$，在常数项内等价于以下形式：\n$$ \\mathbb{E}_{p_{\\text{data}}(\\mathbf{x})} \\left[ \\text{tr}(\\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x})) + \\frac{1}{2} \\|\\mathbf{s}_\\theta(\\mathbf{x})\\|_2^2 \\right], \\tag{1} $$其中 $\\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x})$ 表示 $\\mathbf{s}_\\theta(\\mathbf{x})$ 的雅可比矩阵。在一定正则性条件下，式 (1) 的极小值点（记为 $\\mathbf{s}_\\theta^*(\\mathbf{x})$）几乎必然满足 $\\mathbf{s}_\\theta^*(\\mathbf{x}) = \\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$。实践中，式 (1) 中关于 $p_{\\text{data}}(\\mathbf{x})$ 的期望可通过数据样本快速估计。然而，由于 $\\text{tr}(\\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x}))$ 的计算限制，分数匹配难以扩展至深度网络和高维数据。下文将讨论两种适用于大规模分数匹配的流行方法。\n去噪分数匹配（Denoising score matching）是分数匹配的一种变体，其核心优势在于完全规避了雅可比矩阵迹（$\\text{tr}(\\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x}))$）的计算。该方法首先通过预设噪声分布 $q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x})$ 对数据点 $\\mathbf{x}$ 施加扰动，随后采用分数匹配技术估计扰动后数据分布 $q_\\sigma(\\tilde{\\mathbf{x}}) \\triangleq \\int q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x}) p_{\\text{data}}(\\mathbf{x}) \\mathrm{d}\\mathbf{x}$ 的分数。其目标函数经证明等价于：\n$$ \\frac{1}{2} \\mathbb{E}_{q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x}) p_{\\text{data}}(\\mathbf{x})} \\left[ \\|\\mathbf{s}_\\theta(\\tilde{\\mathbf{x}}) - \\nabla_{\\tilde{\\mathbf{x}}} \\log q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x})\\|_2^2 \\right]. \\tag{2} $$最小化式 (2) 的最优分数网络（记为 $\\mathbf{s}_\\theta^*(\\mathbf{x})$）几乎必然满足 $\\mathbf{s}_\\theta^*(\\mathbf{x}) = \\nabla_{\\mathbf{x}} \\log q_\\sigma(\\mathbf{x})$。然而需注意：仅当噪声强度足够小（使得 $q_\\sigma(\\mathbf{x}) \\approx p_{\\text{data}}(\\mathbf{x})$）时，才有 $\\mathbf{s}_\\theta^*(\\mathbf{x}) \\approx \\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$ 成立。\n切片分数匹配（Sliced score matching）通过随机投影近似分数匹配中的雅可比矩阵迹 $\\text{tr}(\\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x}))$。其目标函数为：\n$$ \\mathbb{E}_{p_{\\mathbf{v}}} \\mathbb{E}_{p_{\\text{data}}} \\left[ \\mathbf{v}^\\top \\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x}) \\mathbf{v} + \\frac{1}{2} \\|\\mathbf{s}_\\theta(\\mathbf{x})\\|_2^2 \\right], \\tag{3} $$其中 $p_{\\mathbf{v}}$ 为简单随机向量分布（例如多变量标准正态分布）。$\\mathbf{v}^\\top \\nabla_{\\mathbf{x}} \\mathbf{s}_\\theta(\\mathbf{x}) \\mathbf{v}$ 可通过前向模式自动微分（forward mode auto-differentiation）高效计算。与去噪分数匹配不同：\n切片分数匹配直接估计原始未扰动数据分布的分数 但因需前向模式自动微分，其计算量约为去噪分数匹配的四倍 关键术语说明\n英文术语 中文译法 技术依据 Sliced score matching 切片分数匹配 \u0026ldquo;sliced\u0026rdquo; 源自随机投影的\u0026quot;切片\u0026quot;特性（保留数学本质） forward mode auto-differentiation 前向模式自动微分 计算机科学标准译法（对比\u0026quot;反向模式\u0026quot;） unperturbed data distribution 未扰动数据分布 与前文\u0026quot;perturbed data\u0026quot;（扰动后数据）严格对应 multivariate standard normal 多变量标准正态分布 概率论规范表述（避免\u0026quot;多元高斯\u0026quot;口语化） 基于朗之万动力学的采样 朗之万动力学（Langevin dynamics）仅需利用分数函数 $\\nabla_{\\mathbf{x}} \\log p(\\mathbf{x})$ 即可从概率密度 $p(\\mathbf{x})$ 中生成样本。给定固定步长 $\\epsilon \u003e 0$ 和初始值 $\\tilde{\\mathbf{x}}_0 \\sim \\pi(\\mathbf{x})$（其中 $\\pi$ 为先验分布），朗之万方法通过以下递归式迭代计算：\n$$ \\tilde{\\mathbf{x}}_t = \\tilde{\\mathbf{x}}_{t-1} + \\frac{\\epsilon}{2} \\nabla_{\\mathbf{x}} \\log p(\\tilde{\\mathbf{x}}_{t-1}) + \\sqrt{\\epsilon} \\, \\mathbf{z}_t, \\tag{4} $$其中 $\\mathbf{z}_t \\sim \\mathcal{N}(0, I)$。当 $\\epsilon \\to 0$ 且 $T \\to \\infty$ 时，在满足一定正则性条件下，$\\tilde{\\mathbf{x}}_T$ 的分布将收敛至 $p(\\mathbf{x})$，此时 $\\tilde{\\mathbf{x}}_T$ 即为 $p(\\mathbf{x})$ 的精确样本。当 $\\epsilon \u003e 0$ 且 $T \u003c \\infty$ 时，需通过 Metropolis-Hastings 更新校正 式 (4) 的误差，但在实际应用中（当 $\\epsilon$ 足够小且 $T$ 足够大时），该误差通常可忽略。\n需注意：从式 (4) 采样仅需分数函数 $\\nabla_{\\mathbf{x}} \\log p(\\mathbf{x})$。因此，为从 $p_{\\text{data}}(\\mathbf{x})$ 生成样本，我们可先训练分数网络使 $\\mathbf{s}_\\theta(\\mathbf{x}) \\approx \\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$，再通过 $\\mathbf{s}_\\theta(\\mathbf{x})$ 近似实现朗之万动力学采样。这正是基于分数的生成建模框架的核心思想。\n基于分数的生成建模所面临的挑战 本节将对基于分数的生成建模思想进行更深入的分析。我们认为，存在两大主要障碍，使得该方法无法被直接（朴素地）应用。\n流形假设 流形假设指出，现实世界的数据往往集中分布在高维空间（即环境空间）中嵌入的低维流形上。该假设已在诸多数据集中得到经验验证，并成为流形学习的基础理论。在流形假设下，基于分数的生成模型将面临两大关键挑战：\n分数的定义问题：由于分数 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$ 是在环境空间中计算的梯度，当数据点 $\\mathbf{x}$ 被限制在低维流形上时，该梯度无法良好定义。 分数估计的不一致性：分数匹配目标函数（式(1)）仅在数据分布的支撑集为整个空间时提供一致的分数估计器（参见文献 [24] 中的定理 2），而当数据分布支撑于低维流形时，该估计器将变得不一致。 流形假设对分数估计的负面影响可通过图 1 清晰观察：我们在 CIFAR-10 数据集上训练 ResNet（附录 B.1 详述）以估计数据分数，采用切片分数匹配目标函数（式(3)）实现快速训练与精确估计。如图 1（左）所示，当直接在原始 CIFAR-10 图像上训练时，切片分数匹配损失先下降后出现剧烈波动。相比之下，若对数据施加微小高斯噪声（使扰动后数据分布的支撑集覆盖整个 $\\mathbb{R}^D$），损失曲线将稳定收敛（右图）。需注意，我们施加的高斯噪声 $\\mathcal{N}(0, 0.0001)$ 对像素值范围在 $[0,1]$ 的图像而言极其微弱，人眼几乎无法辨识。\n图 1 说明\n左图：无噪声添加时，切片分数匹配（SSM）损失随迭代次数的变化 右图：添加 $\\mathcal{N}(0, 0.0001)$ 高斯噪声后，相同条件下的损失曲线 低数据密度区域 数据在低密度区域的稀缺性，将同时导致分数匹配与基于朗之万动力学的MCMC采样面临困难。\n分数匹配中的分数估计不准确性 在数据密度较低的区域，由于样本数量不足，分数匹配可能无法准确估计分数函数。如第 2.1 节所述，分数匹配的目标是最小化分数估计值的期望平方误差，即 $\\frac{1}{2} \\mathbb{E}_{p_{\\text{data}}} \\left[ \\|\\mathbf{s}_\\theta(\\mathbf{x}) - \\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})\\|_2^2 \\right]$。在实际应用中，该期望通常通过独立同分布样本 $\\{\\mathbf{x}_i\\}_{i=1}^N \\stackrel{\\text{i.i.d.}}{\\sim} p_{\\text{data}}(\\mathbf{x})$ 进行估计。考虑任意区域 $\\mathcal{R} \\subset \\mathbb{R}^D$ 满足 $p_{\\text{data}}(\\mathcal{R}) \\approx 0$，在大多数情况下 $\\{\\mathbf{x}_i\\}_{i=1}^N \\cap \\mathcal{R} = \\varnothing$，因此分数匹配无法获得足够样本以准确估计 $\\mathcal{R}$ 内 $\\mathbf{x}$ 处的 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$。\n为验证此负面影响，我们在图 2 中展示了一个简化实验（附录 B.1 详述）：使用切片分数匹配估计高斯混合分布 $p_{\\text{data}} = \\frac{1}{5} \\mathcal{N}((-5,-5), I) + \\frac{4}{5} \\mathcal{N}((5,5), I)$ 的分数。如图所示，分数估计仅在模态（modes）附近的高密度区域内可靠，而在低密度区域存在显著偏差。\n图 2 说明\n左图：真实分数 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$（橙色色阶编码：颜色越深表示密度越高） 右图：估计分数 $\\mathbf{s}_\\theta(\\mathbf{x})$ 红色矩形框：标注 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x}) \\approx \\mathbf{s}_\\theta(\\mathbf{x})$ 的区域 Langevin 动力学的混合缓慢问题 当数据分布的两个模态被低密度区域分隔时，Langevin 动力学将无法在合理时间内准确恢复这两个模态的相对权重，因此可能无法收敛至真实分布。我们的分析主要受文献 [63] 启发，该文献在分数匹配的密度估计背景下分析了相同现象。\n考虑高斯混合分布 $p_{\\text{data}}(\\mathbf{x}) = \\pi p_1(\\mathbf{x}) + (1-\\pi)p_2(\\mathbf{x})$，其中 $p_1(\\mathbf{x})$ 和 $p_2(\\mathbf{x})$ 是支撑集不相交的归一化分布，且 $\\pi \\in (0,1)$。在 $p_1(\\mathbf{x})$ 的支撑集内，$\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x}) = \\nabla_{\\mathbf{x}} (\\log \\pi + \\log p_1(\\mathbf{x})) = \\nabla_{\\mathbf{x}} \\log p_1(\\mathbf{x})$；在 $p_2(\\mathbf{x})$ 的支撑集内，$\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x}) = \\nabla_{\\mathbf{x}} (\\log(1-\\pi) + \\log p_2(\\mathbf{x})) = \\nabla_{\\mathbf{x}} \\log p_2(\\mathbf{x})$。在两种情况下，分数 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$ 均与 $\\pi$ 无关。由于 Langevin 动力学使用 $\\nabla_{\\mathbf{x}} \\log p_{\\text{data}}(\\mathbf{x})$ 从 $p_{\\text{data}}(\\mathbf{x})$ 采样，所得样本将不依赖于 $\\pi$。在实际应用中，当不同模态具有近似不相交的支撑集（可能共享相同支撑但被小密度区域连接）时，该分析结论依然成立。此时 Langevin 动力学理论上可生成正确样本，但可能需要极小步长和极大步数才能完成混合。\n为验证此分析，我们在 3.2.1 节使用的相同高斯混合分布上测试 Langevin 动力学采样，并将结果展示在图 3 中。采样时使用真实分数作为输入。对比图 3(b) 与 (a) 可以明显看出，Langevin 动力学在两个模态间产生的相对密度存在偏差，这与我们的理论分析一致。\n图 3 说明\n(a) 精确采样结果 (b) 使用真实分数的 Langevin 动力学采样结果 (c) 使用退火 Langevin 动力学（annealed Langevin dynamics）的真实分数采样结果 关键结论：Langevin 动力学对模态间相对权重的估计存在偏差，而退火 Langevin 动力学能准确恢复相对权重 噪声条件分数网络：学习与推理 我们观察到，通过随机高斯噪声扰动数据可使数据分布更适配基于分数的生成建模。首先，由于高斯噪声分布的支撑集覆盖整个空间，扰动后的数据将不再受限于低维流形，从而规避流形假设带来的困难并使分数估计明确定义。其次，较大的高斯噪声能填充原始未扰动数据分布中的低密度区域，使分数匹配获得更充分的训练信号以提升分数估计质量。更重要的是，通过采用多级噪声，我们可获得一系列收敛至真实数据分布的噪声扰动分布序列。我们可借鉴模拟退火与退火重要性采样的思想，利用这些中间分布提升多模态分布下 Langevin 动力学的混合效率。\n基于此洞见，我们提出通过以下两步改进基于分数的生成建模：\n使用多级噪声扰动数据； 通过训练单一噪声条件分数网络，联合估计所有噪声层级对应的分数。 训练完成后，在使用 Langevin 动力学生成样本时，我们初始采用大噪声层级对应的分数，再逐步降低噪声层级。这有助于将大噪声层级的优化优势平滑迁移至低噪声层级（此时扰动数据与原始数据几乎无法区分）。下文将详细阐述本方法的技术细节，包括分数网络架构、训练目标函数及 Langevin 动力学的退火调度策略。\n噪声条件分数网络 设 $\\{\\sigma_i\\}_{i=1}^L$ 为满足 $\\frac{\\sigma_1}{\\sigma_2} = \\dots = \\frac{\\sigma_{L-1}}{\\sigma_L} \u003e 1$ 的正几何序列。定义扰动数据分布 $q_{\\sigma}(\\mathbf{x}) \\triangleq \\int p_{\\text{data}}(\\mathbf{t}) \\mathcal{N}(\\mathbf{x} \\mid \\mathbf{t}, \\sigma^2 I) \\mathrm{d}\\mathbf{t}$。我们选择噪声层级 $\\{\\sigma_i\\}_{i=1}^L$，使得 $\\sigma_1$ 足够大以缓解第 3 节讨论的困难，而 $\\sigma_L$ 足够小以最小化对数据的影响。我们的目标是训练一个噪声条件分数网络，联合估计所有扰动数据分布的分数，即对任意 $\\sigma \\in \\{\\sigma_i\\}_{i=1}^L$，满足 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma) \\approx \\nabla_{\\mathbf{x}} \\log q_\\sigma(\\mathbf{x})$。需注意，当 $\\mathbf{x} \\in \\mathbb{R}^D$ 时，$\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma) \\in \\mathbb{R}^D$。我们将 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 称为噪声条件分数网络（Noise Conditional Score Network, NCSN）。\n与基于似然的生成模型和 GANs 类似，模型架构设计对生成高质量样本至关重要。在本工作中，我们主要关注适用于图像生成的架构设计，其他领域的架构设计将留待后续研究。由于噪声条件分数网络 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 的输出形状与输入图像 $\\mathbf{x}$ 相同，我们借鉴语义分割领域成功模型架构的设计思路（例如语义分割任务）。在实验中，我们的模型 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 融合了 U-Net 的架构设计与空洞卷积/扩张卷积（二者在语义分割中已被证明非常成功）。此外，我们采用实例归一化（instance normalization），并基于其在部分图像生成任务中的卓越表现，使用条件实例归一化的改进版本实现对噪声层级 $\\sigma_i$ 的条件化。关于模型架构的更多细节可详见附录 A。\n通过分数匹配学习噪声条件分数网络 切片分数匹配与去噪分数匹配均可用于训练噪声条件分数网络（NCSN）。我们采用去噪分数匹配，因其在训练速度上略占优势，且更自然地契合噪声扰动数据分布的分数估计任务。需强调的是，经验切片分数匹配同样适用于 NCSN 训练。\n我们选择噪声分布为 $q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x}) = \\mathcal{N}(\\tilde{\\mathbf{x}} \\mid \\mathbf{x}, \\sigma^2 I)$，因此 $\\nabla_{\\tilde{\\mathbf{x}}} \\log q_\\sigma(\\tilde{\\mathbf{x}} \\mid \\mathbf{x}) = -(\\tilde{\\mathbf{x}} - \\mathbf{x}) / \\sigma^2$。对于给定噪声强度 $\\sigma$，去噪分数匹配的目标函数（式(2)）为：\n$$ \\ell(\\theta; \\sigma) \\triangleq \\frac{1}{2} \\mathbb{E}_{p_{\\text{data}}(\\mathbf{x})} \\mathbb{E}_{\\tilde{\\mathbf{x}} \\sim \\mathcal{N}(\\mathbf{x}, \\sigma^2 I)} \\left[ \\left\\| \\mathbf{s}_\\theta(\\tilde{\\mathbf{x}}, \\sigma) + \\frac{\\tilde{\\mathbf{x}} - \\mathbf{x}}{\\sigma^2} \\right\\|_2^2 \\right]. \\tag{5} $$随后，我们将式(5)对所有 $\\sigma \\in \\{\\sigma_i\\}_{i=1}^L$ 求和，得到统一目标函数：\n$$ \\mathcal{L}(\\theta; \\{\\sigma_i\\}_{i=1}^L) \\triangleq \\frac{1}{L} \\sum_{i=1}^L \\lambda(\\sigma_i) \\ell(\\theta; \\sigma_i), \\tag{6} $$其中 $\\lambda(\\sigma_i) \u003e 0$ 是依赖于 $\\sigma_i$ 的系数函数。假设 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 具有足够容量，则式(6)的极小值点 $\\mathbf{s}_\\theta^*(\\mathbf{x}, \\sigma)$ 满足 $\\mathbf{s}_\\theta^*(\\mathbf{x}, \\sigma_i) = \\nabla_{\\mathbf{x}} \\log q_{\\sigma_i}(\\mathbf{x})$ 几乎必然成立（对所有 $i \\in \\{1,2,\\cdots,L\\}$），因为式(6)是 $L$ 个去噪分数匹配目标函数的锥形组合。\n关于系数函数 $\\lambda(\\cdot)$ 的取值存在多种可能选择。理想情况下，我们希望所有 $\\{\\sigma_i\\}_{i=1}^L$ 对应的 $\\lambda(\\sigma_i)\\ell(\\theta;\\sigma_i)$ 具有大致同阶的量级。通过实验观察发现，当分数网络训练至最优时，$\\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)\\|_2 \\propto 1/\\sigma$。这一现象启发我们选择 $\\lambda(\\sigma) = \\sigma^2$。在此选择下，$\\lambda(\\sigma)\\ell(\\theta;\\sigma) = \\sigma^2 \\ell(\\theta;\\sigma) = \\frac{1}{2}\\mathbb{E}\\left[\\|\\mathbf{s}_\\theta(\\tilde{\\mathbf{x}}, \\sigma) + \\frac{\\tilde{\\mathbf{x}} - \\mathbf{x}}{\\sigma}\\|_2^2\\right]$。由于 $\\frac{\\tilde{\\mathbf{x}} - \\mathbf{x}}{\\sigma} \\sim \\mathcal{N}(0, I)$ 且 $\\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)\\|_2 \\propto 1$，可直接推导出 $\\lambda(\\sigma)\\ell(\\theta;\\sigma)$ 的量级与 $\\sigma$ 无关。\n需特别强调：我们的目标函数（式(6)）具有以下核心优势：\n训练过程无需对抗训练； 无需代理损失函数（例如对比散度等）； 训练过程中无需从分数网络进行采样（区别于对比散度等方法）； 不要求分数网络具有特殊架构即可保证可训练性。\n此外，当 $\\lambda(\\cdot)$ 和 $\\{\\sigma_i\\}_{i=1}^L$ 固定时，该目标函数可用于定量比较不同噪声条件分数网络（NCSN）的性能。 通过退火朗之万动力学进行 NCSN 推理 在训练完噪声条件分数网络 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 后，我们提出一种采样方法——退火朗之万动力学（算法 1）——用于生成样本。该方法受模拟退火和退火重要性采样的启发。如算法 1 所示，我们首先从某个固定的先验分布（例如均匀噪声）初始化样本 $\\tilde{\\mathbf{x}}_0$。随后，我们以步长 $\\alpha_1$ 运行朗之万动力学，从 $q_{\\sigma_1}(\\mathbf{x})$ 采样。接着，我们从上一次模拟的最终样本出发，以减小的步长 $\\alpha_2$ 运行朗之万动力学，从 $q_{\\sigma_2}(\\mathbf{x})$ 采样。我们以这种方式继续迭代：将 $q_{\\sigma_{i-1}}(\\mathbf{x})$ 的朗之万动力学最终样本作为 $q_{\\sigma_i}(\\mathbf{x})$ 的初始样本，并逐步减小步长 $\\alpha_i$（其中 $\\alpha_i = \\epsilon \\cdot \\sigma_i^2 / \\sigma_L^2$）。最终，我们运行朗之万动力学从 $q_{\\sigma_L}(\\mathbf{x})$ 采样，当 $\\sigma_L \\approx 0$ 时，$q_{\\sigma_L}(\\mathbf{x})$ 与原始数据分布 $p_{\\text{data}}(\\mathbf{x})$ 高度接近。\n由于所有扰动分布 $\\{q_{\\sigma_i}\\}_{i=1}^L$ 均通过高斯噪声进行扰动，其支撑集覆盖整个空间且分数定义良好，从而规避了流形假设带来的困难。当 $\\sigma_1$ 足够大时，$q_{\\sigma_1}(\\mathbf{x})$ 的低密度区域显著缩小，且不同模态之间的隔离程度降低。如前所述，这能提升分数估计的准确性并加速朗之万动力学的混合过程。因此，我们可以合理假设朗之万动力学能从 $q_{\\sigma_1}(\\mathbf{x})$ 生成高质量样本。这些样本很可能处于 $q_{\\sigma_1}(\\mathbf{x})$ 的高密度区域，这意味着它们也大概率处于 $q_{\\sigma_2}(\\mathbf{x})$ 的高密度区域——鉴于 $q_{\\sigma_1}(\\mathbf{x})$ 与 $q_{\\sigma_2}(\\mathbf{x})$ 仅存在细微差异。由于分数估计和朗之万动力学在高密度区域表现更优，$q_{\\sigma_1}(\\mathbf{x})$ 的样本可作为 $q_{\\sigma_2}(\\mathbf{x})$ 朗之万动力学的优质初始样本。同理，$q_{\\sigma_{i-1}}(\\mathbf{x})$ 为 $q_{\\sigma_i}(\\mathbf{x})$ 提供优质初始样本，最终我们能从 $q_{\\sigma_L}(\\mathbf{x})$ 获得高质量样本。\n在算法1中，关于步长 $\\alpha_i$ 的调整策略存在多种可能方案。我们的选择是 $\\alpha_i \\propto \\sigma_i^2$，其动机在于固定朗之万动力学中的\u0026quot;信号-噪声比\u0026quot; $\\frac{\\alpha_i \\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)}{2\\sqrt{\\alpha_i} \\mathbf{z}}$ 的量级。需注意：$\\mathbb{E}\\left[\\left\\|\\frac{\\alpha_i \\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)}{2\\sqrt{\\alpha_i} \\mathbf{z}}\\right\\|_2^2\\right] \\approx \\mathbb{E}\\left[\\frac{\\alpha_i \\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)\\|_2^2}{4}\\right] \\propto \\frac{1}{4} \\mathbb{E}\\left[\\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)\\|_2^2\\right]$。如前所述，当分数网络训练接近最优时，$\\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)\\|_2 \\propto 1/\\sigma_i$，因此 $\\left\\|\\frac{\\alpha_i \\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)}{2\\sqrt{\\alpha_i} \\mathbf{z}}\\right\\|_2^2 \\propto \\frac{1}{4} \\mathbb{E}\\left[\\|\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma_i)\\|_2^2\\right] \\propto \\frac{1}{4}$，该量级与 $\\sigma_i$ 无关。\n为验证退火朗之万动力学的有效性，我们通过一个玩具实验进行演示：仅使用分数从两个分离良好的高斯混合分布中采样（实验设置同3.2节）。我们采用算法1进行采样，选择 $\\{\\sigma_i\\}_{i=1}^L$ 为几何级数，其中 $L=10$，$\\sigma_1=10$，$\\sigma_{10}=0.1$。实验结果展示于图3。对比图3(b)与(c)可见，退火朗之万动力学能正确恢复两模态间的相对权重，而标准朗之万动力学则失败。\n实验 相关工作 我们的方法与若干通过学习马尔可夫链转移算子实现采样的方法存在相似性。例如，生成随机网络（GSN）利用去噪自编码器训练一个马尔可夫链，其平衡分布与数据分布相匹配。类似地，我们的方法通过训练朗之万动力学中使用的分数函数，从数据分布中进行采样。但需注意：GSN 通常从接近训练数据点的位置初始化马尔可夫链，因此要求链在不同模态间快速转移。相比之下，我们的退火朗之万动力学从非结构化噪声初始化。非平衡热力学（NET）采用预设扩散过程将数据缓慢转换为随机噪声，再通过训练逆向扩散过程实现还原。然而，NET 可扩展性较差，因其要求扩散过程步长极小，且训练时需模拟数千步的马尔可夫链。\n先前的方法（如扩散训练（IT）和变分回溯（VW））同样采用不同噪声层级/温度训练马尔可夫链的转移算子。IT 和 VW（以及 NET）均通过最大化适当边缘似然的证据下界（ELBO）训练模型。实践中，它们常生成模糊的图像样本（与变分自编码器类似）。与之形成鲜明对比的是，我们的目标函数基于分数匹配而非似然优化，因此能够生成与 GAN 相媲美的高质量图像。\n与前述方法相比，我们的方法存在若干结构性差异。首先，我们不需要在训练过程中从马尔可夫链采样。相比之下，生成随机网络（GSN）的回溯过程需要多次运行马尔可夫链以生成\u0026quot;负样本\u0026quot;。包括非平衡热力学（NET）、扩散训练（IT）和变分回溯（VW）在内的其他方法，也需要为每个输入模拟马尔可夫链来计算训练损失。这种差异使我们的方法在训练深度模型时更加高效且可扩展。其次，我们的训练与采样方法相互解耦。对于分数估计，可采用切片分数匹配和去噪分数匹配等任意方法；对于采样，可使用任何基于分数的方法，包括朗之万动力学和（潜在的）哈密顿蒙特卡洛。我们的框架允许任意组合分数估计器和（基于梯度的）采样方法，而大多数先前方法则将模型与特定的马尔可夫链绑定。最后，我们的方法可用于训练基于能量的模型（EBM），只需将基于能量模型的梯度作为分数模型。相比之下，目前尚不清楚先前学习马尔可夫链转移算子的方法如何直接用于训练 EBM。\n分数匹配最初是为学习基于能量的模型（EBM）而提出的。然而，许多现有基于分数匹配的方法要么不可扩展，要么无法产生与变分自编码器（VAE）或生成对抗网络（GAN）相当质量的样本。为提升深度基于能量模型的训练性能，一些近期工作转向对比散度，并提出在训练和测试中使用朗之万动力学进行采样。然而，与我们的方法不同，对比散度在训练中使用计算昂贵的朗之万动力学作为内循环。将退火与去噪分数匹配相结合的思想也在先前工作中在不同背景下进行了研究。然而，这些工作主要聚焦于学习表示以改进分类性能，而非生成建模。去噪分数匹配的方法也可从贝叶斯最小二乘的角度推导，并可借助 Stein 无偏风险估计器的技术实现。\n结论 我们提出了一种基于分数的生成建模框架：首先通过分数匹配估计数据密度的梯度，再利用朗之万动力学生成样本。我们分析了该方法朴素应用所面临的若干挑战，并提出通过训练噪声条件分数网络（NCSN） 和采用退火朗之万动力学采样来应对这些挑战。本方法无需对抗训练、训练过程中无需 MCMC 采样，且对模型架构无特殊要求。实验表明，我们的方法能够生成此前仅由最优基于似然模型和 GAN 生成的高质量图像。我们在 CIFAR-10 数据集上取得了8.87 的最先进 Inception Score，且 FID 分数与 SNGANs 相当。\nA 架构 本实验中所用噪声条件分数网络（NCSN）的架构包含三个重要组件：实例归一化、空洞卷积和U-Net类型架构。下文将详细介绍这些组件的背景，并阐述我们如何修改它们以适应研究需求。若需更全面的细节和参考实现，建议读者查阅我们公开的代码库。我们的分数网络基于 PyTorch 实现，代码 Github。\nA.1 实例归一化 我们采用条件实例归一化，使分数网络 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$ 在预测分数时能够考虑噪声水平 $\\sigma$。在条件实例归一化中，针对不同的 $\\sigma \\in \\{\\sigma_i\\}_{i=1}^L$ 采用不同的缩放参数与偏置参数。具体而言，假设输入 $\\mathbf{x}$ 包含 $C$ 个特征图。令 $\\mu_k$ 和 $s_k$ 分别表示 $\\mathbf{x}$ 的第 $k$ 个特征图沿空间轴计算的均值与标准差。条件实例归一化通过以下公式实现：\n$$ \\mathbf{z}_k = \\gamma[i,k] \\frac{\\mathbf{x}_k - \\mu_k}{s_k} + \\beta[i,k], $$其中 $\\gamma \\in \\mathbb{R}^{L \\times C}$ 和 $\\beta \\in \\mathbb{R}^{L \\times C}$ 为可学习参数，$k$ 表示特征图索引，$i$ 表示 $\\{\\sigma_i\\}_{i=1}^L$ 中 $\\sigma$ 的索引。\n然而，实例归一化的一个缺点是它完全移除了不同特征图的 $\\mu_k$ 信息，这可能导致生成图像出现颜色偏移。为解决此问题，我们提出对条件实例归一化进行简单改进：首先计算 $\\mu_k$ 的均值与标准差，分别记为 $m$ 和 $v$；然后引入另一个可学习参数 $\\alpha \\in \\mathbb{R}^{L \\times C}$。改进后的条件实例归一化定义为：\n$$ \\mathbf{z}_k = \\gamma[i,k] \\frac{\\mathbf{x}_k - \\mu_k}{s_k} + \\beta[i,k] + \\alpha[i,k] \\frac{\\mu_k - m}{v}. $$我们将这种改进的条件实例归一化简称为 CondInstanceNorm++。在我们的架构中，CondInstanceNorm++ 被添加在每个卷积层和池化层之前。\nA.2 空洞卷积 空洞卷积可在保持特征图分辨率的同时扩大感受野。研究表明，空洞卷积在语义分割任务中效果显著，因其能更好地保留高分辨率特征图中的位置信息。在噪声条件分数网络（NCSN）的架构设计中，我们使用空洞卷积替换除第一层外的所有下采样层。\nA.3 U-Net 架构 U-Net 是一种具有特殊跳跃连接的架构。这些跳跃连接有助于将浅层中的低层信息（如位置和形状）传递至网络的深层。由于浅层通常包含位置和形状等低层信息，这些跳跃连接有助于提升语义分割的结果。为构建 $\\mathbf{s}_\\theta(\\mathbf{x}, \\sigma)$，我们采用 RefineNet 的架构，这是一种结合了 ResNet 设计的 U-Net 现代变体。关于 RefineNet 架构的详细描述，建议读者参考文献 [32]。\n在我们的实验中，我们使用 4 级级联的 RefineNet。我们采用预激活残差块（pre-activation residual blocks），并移除 RefineNet 架构中的所有批归一化层，替换为 CondInstanceNorm++。我们将 RefineNet 中的最大池化层替换为平均池化，因为平均池化在图像生成任务（如风格迁移）中被证实能产生更平滑的图像。此外，我们在 RefineNet 块中的每个卷积和平均池化前添加 CondInstanceNorm++（尽管原始 RefineNet 块中未使用归一化）。所有激活函数均选择为 ELU。如前所述，我们使用空洞卷积替换残差块中的下采样层（第一层除外）。遵循常规实践，我们在进入下一级联时将膨胀率增加一倍。对于 CelebA 和 CIFAR-10 实验，第一级对应的层的滤波器数量为 128，其他级的滤波器数量加倍；而对于 MNIST 实验，滤波器数量则减半。\n","date":"2026-02-04T14:56:05+08:00","permalink":"https://ruheyun.github.io/p/ncsn/","title":"NCSN"},{"content":"扩散模型笔记(1) 论文基本信息 论文名称：Deep Unsupervised Learning using Nonequilibrium Thermodynamics\n出版期刊：ICML 2015\n学校机构：Stanford University，University of California, Berkeley\n论文翻译 以下翻译结合了AI工具和我对论文的理解，在翻译的过程中会省略我认为不重要的部分，并不是全篇一字一句的翻译。并且可能翻译或理解有误。（此过程同时借助了ChatGPT和Qwen两个AI工具）\n标题 利用非平衡热力学的深度无监督学习\n摘要 机器学习中的一个核心问题在于：如何利用高度灵活的概率分布族对复杂数据集进行建模，同时保证学习、采样、推断和评估在解析上或计算上仍具有可行性。本文提出了一种能够同时实现灵活性与可处理性的方法。其核心思想受非平衡统计物理学启发，即通过迭代式的前向扩散过程，系统且缓慢地破坏数据分布中的结构。随后，我们学习一个反向扩散过程以恢复数据中的结构，从而得到一个兼具高度灵活性与可处理性的数据生成模型。该方法使我们能够快速地在具有数千层或时间步的深度生成模型中进行学习、采样与概率评估，并可计算所学模型下的条件概率与后验概率。此外，我们还开源发布了该算法的参考实现Github。\n引言 历史上，概率模型一直面临两个相互冲突目标之间的权衡：可处理性与灵活性。具有可处理性的模型能够进行解析式评估并易于拟合数据（例如高斯分布或拉普拉斯分布）。然而，这些模型难以恰当地描述丰富数据集中的复杂结构。另一方面，灵活的模型则可以被建模以拟合任意数据中的结构。例如，我们可以通过任意（非负）函数 $\\phi(x)$ 来定义模型，从而得到灵活的分布 $p(x) = \\frac{\\phi(x)}{Z}$，其中 Z 为归一化常数。然而，计算该归一化常数通常是不可行的。对这类灵活模型进行概率评估、训练或采样通常需要代价高昂的蒙特卡洛过程。\n目前已存在多种解析近似方法，它们虽可缓解但无法彻底消除这一权衡——例如平均场理论及其扩展、变分贝叶斯、对比散度、最小概率流、最小 KL 收缩、恰当评分规则、分数匹配、伪似然、循环信念传播等等，不一而足。此外，非参数方法亦可取得显著成效。\n非参数方法可被视为在可处理模型与灵活模型之间实现平滑过渡的一种途径。例如，非参数高斯混合模型在表示少量数据时可能仅使用单个高斯分布，而在表示无限量数据时则可扩展为由无限多个高斯分布构成的混合模型。\n参数化 GMM：需预先设定 K=5 个高斯分量，无论数据多复杂都只能用这 5 个分量拟合；\n非参数 GMM：无需指定 K，算法自动学习需要多少个分量——简单数据可能只用 2 个分量，复杂数据可能用 20 个甚至更多。\n扩散概率模型 我们提出了一种定义概率模型的新方法，该方法具备以下特性：\n模型结构具有极高的灵活性； 支持精确采样； 易于与其他分布相乘（例如用于计算后验概率）； 模型的对数似然以及单个状态的概率均可高效计算。 我们的方法利用马尔可夫链逐步将一个分布转换为另一个分布，这一思想源于非平衡统计物理学和序列蒙特卡洛方法。我们构建了一个生成式马尔可夫链，通过扩散过程将一个简单的已知分布（例如高斯分布）转换为目标（数据）分布。与使用马尔可夫链对已预先定义的模型进行近似评估不同，我们显式地将概率模型定义为马尔可夫链的终点。由于扩散链中的每一步都具有可解析计算的概率，因此整个链的概率亦可进行解析式评估。\n在该框架下的学习过程涉及对扩散过程中的微小扰动进行估计。相比使用单一的、无法解析归一化的势函数来显式描述完整分布，估计微小扰动在计算上更为可行。此外，由于对任意光滑的目标分布都存在对应的扩散过程，该方法能够捕捉任意形式的数据分布。\nPotential function：势函数，源自物理学\u0026quot;势能\u0026quot;（potential energy）概念，在概率模型中表示未归一化的能量/权重函数。\n我们通过在多个数据集上训练高对数似然模型，验证了这些扩散概率模型的有效性。所用数据集包括：二维瑞士卷（two-dimensional swiss roll）、二值序列、手写数字（MNIST）以及若干自然图像数据集（CIFAR-10、树皮纹理和枯叶模型）。\n相关的其他工作 wake-sleep algorithm 首次提出了让推断模型与生成概率模型相互对抗训练的思想。此后近二十年间，这一思路在很大程度上未被深入探索，尽管存在一些例外工作。近年来，围绕该思想的研究呈现爆发式增长。之后提出的变分学习与推断算法，使得灵活的生成模型与潜在变量的后验分布能够被直接联合训练、相互优化。\n有些算法翻译为中文很不好理解，所以不做翻译。\n这些论文中使用的变分界与我们训练目标中采用的变分界以及 Sminchisescu 等人（2006）早期工作中的形式相似。然而，我们的动机与模型形式均存在显著差异。相较于上述方法，本文工作保留了以下区别与优势：\n我们借鉴物理学、准静态过程（quasi-static processes）以及退火重要性采样（annealed importance sampling）的思想构建框架，而非基于变分贝叶斯方法； 我们展示了如何便捷地将所学分布与另一概率分布相乘（例如与条件分布相乘以计算后验分布）； 我们解决了变分推断方法中推断模型训练尤为困难的问题——该困难源于推断模型与生成模型在目标函数中的不对称性。为此，我们将前向（推断）过程限制为简单的函数形式，使得反向（生成）过程具有相同的函数形式； 我们训练了包含数千层（或时间步）的模型，而非仅限于少量层次； 我们为每一层（或时间步）中的熵产生（entropy production）提供了上界与下界估计。 存在多种与概率模型训练相关的技术（下文将简要总结），这些方法致力于构建高度灵活的生成模型形式、训练随机轨迹，或学习贝叶斯网络的逆过程。\n技术/作者 时间 简述 Reweighted wake-sleep 2015 对原始wake-sleep algorithm提出了扩展并改进了学习规则。 Generative stochastic networks 2013/2014 通过训练马尔可夫核，使其平稳分布与数据分布相匹配。 Neural autoregressive distribution estimators 2011/2013 将联合分布分解为一系列关于各维度的可处理条件分布序列。 Adversarial networks 2014 通过让生成模型与一个试图区分生成样本与真实数据的分类器进行对抗训练。 Schmidhuber（作者） 1992 提出的类似目标学习了一个双向映射，将数据映射到具有边缘独立单元的表示空间。 Rippel 与 Adams以及 Dinh（作者） 2013/2014 学习了到潜在表示空间的双射确定性映射，该潜在空间具有简单的阶乘密度函数。 Stuhlmüller（作者） 2013 贝叶斯网络学习了随机逆映射。 Mixtures of conditional Gaussian scale mixtures, MCGSMs 2012 利用高斯尺度混合来描述数据集，其参数依赖于一系列因果邻域。 此外，还有大量工作致力于学习从简单潜在分布到数据分布的灵活生成映射——早期范例包括 MacKay 将神经网络引入作为生成模型，以及 Bishop 等学习从潜在空间到数据空间的随机流形映射。本文将在实验中与对抗网络及 MCGSMs 进行对比。\n来自物理学的相关思想包括 Jarzynski 等式，该等式在机器学习中被称为退火重要性采样（Annealed Importance Sampling, AIS）。AIS 利用马尔可夫链将一个分布缓慢转换为另一个分布，以计算归一化常数的比值。Burda 等人进一步证明，AIS 亦可基于反向轨迹而非前向轨迹执行。朗之万动力学（Langevin dynamics）作为福克-普朗克方程（Fokker-Planck equation）的随机实现形式，展示了如何定义一个高斯扩散过程，使其以任意目标分布作为平稳分布。福克-普朗克方程也被用来进行随机优化。最后，柯尔莫哥洛夫前向与后向方程（Kolmogorov forward and backward equations）表明：对于许多前向扩散过程，其对应的反向扩散过程可用相同的函数形式加以描述。\n算法 我们的目标是定义一个前向（或推断）扩散过程，将任意复杂的数据分布转换为简单且易于处理的分布；随后学习该扩散过程的有限时间反向过程，以此定义我们的生成模型分布（见图1）。我们首先描述前向推断扩散过程，继而展示如何训练反向生成扩散过程并利用其进行概率评估。此外，我们还为反向过程推导了熵的上下界，并说明所学分布如何与任意第二个分布相乘（例如在图像修复或去噪任务中计算后验分布时所需的操作）。\n图1：在 2-d swiss roll data 上训练的建模框架。第一行展示了前向轨迹 $q(x^{(0:T)})$ 在各时间切片上的分布。数据分布（左）经历高斯扩散过程，逐步转化为单位协方差高斯分布（右）。第二行展示了训练所得反向轨迹 $p(x^{(0:T)})$ 对应的时间切片。单位协方差高斯分布（右）经过具有学习得到的均值与协方差函数的高斯扩散过程，逐步重构回原始数据分布（左）。第三行展示了同一反向扩散过程的漂移项（drift term）$f_\\mu(x^{(t)}, t) - x^{(t)}$。\n为什么论文这里又称前向过程为 Inference Process？\n在这篇论文中，“inference” 指的是：给定一个真实数据样本 x(0) ，推断（或构造）它在整个扩散轨迹中对应的噪声版本序列 x(1),x(2),…,x(T) 。这里的 “inference” 不是指“从训练好的模型生成新样本”，而是指“为训练目的，从已知数据反推其在扩散链中的演化路径”。\n前向轨迹 我们将数据分布记为 $q(x^{(0)})$。通过反复应用针对 $\\pi(y)$ 的马尔可夫扩散核 $T_\\pi(y \\mid y'; \\beta)$，数据分布被逐步转换为一个性质良好（解析可处理）的分布 $\\pi(y)$，其中 $\\beta$ 为扩散速率， $$ \\pi (y) = \\int dy' \\, T_\\pi (y|y'; \\beta) \\, \\pi (y') \\tag{1} $$$$ q \\left(x^{(t)} \\mid x^{(t-1)} \\right) = T_\\pi \\left(x^{(t)} \\mid x^{(t-1)}; \\beta_t \\right). \\tag{2} $$ 公式 (1)：目标分布的平稳性条件。\n该公式定义了 目标分布 $\\pi (y)$ 作为扩散过程的平稳分布（equilibrium distribution）：\n$T_{\\pi}(y∣y′;\\beta)$ 是 马尔可夫扩散核（Markov diffusion kernel），表示从状态 $y′$ 到 $y$ 的转移概率，$\\beta$ 是扩散速率（diffusion rate）。 $\\pi(y)$ 满足：当系统达到平衡时，应用扩散核 $T_{\\pi}$ 后分布保持不变。 在扩散模型中，$\\pi(y)$ 通常选择为标准高斯分布（如 $\\pi(y) = N(y;0,I)$），因其解析性质良好（易于计算）。 公式 (2)：前向扩散过程的定义。\n该公式定义了 前向扩散过程（inference process）的条件转移概率：\n$q(x^{(t)}∣x^{(t−1)})$ 是在时间步 $t−1$ 给定 $x^{(t−1)}$ 时，状态 $x^{(t)}$ 的条件分布。 $T_{\\pi}(x^{(t)}∣x^{(t−1)};β_t)$ 是时间相关的扩散核，$\\beta_t$ 是第 $t$ 步的扩散速率（通常随时间递增）。 核心思想：前向过程使用与目标分布 $\\pi (y)$ 相同的扩散核 $T_{\\pi}$，但 $\\pi$ 随时间变化（$\\beta_t$ 而非固定 $\\beta$）。 前向轨迹对应于从数据分布开始并执行 $T$ 步扩散的过程，因此有 $$ q \\left( x^{(0 \\cdots T)} \\right) = q \\left( x^{(0)} \\right) \\prod_{t=1}^T q \\left( x^{(t)} \\mid x^{(t-1)} \\right) \\tag{3} $$ 马尔科夫性质，每一步只依赖与前一步，与其他步独立。\n在下文展示的实验中，$q(x^{(t)}∣x^{(t−1)})$ 对应于以下两种扩散过程之一：\n高斯扩散：将数据逐步扩散至单位协方差高斯分布（identity-covariance Gaussian distribution）； 二项扩散：将数据逐步扩散至独立二项分布（independent binomial distribution）。 反向轨迹 生成分布将被训练以描述相同的轨迹，但方向相反， $$ p \\left( x^{(T)} \\right) = \\pi \\left( x^{(T)} \\right) \\tag{4} $$$$ p \\left( x^{(0 \\cdots T)} \\right) = p \\left( x^{(T)} \\right) \\prod_{t=1}^T p \\left( x^{(t-1)} \\mid x^{(t)} \\right). \\tag{5} $$ 反向轨迹也是马尔科夫链，根据马尔科夫性质得到的。\n关键意义：该框架通过学习反向扩散轨迹，使模型能够从简单分布 $\\pi(x^{(T)})$ 逐步还原数据分布 $q(x^{(0)})$。由于每一步反向转移概率 $p(x^{(t−1)}∣x^{(t)})$ 均可参数化为神经网络，因此整个生成过程既灵活又可解析计算。\n对于高斯扩散与二项扩散，在连续扩散情形下（即步长 $\\beta$ 趋近于零的极限），扩散过程的反向过程具有与前向过程完全相同的函数形式。由于 $q(x^{(t)}∣x^{(t−1)})$ 服从高斯（或二项）分布，且当 $\\beta_t$ 足够小时，反向条件分布 $q(x^{(t−1)}∣x^{(t)})$ 同样服从高斯（或二项）分布。轨迹长度 $T$ 越长，每一步的扩散速率 $\\beta$ 即可取得越小，从而使离散扩散过程更逼近连续极限，反向过程的函数形式亦更精确地匹配前向过程。\n在学习过程中，仅需估计高斯扩散核的均值与协方差，或二项扩散核的比特翻转概率。如表 App.1 所示，$f_{\\mu}(x^{(t)},t)$ 与 $f_{\\Sigma}(x^{(t)},t)$ 是定义高斯分布反向马尔可夫转移的均值与协方差的函数，$f_b(x^{(t)},t)$ 是为二项分布提供比特翻转概率的函数。运行该算法的计算成本等于这些函数的计算开销乘以时间步数。本文所有实验结果均采用多层感知机（MLP）来参数化这些函数。然而，大量回归或函数拟合技术均可适用，包括非参数方法。\n模型概率 生成模型赋予原始数据的概率为 $$ p \\left( x^{(0)} \\right) = \\int dx^{(1 \\cdots T)} \\, p \\left( x^{(0 \\cdots T)} \\right). \\tag{6} $$ 直观上，该积分难以处理——但借鉴退火重要性采样（annealed importance sampling）和 Jarzynski 等式的思想，我们转而评估前向与反向轨迹的相对概率，并对前向轨迹进行平均， $$ \\begin{align} p \\left( x^{(0)} \\right) \u0026= \\int dx^{(1 \\cdots T)} \\, p \\left( x^{(0 \\cdots T)} \\right) \\frac{q \\left( x^{(1 \\cdots T)} \\mid x^{(0)} \\right)}{q \\left( x^{(1 \\cdots T)} \\mid x^{(0)} \\right)} \\tag{7} \\\\ \u0026= \\int dx^{(1 \\cdots T)} \\, q \\left( x^{(1 \\cdots T)} \\mid x^{(0)} \\right) \\frac{p \\left( x^{(0 \\cdots T)} \\right)}{q \\left( x^{(1 \\cdots T)} \\mid x^{(0)} \\right)} \\tag{8} \\\\ \u0026= \\int dx^{(1 \\cdots T)} \\, q \\left( x^{(1 \\cdots T)} \\mid x^{(0)} \\right) p \\left( x^{(T)} \\right) \\prod_{t=1}^{T} \\frac{p \\left( x^{(t-1)} \\mid x^{(t)} \\right)}{q \\left( x^{(t)} \\mid x^{(t-1)} \\right)}. \\tag{9} \\end{align} $$ 公式（7）：概率表达式的重写，分子分母同乘相同因子，等式不变；\n公式（8）：重要性采样形式，将积分改写为对前向轨迹的期望值；\n公式（9）：轨迹相对概率的显示表达，由将（5）带入（8）得到。\n该积分可通过从前向轨迹 $q(x^{(1⋯T)}∣x^{(0)})$ 中采样并取平均值来快速评估。当扩散步长 $\\beta$ 趋近于无穷小时，前向与反向轨迹分布可趋于一致。若二者完全相同，则仅需从前向轨迹 $q(x^{(1⋯T)}∣x^{(0)})$ 中采样单一样本，即可通过代入精确计算上述积分。此情形对应于统计物理学中的准静态过程（quasi-static process）。\n核心概念解析\n概念 说明 快速评估 通过蒙特卡洛采样估计积分 $E_q[⋅]$，避免高维解析积分 轨迹分布一致 当 $\\beta \\rightarrow 0$ 且 $T \\rightarrow \\infty$（连续扩散极限）时，$p(x^{(0⋯T)})=q(x^{(0⋯T)})$，此时相对概率比值恒为 1 单样本精确估计 若 $p=q$，则 $\\frac{p(x^{(0⋯T)})}{q(x^{(1⋯T)}∣x^{(0)})}=const$，任意单样本即可给出精确期望值（方差为零） 准静态过程 热力学中系统在无限缓慢变化下始终保持平衡态的过程；在扩散模型中，对应于每步扰动极小、前向/反向过程可逆的理想极限 实践意义：虽然实际应用中 $\\beta$ 无法取无穷小（计算成本限制），但该理论表明——轨迹越长、每步扰动越小，模型对数似然的估计方差越低。这为扩散模型设计提供了理论指导：增加时间步数 $T$ 可提升概率估计精度。\n训练 训练等价于最大化模型的对数似然， $$ L = \\int dx^{(0)} q\\left(x^{(0)}\\right) \\log p\\left(x^{(0)}\\right) \\tag{10} $$ 该目标函数可以重写为： $$ L = \\int dx^{(0)} q\\left(x^{(0)}\\right) \\log \\left[ \\int dx^{(1 \\cdots T)} q\\left(x^{(1 \\cdots T)} \\mid x^{(0)}\\right) p\\left(x^{(T)}\\right) \\prod_{t=1}^T \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right], \\tag{11} $$ 该表达式由Jensen不等式提供了一个下界： $$ L \\geq \\int dx^{(0 \\cdots T)} q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ p\\left(x^{(T)}\\right) \\prod_{t=1}^T \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right]. \\tag{12} $$ 公式解析（q不含参数，p含参数）\n公式（10）：最大似然目标。本质是 期望对数似然（负交叉熵）。\n公式（11）：将公式（9）带入（10），通过引入重要性采样，将高维积分转化为轨迹期望。\n公式（12）：Jensen 不等式下界，避免计算轨迹比值，下界可表示为单轨迹的对数似然，通过蒙特卡洛采样估计。\n该是扩散模型的训练目标函数。它将复杂的最大似然估计转化为一个可优化的目标，且：\n无需计算归一化常数 仅需对轨迹进行采样和局部计算 与变分推断中的 ELBO 本质相同，但通过扩散过程结构实现了更精确的下界 与单样本精确估计的关联\n当模型完美学习（$p=q$）且处于准静态极限时：\n轨迹比值 $\\frac{p(x^{(0:T)})}{q(x^{(1:T)}∣x^{(0)})}$ 变为常数 此时 $log⁡E[X]=E[log⁡X]$，不等式取等，下界达到紧致 这解释了为何在理想情况下\u0026quot;单样本即可精确估计\u0026quot;（但实际中需多采样） 如附录 B 所述，对于我们的扩散轨迹，该下界简化为， $$ L \\geq K \\tag{13} $$$$ \\begin{align*} K = \u0026-\\sum_{t=2}^T \\int dx^{(0)} dx^{(t)} q\\left(x^{(0)}, x^{(t)}\\right) D_{KL}\\left(q\\left(x^{(t-1)} \\mid x^{(t)}, x^{(0)}\\right) \\parallel p\\left(x^{(t-1)} \\mid x^{(t)}\\right)\\right) \\\\ \u0026+ H_q\\left(X^{(T)} \\mid X^{(0)}\\right) - H_q\\left(X^{(1)} \\mid X^{(0)}\\right) - H_p\\left(X^{(T)}\\right). \\tag{14} \\end{align*} $$ 公式（14）求和项：\n本质是每步的 KL 散度期望 衡量反向生成过程 p 与前向推断过程 q 的差异 训练目标：最小化该差异（即让 p 尽可能接近 q 的逆过程） 熵项：\n$H_q\\left(X^{(T)} \\mid X^{(0)}\\right)$：最终状态 $X^{(T)}$ 在给定初始状态 $X^{(0)}$ 下的条件熵\n$H_q\\left(X^{(1)} \\mid X^{(0)}\\right)$：第一步后的条件熵\n$H_p\\left(X^{(T)}\\right)$：模型在最终状态 $X^{(T)}$ 的熵（通常为 0，因为 $X^{(T)} \\sim \\pi$ 是固定分布）\n其中熵和 KL 散度均可解析计算。该下界的推导与变分贝叶斯方法中对数似然界（log likelihood bound）的推导过程平行。\n训练过程包括寻找能够最大化对数似然下界的反向马尔可夫转移概率， $$ \\hat{p}\\left(x^{(t-1)} \\mid x^{(t)}\\right) = \\underset{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{\\operatorname{argmax}} K. \\tag{15} $$ 由此，概率分布的估计问题被简化为对函数的回归任务：这些函数用于设定一系列高斯分布的均值与协方差（或设定一系列伯努利试验的状态翻转概率）。\n选择扩散比率$\\beta_t$ 前向轨迹中 $\\beta_t$ 的选择对训练后模型的性能至关重要。在退火重要性采样（AIS）中，中间分布的合理调度可显著提升对数配分函数估计的准确性。在热力学中，系统在不同平衡分布之间转移时所采用的路径调度，决定了自由能的损耗程度。\n自由能损耗：非平衡过程中因不可逆性导致的能量耗散。\n在高斯扩散的情形下，我们通过在 $K$ 上执行梯度上升来学习前向扩散调度 $\\beta_{2 \\cdots T}$。第一步的方差 $\\beta_1$ 被固定为一个较小的常数，以防止过拟合。为了显式表达从 $q(x^{(1 \\cdots T)} \\mid x^{(0)})$ 中采样的样本对 $\\beta_{1 \\cdots T}$ 的依赖关系，我们采用\u0026quot;冻结噪声\u0026quot;（frozen noise）技术——如（Kingma 与 Welling，2013）所述，将噪声视为额外的辅助变量，并在计算 $K$ 对参数的偏导数时保持其恒定。\n$\\beta$ 调度的选择有两种：固定或可学习。这段描述的是可学习的清况：\n即使在可学习调度中，$\\beta_1$ 仍被固定为小常数（防止过拟合） 可学习的是 $\\beta_2$ 到 $\\beta_T$，即从第 2 步开始的扩散速率 “冻结噪声”技术：这是使采样过程对 $\\beta_t$ 可微的关键技巧，本质与 VAE 中的\u0026quot;重参数化技巧\u0026quot;相同。\n刚开始以为和调度的选择有关，然后发现这个技术是为了使随机过程可微，\u0026ldquo;冻结\u0026quot;是指计算梯度时将已采样的噪声视为常数，是扩散模型中的必要技术，其实就是\u0026quot;重参数化技巧\u0026quot;的另一个表达形式。\n对于二项扩散，离散状态空间使得基于冻结噪声的梯度上升方法无法实现（因离散变量不可微）。我们转而选择前向扩散调度 $\\beta_{1 \\cdots T}$，使得每一步扩散擦除原始信号的固定比例 $1/T$，由此得到的扩散速率为 $\\beta_t = (T - t + 1)^{-1}$。\n在扩散模型里（无论 Gaussian 还是 binomial），都会用到：\n$\\beta_t$：第 t 步的噪声强度 $1-\\beta_t$：第 t 步信号保留比例 累积信号保留量：$\\bar{\\alpha}_t = \\prod_{s=1}^{t}(1-\\beta_s)$ （表示第 t 步之后，还剩多少“原始信号”） 在二项扩散情况下，每步抹掉 $\\frac{1}{T}$ 原始信1号：\n则 $\\bar{\\alpha}_t = 1 - \\frac{t}{T}$\n由 $\\bar{\\alpha}_t = \\bar{\\alpha}_{t-1}(1-\\beta_t)$\n可解得 $\\beta_t = \\frac{1}{T-t+1}$\n分布相乘与后验计算 如信号去噪或缺失值推断等任务需要计算后验分布，这要求将模型分布 $p(x^{(0)})$ 与第二个分布（或有界正函数）$r(x^{(0)})$ 相乘，从而生成一个新的分布 $\\tilde{p}(x^{(0)}) \\propto p(x^{(0)}) \\, r(x^{(0)})$。\n对于许多技术而言，分布相乘在计算上代价高昂且实现困难，这些技术包括变分自编码器（VAE）、生成式随机网络（GSN）、神经自回归分布估计器（NADE）以及大多数图模型。然而，在扩散模型框架下，分布相乘却十分直接：第二个分布 $r(x^{(0)})$ 既可以被视为对扩散过程中每一步的微小扰动，也常常能够精确地融入每一步扩散操作中。后续章节将详细阐述如何在扩散概率模型的框架下实现分布相乘。\n修改后的边际分布 首先，为了计算 $\\tilde{p}(x^{(0)})$，我们将每个中间分布乘以一个对应的函数 $r(x^{(t)})$。我们使用波浪号（tilde）表示该分布或马尔可夫转移属于一条经过此类修改的轨迹。$\\tilde{p}(x^{(0\\cdots T)})$ 是修改后的反向轨迹，它从分布 $\\tilde{p}(x^{(T)}) = \\frac{1}{\\tilde{Z}_T} p(x^{(T)}) r(x^{(T)})$ 开始，并通过一系列修改后的中间分布进行传递：\n$$ \\tilde{p}\\left(x^{(t)}\\right) = \\frac{1}{\\tilde{Z}_t} p\\left(x^{(t)}\\right) r\\left(x^{(t)}\\right), \\tag{16} $$其中 $\\tilde{Z}_t$ 是第 $t$ 个中间分布的归一化常数。\n修改后的扩散步骤 逆扩散过程的马尔可夫核 $p(x^{(t)} \\mid x^{(t+1)})$ 满足平衡条件：\n$$ p(x^{(t)}) = \\int dx^{(t+1)} \\, p(x^{(t)} \\mid x^{(t+1)}) \\, p(x^{(t+1)}). \\tag{17} $$ 我们希望扰动的马尔可夫核 $\\tilde{p}(x^{(t)} \\mid x^{(t+1)})$ 满足扰动分布的平衡条件，\n$$ \\tilde{p}(x^{(t)}) = \\int dx^{(t+1)} \\, \\tilde{p}(x^{(t)} \\mid x^{(t+1)}) \\, \\tilde{p}(x^{(t+1)}), \\tag{18} $$$$ \\frac{p(x^{(t)}) \\, r(x^{(t)})}{\\tilde{Z}_t} = \\int dx^{(t+1)} \\, \\frac{\\tilde{p}(x^{(t)} \\mid x^{(t+1)}) \\, p(x^{t+1}) \\, r(x^{(t+1)})}{\\tilde{Z}_{t+1}}, \\tag{19} $$$$ p(x^{(t)}) = \\int dx^{(t+1)} \\, \\tilde{p}(x^{(t)} \\mid x^{(t+1)}) \\, \\frac{\\tilde{Z}_t \\, r(x^{(t+1)})}{\\tilde{Z}_{t+1} \\, r(x^{(t)})} \\, p(x^{(t+1)}). \\tag{20} $$若满足\n$$ \\tilde{p}\\left(x^{(t)} \\mid x^{(t+1)}\\right) = p\\left(x^{(t)} \\mid x^{(t+1)}\\right) \\frac{\\tilde{Z}_{t+1} r\\left(x^{(t)}\\right)}{\\tilde{Z}_t r\\left(x^{(t+1)}\\right)}. \\tag{21} $$则方程 (20) 成立。\n方程 (21) 可能不对应于一个归一化的概率分布，因此我们选择 $\\tilde{p}(x^{(t)} \\mid x^{(t+1)})$ 为相应的归一化分布：\n$$ \\tilde{p}\\left(x^{(t)} \\mid x^{(t+1)}\\right) = \\frac{1}{\\tilde{Z}_t\\left(x^{(t+1)}\\right)} p\\left(x^{(t)} \\mid x^{(t+1)}\\right) r\\left(x^{(t)}\\right), \\tag{22} $$其中 $\\tilde{Z}_t(x^{(t+1)})$ 是归一化常数。\n对于高斯分布，由于其方差较小，每一步扩散通常相对于 $r(x^{(t)})$ 具有非常尖锐的峰值。这意味着 $\\frac{r(x^{(t)})}{r(x^{(t+1)})}$ 可视为对 $p(x^{(t)} \\mid x^{(t+1)})$ 的微小扰动。对高斯分布的微小扰动仅影响其均值，而不会改变归一化常数，因此在此情况下方程 (21) 与 (22) 是等价的（见附录 C）。\n应用 $r(x^{(t)})$ 若 $r(x^{(t)})$ 足够平滑，则可将其视为对反向扩散核 $p(x^{(t)} \\mid x^{(t+1)})$ 的微小扰动。在此情况下，$\\tilde{p}(x^{(t)} \\mid x^{(t+1)})$ 将具有与 $p(x^{(t)} \\mid x^{(t+1)})$ 相同的函数形式，但对于高斯核而言其均值将被扰动，而对于二项核而言其翻转率将被扰动。扰动后的扩散核见表 App.1，并在附录 C 中针对高斯核进行了推导。\n若 $r(x^{(t)})$ 可以与高斯（或二项）分布以闭式形式相乘，则它可以直接与反向扩散核 $p(x^{(t)} \\mid x^{(t+1)})$ 以闭式形式相乘。这种情况适用于 $r(x^{(t)})$ 由某些坐标子集的 delta 函数构成的情形，例如图 5 中的图像修复（inpainting）示例。\n选择 $r(x^{(t)})$ 通常，$r(x^{(t)})$ 应当在整个轨迹过程中缓慢变化。在本文的实验中，我们选择其为常数，\n$$ r\\left(x^{(t)}\\right) = r\\left(x^{(0)}\\right). \\tag{23} $$ 另一种便捷的选择是 $r(x^{(t)}) = r(x^{(0)})^{\\frac{T-t}{T}}$。在此第二种选择下，$r(x^{(t)})$ 对反向轨迹的起始分布没有贡献。这保证了从 $\\tilde{p}(x^{(T)})$ 中抽取反向轨迹的初始样本仍然简单直接。\n反向过程的熵 由于前向过程已知，我们可以推导反向轨迹中每一步条件熵的上下界，从而得到对数似然的上下界，公式 24：\n$$ \\begin{align*} H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)} \\mid X^{(0)}\\right) - H_q\\left(X^{(t)} \\mid X^{(0)}\\right) \u0026\\leq H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) \\\\ \u0026\\leq H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right), \\tag{24} \\end{align*} $$其中上下界仅依赖于 $q(x^{(1 \\cdots T)} \\mid x^{(0)})$，并且可以解析计算。推导过程见附录 A。\n实验 使用的是 Theano 库，现在已淘汰，学术上更多的用 pytorch，看代码时能看懂思路就行。\n总结 我们提出了一种新颖的概率分布建模算法，该算法支持精确采样与概率评估，并在多种玩具数据集与真实数据集（包括具有挑战性的自然图像数据集）上验证了其有效性。在所有实验中，我们均采用相似的基础算法，表明该方法能够准确建模广泛多样的分布形态。\n现有大多数密度估计技术为保持计算可行性与效率，往往不得不牺牲建模能力，且采样或概率评估的计算成本通常极高。本算法的核心在于估计一个马尔可夫扩散链的逆过程——该扩散链将数据映射至噪声分布。随着扩散步数的增加，每一步的逆分布逐渐变得简单且易于估计。最终得到的算法兼具以下优势：\n能够拟合任意数据分布（高建模灵活性） 训练过程可处理（tractable） 支持精确采样与概率评估 便于对条件分布与后验分布进行直接操作 这一设计在建模能力与计算效率之间实现了前所未有的平衡。\n附录 A 条件熵边界推导 反向轨迹中一步的条件熵 $H_q(X^{(t−1)}∣X^{(t)})$ 为 $$ H_q\\left(X^{(t-1)}, X^{(t)}\\right) = H_q\\left(X^{(t)}, X^{(t-1)}\\right) \\tag{25} $$$$ H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) + H_q\\left(X^{(t)}\\right) = H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)}\\right) \\tag{26} $$$$ H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) = H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)}\\right) - H_q\\left(X^{(t)}\\right) \\tag{27} $$ 公式 25 ：联合熵的对称性\n公式 26 ：条件熵之间的关系\n通过观察 $\\pi(y)$ 是最大熵分布，可以构建熵变化的上界。这一结论对二项分布无条件成立，对高斯分布的情形则要求训练数据的方差为 1。对于高斯分布的情况，因此需要将训练数据缩放到单位范数以保证下述等式成立。但不需要进行白化处理。该上界推导如下， $$ H_q\\left(X^{(t)}\\right) \\geq H_q\\left(X^{(t-1)}\\right) \\tag{28} $$$$ H_q\\left(X^{(t-1)}\\right) - H_q\\left(X^{(t)}\\right) \\leq 0 \\tag{29} $$$$ H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) \\leq H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right). \\tag{30} $$ 公式 28 ：随着扩散步数增加，数据分布的熵单调非减\n公式 30 ：将 27 代入 29 得到，表明了反向过程的条件熵不超过前向过程的条件熵，即给出了反向过程条件熵的紧致上界\n通过观察马尔可夫链中的额外步骤不会增加关于链中初始状态的可用信息，因此不会降低初始状态的条件熵，可以建立熵差的下界， $$ H_q\\left(X^{(0)} \\mid X^{(t)}\\right) \\geq H_q\\left(X^{(0)} \\mid X^{(t-1)}\\right) \\tag{31} $$$$ \\begin{align*} H_q\\left(X^{(t-1)}\\right) - H_q\\left(X^{(t)}\\right) \\geq \\,\u0026 H_q\\left(X^{(0)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)}\\right) \\\\ \u0026- H_q\\left(X^{(0)} \\mid X^{(t)}\\right) - H_q\\left(X^{(t)}\\right) \\tag{32} \\end{align*} $$$$ H_q\\left(X^{(t-1)}\\right) - H_q\\left(X^{(t)}\\right) \\geq H_q\\left(X^{(0)}, X^{(t-1)}\\right) - H_q\\left(X^{(0)}, X^{(t)}\\right) \\tag{33} $$$$ H_q\\left(X^{(t-1)}\\right) - H_q\\left(X^{(t)}\\right) \\geq H_q\\left(X^{(t-1)} \\mid X^{(0)}\\right) - H_q\\left(X^{(t)} \\mid X^{(0)}\\right) \\tag{34} $$$$ H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) \\geq H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)} \\mid X^{(0)}\\right) - H_q\\left(X^{(t)} \\mid X^{(0)}\\right). \\tag{35} $$ 公式 31 ：随着扩散步数增加，关于初始状态 $X^{(0)}$ 的条件熵单调非减\n公式 32-35 ：熵差下界的推导，得到单步条件熵下界\n公式 35 ：将 27 代入 34 可得\n结合上述不等式，我们可以得到单步条件熵的紧致边界 $$ \\begin{align*} H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) \u0026\\geq H_q\\left(X^{(t-1)} \\mid X^{(t)}\\right) \\\\ \u0026\\geq H_q\\left(X^{(t)} \\mid X^{(t-1)}\\right) + H_q\\left(X^{(t-1)} \\mid X^{(0)}\\right) - H_q\\left(X^{(t)} \\mid X^{(0)}\\right). \\tag{36} \\end{align*} $$ 仅依赖前向轨迹：上下界均只依赖于已知的前向扩散过程 $q(x^{(1⋯T)}∣x^{(0)})$ 解析可计算：无需蒙特卡洛采样，可直接通过概率分布的解析形式计算 紧致性：在准静态极限下（$\\beta \\rightarrow0$），上下界收敛，实现精确计算 B. 对数似然下界 对数似然的下界为\n$$ L \\geq K \\tag{37} $$$$ K = \\int dx^{(0 \\cdots T)} q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ p\\left(x^{(T)}\\right) \\prod_{t=1}^T \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right] \\tag{38} $$ 这里对应正文公式 （11）（12）\nB.1. $p(X^{(T)})$ 的熵 我们可以分离出 $p(X^{(T)})$ 的贡献，并将其重写为熵， $$ K = \\int dx^{(0 \\cdots T)} \\, q\\left(x^{(0 \\cdots T)}\\right) \\sum_{t=1}^T \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right] + \\int dx^{(T)} \\, q\\left(x^{(T)}\\right) \\log p\\left(x^{(T)}\\right) \\tag{40} $$$$ = \\int dx^{(0\\cdots T)} q\\left(x^{(0\\cdots T)}\\right) \\sum_{t=1}^T \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right] + \\int dx^{(T)} q\\left(x^{(T)}\\right) \\log \\pi\\left(x^{(T)}\\right) \\tag{41} $$根据设计（选择或规范化了核与参数，使得每一步的二阶矩保持与 $\\pi$ 相同），相对于 $\\pi(x^{(t)})$ 的交叉熵在我们的扩散核下是常数，并且等于 $p(x^{(T)})$ 的熵。\n因此，\n$$ K = \\sum_{t=1}^T \\int dx^{(0\\cdots T)} q\\left(x^{(0\\cdots T)}\\right) \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)} \\right] - H_q\\left(X^{(T)}\\right). \\tag{43} $$ 最大熵性质：在给定方差的约束下，高斯分布具有最大熵\n交叉熵恒定：若 $q(x^{(t)})$ 与 $\\pi (x^{(t)})$ 具有相同的二阶矩（方差），则：\n$$ -\\int q\\left(x^{(t)}\\right) \\log \\pi\\left(x^{(t)}\\right) \\, dx^{(t)} = -\\int \\pi\\left(x^{(t)}\\right) \\log \\pi\\left(x^{(t)}\\right) \\, dx^{(t)} = H(\\pi) $$ 即：任何具有单位方差的分布与标准高斯 $\\pi$ 的交叉熵都等于 $\\pi$ 的熵\n特别地：当 $t=T$ 时，$q(x^{(T)})=\\pi (x^{(T)})$，此时交叉熵退化为 $\\pi$ 的熵： $$ \\int q\\left(x^{(T)}\\right) \\log \\pi\\left(x^{(T)}\\right) \\, dx^{(T)} = \\int \\pi\\left(x^{(T)}\\right) \\log \\pi\\left(x^{(T)}\\right) \\, dx^{(T)} = -H(\\pi) = -H_p\\left(X^{(T)}\\right) $$ 只要 $q(x^{(t)})$ 与 $\\pi (x^{(t)})$ 具有相同的二阶矩，交叉熵即恒等于 $\\pi$ 的熵，与 $q$ 的具体形式无关。这是扩散模型设计中利用高斯分布最大熵性质的关键技巧。\n核心推导\n设目标分布为标准高斯 $\\pi(x)=N(x;0,I)$，其概率密度为：\n$$ \\pi(x) = (2\\pi)^{-d/2} \\exp\\left(-\\frac{1}{2}x^\\top x\\right) $$ 对数形式为：\n$$ \\log \\pi(x) = -\\frac{d}{2} \\log(2\\pi) - \\frac{1}{2}x^\\top x $$ 关键观察：$log⁡\\pi(x)$ 仅包含常数项和 $x^⊤x$（即二阶矩）。\n交叉熵定义为：\n$$ H(q, \\pi) = -\\int q(x) \\log \\pi(x) \\, dx $$ 所以：\n$$ \\begin{aligned} H(q, \\pi) \u0026= -\\int q(x) \\left[-\\frac{d}{2} \\log(2\\pi) - \\frac{1}{2}x^\\top x\\right] dx \\\\ \u0026= \\frac{d}{2} \\log(2\\pi) \\underbrace{\\int q(x)dx}_{=1} + \\frac{1}{2} \\int q(x)x^\\top x \\, dx \\\\ \u0026= \\frac{d}{2} \\log(2\\pi) + \\frac{1}{2} \\mathbb{E}_q[x^\\top x] \\end{aligned} $$ 同理，$\\pi$ 的熵为：\n$$ H(\\pi) = \\frac{d}{2} \\log(2\\pi) + \\frac{1}{2} \\mathbb{E}_{\\pi}[x^T x] $$ 因此，当 $E_q[x^⊤x]=E_{\\pi}[x^⊤x]$ 时：交叉熵退化为熵\nB.2. 在 t=0 时移除边缘效应 为了避免边缘效应，我们将反向轨迹的最后一步设置为与对应的前向扩散步骤相同， $$ p\\left(x^{(0)} \\mid x^{(1)}\\right) = q\\left(x^{(1)} \\mid x^{(0)}\\right) \\frac{\\pi\\left(x^{(0)}\\right)}{\\pi\\left(x^{(1)}\\right)} = T_{\\pi}\\left(x^{(0)} \\mid x^{(1)}; \\beta_1\\right). \\tag{44} $$ 然后我们利用这种等价性来移除求和中第一步的贡献， $$ \\begin{align*} K = \u0026\\sum_{t=2}^{T} \\int dx^{(0\\cdots T)} q\\left(x^{(0\\cdots T)}\\right) \\log \\left[\\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)}\\right] \\\\ \u0026+ \\int dx^{(0)} dx^{(1)} q\\left(x^{(0)}, x^{(1)}\\right) \\log \\left[\\frac{q\\left(x^{(1)} \\mid x^{(0)}\\right) \\pi\\left(x^{(0)}\\right)}{q\\left(x^{(1)} \\mid x^{(0)}\\right) \\pi\\left(x^{(1)}\\right)}\\right] - H_p\\left(X^{(T)}\\right) \\tag{45} \\end{align*} $$$$ K = \\sum_{t=2}^{T} \\int dx^{(0\\cdots T)} q\\left(x^{(0\\cdots T)}\\right) \\log \\left[\\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}\\right)}\\right] - H_p\\left(X^{(T)}\\right), \\tag{46} $$ 其中我们再次利用了这样一个事实：根据设计，$−∫dx^{(t)}q(x^{(t)})log⁡\\pi(x^{(t)})=H_p(X^{(T)})$ 对所有 $t$ 都是一个常数。\nB.3. 重写后验分布 q(x(t−1)∣x(0)) 由于前向轨迹是一个马尔可夫过程， $$ K = \\sum_{t=2}^{T} \\int dx^{(0 \\cdots T)} \\, q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}, x^{(0)}\\right)} \\right] - H_p\\left(X^{(T)}\\right). \\tag{47} $$ 利用贝叶斯规则将条件概率重写为后验分布形式， $$ K = \\sum_{t=2}^{T} \\int dx^{(0 \\cdots T)} \\, q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}, x^{(0)}\\right)} \\cdot \\frac{q\\left(x^{(t-1)} \\mid x^{(0)}\\right)}{q\\left(x^{(t)} \\mid x^{(0)}\\right)} \\right] - H_p\\left(X^{(T)}\\right). \\tag{48} $$B.4. 用KL散度和熵重写 然后我们认识到一些项是条件熵， $$ \\begin{align*} K = \u0026\\sum_{t=2}^{T} \\int dx^{(0 \\cdots T)} \\, q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}, x^{(0)}\\right)} \\right] \\\\ \u0026+ \\sum_{t=2}^{T} \\left[ H_q\\left(X^{(t)} \\mid X^{(0)}\\right) - H_q\\left(X^{(t-1)} \\mid X^{(0)}\\right) \\right] - H_p\\left(X^{(T)}\\right) \\tag{49} \\end{align*} $$$$ \\begin{align*} K = \u0026\\sum_{t=2}^{T} \\int dx^{(0 \\cdots T)} \\, q\\left(x^{(0 \\cdots T)}\\right) \\log \\left[ \\frac{p\\left(x^{(t-1)} \\mid x^{(t)}\\right)}{q\\left(x^{(t)} \\mid x^{(t-1)}, x^{(0)}\\right)} \\right] \\\\ \u0026+ H_q\\left(X^{(T)} \\mid X^{(0)}\\right) - H_q\\left(X^{(1)} \\mid X^{(0)}\\right) - H_p\\left(X^{(T)}\\right) \\tag{50} \\end{align*} $$ 通过**识别条件熵（公式 49）并利用望远镜级数（公式 50）**的特性，将复杂的求和项简化为仅依赖于初始和最终状态的表达式。这是扩散模型能够高效计算对数似然下界的关键数学技巧。\n最后，我们将概率分布的对数比转换为KL散度， $$ \\begin{align*} K = \u0026-\\sum_{t=2}^{T} \\int dx^{(0)} dx^{(t)} q\\left(x^{(0)}, x^{(t)}\\right) D_{KL}\\left(q\\left(x^{(t-1)} \\mid x^{(t)}, x^{(0)}\\right) \\parallel p\\left(x^{(t-1)} \\mid x^{(t)}\\right)\\right) \\\\ \u0026+ H_q\\left(X^{(T)} \\mid X^{(0)}\\right) - H_q\\left(X^{(1)} \\mid X^{(0)}\\right) - H_p\\left(X^{(T)}\\right). \\tag{51} \\end{align*} $$ 注意：熵项可以解析计算，且给定 $x^{(0)}$ 和 $x^{(t)}$ 时，KL 散度也可以解析计算。\n该公式将复杂的概率计算问题转化为可解析计算的KL散度和熵项。由于扩散过程的前向轨迹已知，所有这些项都可以精确计算，无需蒙特卡洛采样。这是扩散模型区别于其他生成模型（如GAN、VAE）的核心优势。\nC. 扰动高斯转移 我们希望计算 $\\tilde{p}(x^{(t−1)}∣x^{(t)})$。为简化符号表示，令 $\\mu=f_{\\mu}(x^{(t)},t)$，$\\Sigma =f_{\\Sigma}(x^{(t)},t)$，且 $y=x(t−1)$。使用此符号表示， $$ \\tilde{p}(y \\mid x^{(t)}) \\propto p(y \\mid x^{(t)}) r(y) = \\mathcal{N}(y; \\mu, \\Sigma) r(y). \\tag{53} $$ 我们可以将此重写为能量函数的形式，其中 $E_r(y)=−log⁡r(y)$， $$ \\tilde{p}(y \\mid x^{(t)}) \\propto \\exp\\left[-E(y)\\right] \\tag{54} $$$$ E(y) = \\frac{1}{2}(y - \\mu)^T \\Sigma^{-1} (y - \\mu) + E_r(y). \\tag{55} $$ 公式 54 ：扰动后的分布可表示为能量函数 $E(y)$ 的指数形式；能量越低的区域，概率密度越高（玻尔兹曼分布原理）\n公式 55 ：第一项表示原始高斯分布的能量项（二次型）；第二项表示扰动函数 $r(y)$ 对应的能量项\n如果 $E_r(y)$ 相对于 $\\frac{1}{2}(y−μ)^T\\Sigma^{−1}(y−μ)$ 是平滑的，那么我们可以使用其在 $\\mu$ 处的泰勒展开来近似它。一个充分条件是 $E_r(y)$ 的 Hessian 矩阵的特征值处处比 $\\Sigma^{-1}$ 的特征值的模小得多。然后我们有 $$ E_r(y) \\approx E_r(\\mu) + (y-\\mu)g \\tag{56} $$ 其中 $g=\\frac{\\partial E_r(y′)}{\\partial y′} ∣_{y′=μ}$。将此代入完整能量函数， $$ \\begin{align*} E(y) \u0026\\approx \\frac{1}{2}(y - \\mu)^T \\Sigma^{-1} (y - \\mu) + (y - \\mu)^T \\mathbf{g} + \\text{constant} \\tag{57} \\\\ \u0026= \\frac{1}{2} y^T \\Sigma^{-1} y - \\frac{1}{2} y^T \\Sigma^{-1} \\mu - \\frac{1}{2} \\mu^T \\Sigma^{-1} y + \\frac{1}{2} y^T \\Sigma^{-1} \\Sigma \\mathbf{g} + \\frac{1}{2} \\bf{g}^T \\Sigma \\Sigma^{-1} y + \\text{constant} \\tag{58} \\\\ \u0026= \\frac{1}{2} (y - \\mu + \\Sigma \\mathbf{g})^T \\Sigma^{-1} (y - \\mu + \\Sigma \\mathbf{g}) + \\text{constant}. \\tag{59} \\end{align*} $$ 这对应于一个高斯分布， $$ \\tilde{p}(y \\mid x^{(t)}) \\approx \\mathcal{N}(y; \\mu - \\Sigma g, \\Sigma). \\tag{60} $$ 将结果代回原始形式，得到： $$ \\tilde{p}\\left(x^{(t-1)} \\mid x^{(t)}\\right) \\approx \\mathcal{N}\\left(x^{(t-1)}; \\mathbf{f}_{\\mu}\\left(x^{(t)}, t\\right) + \\mathbf{f}_{\\Sigma}\\left(x^{(t)}, t\\right) \\left.\\frac{\\partial \\log r\\left(x^{(t-1)'}\\right)}{\\partial x^{(t-1)'}}\\right|_{x^{(t-1)'} = \\mathbf{f}_{\\mu}\\left(x^{(t)}, t\\right)}, \\mathbf{f}_{\\Sigma}\\left(x^{(t)}, t\\right)\\right). \\quad (61) $$实验细节 用的卷积神经网络，数据集不再进行介绍。\n","date":"2026-01-29T15:55:20+08:00","permalink":"https://ruheyun.github.io/p/diffusion/","title":"Diffusion"},{"content":"关于Hugo的Stack渲染Markdown语言的笔记\n文章模版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +++ date = \u0026#39;2026-01-27\u0026#39; draft = true title = \u0026#39;文章模版\u0026#39; author = \u0026#39;RuHeYun\u0026#39; description = \u0026#39;这是一个副标题\u0026#39; categories = [\u0026#39;Test\u0026#39;, \u0026#39;Hugo\u0026#39;,] tags = [\u0026#39;Post\u0026#39;, \u0026#39;Template\u0026#39;,] slug = \u0026#39;post-template\u0026#39; image = \u0026#39;helena-hertz-wWZzXlDpMog-unsplash.jpg\u0026#39; math = true toc = true comments = true lastmod = \u0026#39;2026-01-28\u0026#39; +++ 参数说明 front matter参数使用的是toml格式\nauthor：作者名\ndraft：草稿状态标识（true，false）\ntitle：文章标题，显示在文章顶部和浏览器标签页\ndescription：文章描述，副标题\ndate：文章发布日期\nslug：自定义文章的URL路径，更改浏览器标签页显示\nimage：封面图片\ncategories：文章分类\ntags：文章标签\nlastmod：最后修改日期\nmath：数学公式支持（true，false）\ntoc：目录显示（true，false）\ncomments：是否开启评论区（true，false）\nweight：文章的权重，越低排的越前，默认不设置按照发布日期排，如果置顶文章通常设置为 1\n说明文档 https://stack.jimmycai.com/guide/\n已经配置了自动更新最后更新时间功能，所以不用再显示定义lastmod参数。\n","date":"2026-01-27T11:32:30+08:00","permalink":"https://ruheyun.github.io/p/post-template/","title":"PostTemplate"},{"content":"网站美化 评论区配置 giscus是利用Github仓库的Discussions来实现的，完全免费。\n使用方法 进入官网，giscus官方网站：https://github.com/giscus/giscus 点击右侧giscus.app，到下面配置界面，先点击最上面giscus，进入安装界面\n可以选择安装到所有仓库，或者之前创建的静态页面仓库，建议安装在静态页面仓库\n返回到配置界面，往下找到配置项 将静态仓库名按照要求填进去\n页面与discussion映射关系：只选择第一个，默认已选择，不用改 Discussion按照推荐选择 特性选择建议 主题自定义\n启用giscus\n上面配置好的信息会出现在这里，下面配置hugo.yaml网站配置文件\n在hugo.yaml中找到comments-\u0026gt;provider，填上giscus，然后找到下面giscus，按照上图中的参数，找到对应名字填进去就行，比如data-repo\u0026lt;-\u0026gt;repo，data-repo-id\u0026lt;-\u0026gt;repoID，需要说明的是配置中有两个主题lightTheme、darkTheme，这个参数对应data-theme，可以通过第6步中主题自定义更改这个参数。 1 2 lightTheme: \u0026#34;light_protanopia\u0026#34; darkTheme: \u0026#34;dark_high_contrast\u0026#34; 先到静态仓库页面，点击settings，右侧向下滑动，找到Features，勾选Discussions 提交代码，评论区配置完成。 网站页脚更改 网站页脚的html文件在以下路径：D:\\Dev\\MyBlog\\blog\\themes\\hugo-theme-stack\\layouts\\partials\\footer\n复制footer.html，放到D:\\Dev\\MyBlog\\blog\\layouts\\partials\\footer文件夹下（前面说过不能改themes内的文件，要把对应文件复制到blog文件夹下进行更改），打开html文件，将内容替换为下面代码\n1 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 {{- $ThemeVersion := \u0026#34;3.33.0\u0026#34; -}} \u0026lt;footer class=\u0026#34;site-footer\u0026#34;\u0026gt; \u0026lt;section class=\u0026#34;copyright\u0026#34;\u0026gt; \u0026amp;copy; {{ if and (.Site.Params.footer.since) (ne .Site.Params.footer.since (int (now.Format \u0026#34;2006\u0026#34;))) }} {{ .Site.Params.footer.since }} - {{ end }} {{ now.Format \u0026#34;2006\u0026#34; }} {{ default .Site.Title .Site.Copyright }} \u0026lt;/section\u0026gt; \u0026lt;section class=\u0026#34;custom-footer-text\u0026#34;\u0026gt; \u0026lt;p style=\u0026#34;text-align: left; font-size: 1.1em; margin: 0.5em 0;\u0026#34;\u0026gt; [ 天天熬夜 \u0026lt;span class=\u0026#34;heartbeat\u0026#34;\u0026gt;❤️\u0026lt;/span\u0026gt; 迟早猝死 ] \u0026lt;/p\u0026gt; \u0026lt;p id=\u0026#34;blog-runtime\u0026#34; style=\u0026#34;text-align: left; font-size: 0.9em; margin: 0.5em 0; color: #888;\u0026#34;\u0026gt; 这个网站已经运行了: \u0026lt;span id=\u0026#34;runtime-value\u0026#34;\u0026gt;Loading...\u0026lt;/span\u0026gt; \u0026lt;span class=\u0026#34;floating-end\u0026#34;\u0026gt;ღゝ◡╹)ノ♡\u0026lt;/span\u0026gt; \u0026lt;/p\u0026gt; \u0026lt;/section\u0026gt; \u0026lt;/footer\u0026gt; \u0026lt;style\u0026gt; .custom-footer-text { font-family: \u0026#39;ZCOOL QingKe HuangYou\u0026#39;, cursive, sans-serif; } .custom-footer-text p:first-child { font-size: 1.2em; /* 可选：加粗 */ /* font-weight: bold; */ } .heartbeat { display: inline-block; animation: heartbeat 1.5s ease-in-out infinite; color: #e74c3c; /* 红色 */ } @keyframes heartbeat { 0% { transform: scale(1); } 15% { transform: scale(1.1); } 30% { transform: scale(1); } 45% { transform: scale(1.1); } 60% { transform: scale(1); } 75% { transform: scale(1.1); } 100% { transform: scale(1); } } .floating-end { display: inline-block; animation: float 3s ease-in-out infinite; } @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } } \u0026lt;/style\u0026gt; \u0026lt;script\u0026gt; document.addEventListener(\u0026#39;DOMContentLoaded\u0026#39;, function() { // 设置博客开始时间 (请替换为你的实际建站日期) const startDate = new Date(\u0026#34;2022-06-18T00:00:00Z\u0026#34;); function updateRuntime() { const now = new Date(); const diffMs = now - startDate; const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); const diffHours = Math.floor((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000); const runtimeStr = `${diffDays} 天 ${diffHours} 小时 ${diffMinutes} 分钟 ${diffSeconds} 秒`; document.getElementById(\u0026#39;runtime-value\u0026#39;).textContent = runtimeStr; } updateRuntime(); setInterval(updateRuntime, 1000); }); \u0026lt;/script\u0026gt; 滚动事件 在页面右下角添加回到顶端和滚动到底部两个按钮。\n首先在D:\\Dev\\MyBlog\\blog\\static\\js路径下新建scroll-button.js，将下面代码复制进去\n1 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 document.addEventListener(\u0026#39;DOMContentLoaded\u0026#39;, function() { // 创建按钮容器 const btnContainer = document.createElement(\u0026#39;div\u0026#39;); btnContainer.id = \u0026#39;scrollButtons\u0026#39;; btnContainer.style.cssText = ` position: fixed; right: 1.5rem; bottom: 1.5rem; z-index: 9999; display: flex; flex-direction: column; gap: 0.75rem; pointer-events: none; `; // 创建「到顶部」按钮 const topBtn = document.createElement(\u0026#39;button\u0026#39;); topBtn.id = \u0026#39;scrollToTop\u0026#39;; topBtn.title = \u0026#39;回到顶部\u0026#39;; topBtn.innerHTML = ` \u0026lt;svg xmlns=\u0026#34;http://www.w3.org/2000/svg\u0026#34; width=\u0026#34;20\u0026#34; height=\u0026#34;20\u0026#34; viewBox=\u0026#34;0 0 24 24\u0026#34; fill=\u0026#34;none\u0026#34; stroke=\u0026#34;currentColor\u0026#34; stroke-width=\u0026#34;2\u0026#34;\u0026gt; \u0026lt;path d=\u0026#34;M12 19V5M5 12l7-7 7 7\u0026#34;/\u0026gt; \u0026lt;/svg\u0026gt; `; topBtn.style.cssText = ` width: 44px; height: 44px; border-radius: 50%; background: var(--card-background); color: var(--card-font-color); border: none; box-shadow: 0 2px 8px rgba(0,0,0,0.15); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; pointer-events: auto; `; topBtn.onmouseover = () =\u0026gt; { topBtn.style.transform = \u0026#39;translateY(-2px)\u0026#39;; topBtn.style.boxShadow = \u0026#39;0 4px 12px rgba(0,0,0,0.2)\u0026#39;; topBtn.style.background = \u0026#39;var(--theme-color)\u0026#39;; topBtn.style.color = \u0026#39;white\u0026#39;; }; topBtn.onmouseout = () =\u0026gt; { topBtn.style.transform = \u0026#39;translateY(0)\u0026#39;; topBtn.style.boxShadow = \u0026#39;0 2px 8px rgba(0,0,0,0.15)\u0026#39;; topBtn.style.background = \u0026#39;var(--card-background)\u0026#39;; topBtn.style.color = \u0026#39;var(--card-font-color)\u0026#39;; }; topBtn.onclick = (e) =\u0026gt; { e.preventDefault(); window.scrollTo({ top: 0, behavior: \u0026#39;smooth\u0026#39; }); }; // 创建「到底部」按钮 const bottomBtn = document.createElement(\u0026#39;button\u0026#39;); bottomBtn.id = \u0026#39;scrollToBottom\u0026#39;; bottomBtn.title = \u0026#39;滚动到底部\u0026#39;; bottomBtn.innerHTML = ` \u0026lt;svg xmlns=\u0026#34;http://www.w3.org/2000/svg\u0026#34; width=\u0026#34;20\u0026#34; height=\u0026#34;20\u0026#34; viewBox=\u0026#34;0 0 24 24\u0026#34; fill=\u0026#34;none\u0026#34; stroke=\u0026#34;currentColor\u0026#34; stroke-width=\u0026#34;2\u0026#34;\u0026gt; \u0026lt;path d=\u0026#34;M12 5v14M5 12l7 7 7-7\u0026#34;/\u0026gt; \u0026lt;/svg\u0026gt; `; bottomBtn.style.cssText = ` width: 44px; height: 44px; border-radius: 50%; background: var(--card-background); color: var(--card-font-color); border: none; box-shadow: 0 2px 8px rgba(0,0,0,0.15); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; pointer-events: auto; `; bottomBtn.onmouseover = () =\u0026gt; { bottomBtn.style.transform = \u0026#39;translateY(2px)\u0026#39;; bottomBtn.style.boxShadow = \u0026#39;0 4px 12px rgba(0,0,0,0.2)\u0026#39;; bottomBtn.style.background = \u0026#39;var(--theme-color)\u0026#39;; bottomBtn.style.color = \u0026#39;white\u0026#39;; }; bottomBtn.onmouseout = () =\u0026gt; { bottomBtn.style.transform = \u0026#39;translateY(0)\u0026#39;; bottomBtn.style.boxShadow = \u0026#39;0 2px 8px rgba(0,0,0,0.15)\u0026#39;; bottomBtn.style.background = \u0026#39;var(--card-background)\u0026#39;; bottomBtn.style.color = \u0026#39;var(--card-font-color)\u0026#39;; }; bottomBtn.onclick = (e) =\u0026gt; { e.preventDefault(); window.scrollTo({ top: document.documentElement.scrollHeight, behavior: \u0026#39;smooth\u0026#39; }); }; // 组装 btnContainer.appendChild(topBtn); btnContainer.appendChild(bottomBtn); document.body.appendChild(btnContainer); // 滚动时动态显示/隐藏（滚动 \u0026gt; 300px 显示） window.addEventListener(\u0026#39;scroll\u0026#39;, () =\u0026gt; { const show = window.pageYOffset \u0026gt; 300; topBtn.style.opacity = show ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; topBtn.style.visibility = show ? \u0026#39;visible\u0026#39; : \u0026#39;hidden\u0026#39;; bottomBtn.style.opacity = show ? \u0026#39;1\u0026#39; : \u0026#39;0\u0026#39;; bottomBtn.style.visibility = show ? \u0026#39;visible\u0026#39; : \u0026#39;hidden\u0026#39;; }); // 接近底部时隐藏「到底部」按钮 window.addEventListener(\u0026#39;scroll\u0026#39;, () =\u0026gt; { const nearBottom = window.innerHeight + window.scrollY \u0026gt;= document.documentElement.scrollHeight - 200; bottomBtn.style.opacity = nearBottom ? \u0026#39;0\u0026#39; : \u0026#39;1\u0026#39;; bottomBtn.style.visibility = nearBottom ? \u0026#39;hidden\u0026#39; : \u0026#39;visible\u0026#39;; }); }); 然后再页脚的html文件里引入这个js文件\n在D:\\Dev\\MyBlog\\blog\\layouts\\partials\\footer路径下的footer.html最下面添加下面一行代码\n1 \u0026lt;script src=\u0026#34;{{ \u0026#34;js/scroll-buttons.js\u0026#34; | relURL }}\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; 动态背景 引入点线漂浮的动态背景\n（1）前往官网particles.js下载Js文件\n（2）前往配置界面微调参数，并下载配置Json文件\ndetect_on设置为window，其余按照自己喜好设置，然后Download。\n（3）将上面下载的两个文件放到D:\\Dev\\MyBlog\\blog\\assets\\background文件夹下\n（4）将themes里的custom.html复制到D:\\Dev\\MyBlog\\blog\\layouts\\partials\\footer下，并添加以下代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 \u0026lt;div id=\u0026#34;particles-js\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;script src=\u0026#39;{{ (resources.Get \u0026#34;background/particles.min.js\u0026#34;).Permalink }}\u0026#39;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; particlesJS.load(\u0026#39;particles-js\u0026#39;, \u0026#39;{{ (resources.Get \u0026#34;background/particlesjs-config.json\u0026#34;).Permalink }}\u0026#39;, function() { console.log(\u0026#39;particles.js loaded - callback\u0026#39;); }); \u0026lt;/script\u0026gt; \u0026lt;style\u0026gt; #particles-js { position: fixed; top: 0; left: 0; width: 100%; z-index: -1; } \u0026lt;/style\u0026gt; 修改默认字体 （1）自行百度谷歌喜欢的字体，然后下载xxx.ttf格式的文件\n（2）把字体文件放到D:\\Dev\\MyBlog\\blog\\assets\\font文件夹下，没有的新建文件夹\n（3）修改D:\\Dev\\MyBlog\\blog\\layouts\\partials\\footer路径下的custom.html文件，加入下面代码\n1 2 3 4 5 6 7 8 9 10 11 \u0026lt;style\u0026gt; @font-face { font-family: \u0026#39;字体名\u0026#39;; src: url(\u0026#39;{{ (resources.Get \u0026#34;font/XXX.ttf\u0026#34;).Permalink }}\u0026#39;) format(\u0026#39;truetype\u0026#39;); } :root { --base-font-family: \u0026#39;字体名\u0026#39;; --code-font-family: \u0026#39;字体名\u0026#39;; } \u0026lt;/style\u0026gt; 字体名：随便起个，统一即可\nXXX.ttf：替换为实际的文件名，带后缀\n自动更改文章最后修改时间 之前写文章，如果要显示最后更新时间，需要在front matter上显示定义lastmod，并且每次改完文章后还需要手动改这个时间，现提供自动更改方案\n（1）更改配置文件hugo.yaml，在最下面加入下面代码，注意缩进问题\n1 2 3 4 5 6 7 8 # 更新时间：优先读取git时间 -\u0026gt; git时间不存在，就读取本地文件修改时间 frontmatter: lastmod: - :git - :fileModTime # 允许获取Git信息\tenableGitInfo: true （2）修改主文件夹下.github/workflows/xxx.yaml文件，在运行 hugo -D 命令的step前加入以下配置\n1 2 3 4 5 6 7 8 9 jobs: deploy: steps: - name: Git Configuration run: | git config --global core.quotePath false git config --global core.autocrlf false git config --global core.safecrlf true git config --global core.ignorecase false （3）更改文章时，会读取git提交时间，或者本地更改时间。\n友链、归档多列显示 修改主文件夹下assets/scss/custom.scss文件(不存在则自行创建)，引入以下css样式代码\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @media (min-width: 1024px) { .article-list--compact { display: grid; // 目前是两列，如需三列，则后面再加一个1fr，以此类推 grid-template-columns: 1fr 1fr; background: none; box-shadow: none; gap: 1rem; article { background: var(--card-background); border: none; box-shadow: var(--shadow-l2); margin-bottom: 8px; margin-right: 8px; border-radius: 16px; } } } macOS风格代码块 (1) 准备一张macOS代码块的图片, 放到主文件夹下的static/icons文件夹下\n(2) 将以下代码复制进assets/scss/custom.scss文件中(不存在则自行创建)\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 .highlight { border-radius: var(--card-border-radius); max-width: 100% !important; margin: 0 !important; box-shadow: var(--shadow-l1) !important; } .highlight:before { content: \u0026#34;\u0026#34;; display: block; background: url(../icons/macOS-code-header.svg) no-repeat 0; background-size: contain; height: 18px; margin-top: -10px; margin-bottom: 10px; } 代码块折叠 (1) 准备一张向下展开图片，放到assets/icons目录下\n(2) 将以下代码复制进layouts/partials/footer/custom.html(文件不存在则自行创建)\n1 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 \u0026lt;style\u0026gt; .highlight { /* 你可以根据需要调整这个高度 */ max-height: 400px; overflow: hidden; } .code-show { max-height: none !important; } .code-more-box { width: 100%; padding-top: 78px; background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0)), to(#fff)); position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; } .code-more-btn { display: block; margin: auto; width: 44px; height: 22px; background: #f0f0f5; border-top-left-radius: 8px; border-top-right-radius: 8px; padding-top: 6px; cursor: pointer; } .code-more-img { cursor: pointer !important; display: block; margin: auto; width: 22px; height: 16px; } \u0026lt;/style\u0026gt; \u0026lt;script\u0026gt; function initCodeMoreBox() { let codeBlocks = document.querySelectorAll(\u0026#34;.highlight\u0026#34;); if (!codeBlocks) { return; } codeBlocks.forEach(codeBlock =\u0026gt; { // 校验是否overflow if (codeBlock.scrollHeight \u0026lt;= codeBlock.clientHeight) { return; } // 元素初始化 // codeMoreBox let codeMoreBox = document.createElement(\u0026#39;div\u0026#39;); codeMoreBox.classList.add(\u0026#39;code-more-box\u0026#39;); // codeMoreBtn let codeMoreBtn = document.createElement(\u0026#39;span\u0026#39;); codeMoreBtn.classList.add(\u0026#39;code-more-btn\u0026#39;); codeMoreBtn.addEventListener(\u0026#39;click\u0026#39;, () =\u0026gt; { codeBlock.classList.add(\u0026#39;code-show\u0026#39;); codeMoreBox.style.display = \u0026#39;none\u0026#39;; // 触发resize事件，重新计算目录位置 window.dispatchEvent(new Event(\u0026#39;resize\u0026#39;)) }) // img let img = document.createElement(\u0026#39;img\u0026#39;); img.classList.add(\u0026#39;code-more-img\u0026#39;); img.src = \u0026#39;{{ (resources.Get \u0026#34;icons/codeMore.png\u0026#34;).Permalink }}\u0026#39; // 元素添加 codeMoreBtn.appendChild(img); codeMoreBox.appendChild(codeMoreBtn); codeBlock.appendChild(codeMoreBox) }) } initCodeMoreBox(); \u0026lt;/script\u0026gt; 本文美化功能大多参考网络上的方法和代码，主要参考美化文章，可以在友链里找到。\n统计浏览数 本网站使用Vercount作为计数器，具体官方源码为Github。\n页脚添加总浏览数 更改D:\\Dev\\MyBlog\\blog\\layouts\\partials\\footer下的footer.html，在最后一行先添加JS引用\n1 2 \u0026lt;!-- vercount计数 --\u0026gt; \u0026lt;script defer src=\u0026#34;https://events.vercount.one/js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; 然后在footer标签内添加下面代码\n1 2 3 4 5 6 7 8 9 \u0026lt;!-- ========== 新增的自定义文本区域 ========== --\u0026gt; \u0026lt;section class=\u0026#34;custom-footer-text\u0026#34;\u0026gt; ... \u0026lt;p style=\u0026#34;font-size: 0.9em;\u0026#34;\u0026gt; 本站总访问量 \u0026lt;span id=\u0026#34;vercount_value_site_pv\u0026#34;\u0026gt;Loading...\u0026lt;/span\u0026gt; 次 总访客数 \u0026lt;span id=\u0026#34;vercount_value_site_uv\u0026#34;\u0026gt;Loading...\u0026lt;/span\u0026gt; 人 \u0026lt;/p\u0026gt; ... \u0026lt;/section\u0026gt; 单篇文章显示阅读量 先在D:\\Dev\\MyBlog\\blog\\assets\\icons下添加下面图标，命名eye.svg\n然后更改D:\\Dev\\MyBlog\\blog\\layouts\\partials\\article\\components下的footer.html，如果没有就去themes对应文件复制过来，然后在footer标签内添加下面代码\n1 2 3 4 5 6 7 8 \u0026lt;!-- 浏览量统计 --\u0026gt; \u0026lt;section\u0026gt; {{ partial \u0026#34;helper/icon\u0026#34; \u0026#34;eye\u0026#34; }} \u0026lt;time class=\u0026#34;article-time--reading\u0026#34;\u0026gt; \u0026lt;!-- vercount统计当前页面浏览数的标签 --\u0026gt; \u0026lt;span id=\u0026#34;vercount_value_page_pv\u0026#34;\u0026gt;loading... \u0026lt;/span\u0026gt;次 \u0026lt;/time\u0026gt; \u0026lt;/section\u0026gt; ","date":"2026-01-27T11:01:58+08:00","image":"https://ruheyun.github.io/p/hugo-beautify/26_21_hu_34b13614ad778c05.jpg","permalink":"https://ruheyun.github.io/p/hugo-beautify/","title":"Hugo网站美化"},{"content":"这篇文章主要是记录了使用Hugo和Stack搭建整个网站的过程，以及部署到Github上，并编写了几个方便使用的Bat脚本。\nHugo说明文档\nStack说明文档\nHugo网站搭建过程 下载Hugo 进入Hugo官网 https://gohugo.io/\n点击上图Github 右侧界面找到Releases，点击进入\n在Assets中找到适合自己电脑的版本\n以Windows为例，下载hugo_extended_0.154.5_windows-amd64.zip 。\n解压出来放到自定义文件夹内 一共三个文件，只有hugo.exe有用\n1 2 3 hugo.exe LICENSE README.md 在该文件夹的地址栏敲打cmd，使用以下命令\n1 2 hugo new site blog # blog：是由Hugo生成的含有一些文件的文件夹，可自定义这个名字 进入由Hugo生成的blog文件夹。\n下载Stack主题 Hugo官网点击Themes 选择自己喜欢的主题，这里以Stack为例，点击Stack，然后点击Download会跳转到该主题的Github页面，按照上面下载Hugo的方式下载最新版主题源码。\n将下载后的主题压缩包解压，文件夹名字去掉版本号，如下图形式，复制到blog文件夹内的themes里\n启动Hugo网站 先将D:\\Dev\\MyBlog文件夹下的hugo.exe，复制到D:\\Dev\\MyBlog\\blog下，然后在该文件夹的地址栏敲打cmd，进入命令行窗口，输入下面命令\n1 hugo server -D 复制图片倒数第二行地址 http://localhost:1313/，去浏览器打开，最基础的网站就搭建好了。\n配置Stack主题 主题文件夹路径为D:\\Dev\\MyBlog\\blog\\themes\\hugo-theme-stack，但是不建议直接改themes内的文件，所以把下图两个重要的文件和文件夹复制到D:\\Dev\\MyBlog\\blog文件夹下\n后续如果有要修改hugo-theme-stack内的文件或文件夹，就在blog文件夹下创建相同路径或文件进行修改，blog文件夹优先级高于hugo-theme-stack文件夹。\n删除blog文件夹下的hugo.toml文件，使用上面复制的hugo.yaml配置文件。\n更改网站名字 1 2 3 4 5 baseurl: # 可先不填 languageCode: en-us theme: hugo-theme-stack # 与对应文件夹名字相同 title: RuHeYun # 自定义 copyright: RuHeYun # 自定义 网站默认为简体中文 1 2 3 DefaultContentLanguage: zh-cn hasCJKLanguage: true 标题和子标题 1 2 3 4 5 6 7 zh-cn: languageName: 简体中文 title: RuHeYun # 自定义 weight: 2 params: sidebar: subtitle: 欢迎来到我的网站！ # 自定义 weight是指在下拉菜单中的位置权重，越靠近0的在上方。\n设置每页显示文章个数 1 2 pagination: pagerSize: 3 # 自定义 网站的图标 1 favicon: /favicon.ico # \u0026#39;/\u0026#39;必须要带 在D:\\Dev\\MyBlog\\blog\\static目录下放图标。\n页脚日期以及文章日期格式 1 2 3 4 5 6 footer: since: 2022 # 自定义 dateFormat: published: 2006-01-02 lastUpdated: 2006-01-02 头像设置 1 2 3 4 5 6 7 sidebar: emoji: 🥰 # 自定义 subtitle: avatar: enabled: true local: true src: img/avatar.png # 自定义 目录为D:\\Dev\\MyBlog\\blog\\assets\\img，所有操作都是在blog内操作，不改themes文件夹内的内容。\n配置评论区 本网站使用giscus评论软件 ，这个功能是基于Github的，因此此部分放到部署到Github后。\n部署到Github 首先要有Github账号，本地电脑安装了Git，后续需要用 git 将代码上传到 github，这部分需要在本地 git 配置密钥与 github 连接，自行学习关于 git 部分内容。\n先创建Github仓库 点击Github头像，点击Repositories，然后点击New创建仓库\n两个仓库要求如下：\n第一个仓库公开，名字必须是你的github名字.github.io。\n第二个仓库隐私，名字随意，比如hugo-code。\n手动部署 先改动hugo.yaml配置文件第一行，将网站网址填进去\n1 baseurl: https://ruheyun.github.io public文件夹是整个网站文件夹经过go语言编译好的包含html文件的文件夹，不包含原始代码。由命令hugo server -D产生的（前面使用过，如果更改了内容就需要重新运行这个命令，更新public文件夹）。\n进入public文件夹，地址为D:\\Dev\\MyBlog\\blog\\public，在地址栏敲cmd，进入命令行窗口，依次输入下面命令\n1 2 3 4 5 6 7 8 9 10 11 12 # 初始化本地仓库 git init # 添加所有新增文件 git add . # 提交到本地仓库 git commit -m \u0026#34;first commit\u0026#34; # 设置本地分支为main git branch -M main # 连接远程仓库，需要本地git与远程github通过密钥连接后才能连接仓库 git remote add origin git@github.com:ruheyun/ruheyun.github.io.git # 将本地仓库推送到远程仓库 git push -u origin main 打开github，到ruheyun.github.io仓库界面\n依次点击Settings-\u0026gt;Pages-\u0026gt;Visit site\n或者直接浏览器输入https://ruheyun.github.io/，成功进入网站。\n自动部署 按照上面手动部署过程，每次改完内容，都需要运行hugo server -D更新public文件夹，然后将public文件夹推送到远程仓库。这里提供自动部署方案。\n生成token 依次点击github头像-\u0026gt;Settings-\u0026gt;Developer settings-\u0026gt;Personal access tokens-\u0026gt;Tokens(classic)-\u0026gt;Generate new token(classic)\n按照图示Note随便写\nExpiration建议按照图示选择，表示token永远有效\nSelect scopes建议按照图示选择\n最后生成的token，要自己建个txt文件保留好，只会在生成的这个时候显示，以后不会再显示具体token值了\n配置token 下一步，将token值配置到上面创建的第二个隐私仓库里。\n首先进入仓库hugo-code页面，依次点击Settings-\u0026gt;Secrets and variables-\u0026gt;Actions-\u0026gt;Repository secrets-\u0026gt;New repository secret\n然后将token值填进去保存为TOKEN，这个名字可自定义。\n配置本地文件 在hugo主文件夹，比如D:\\Dev\\MyBlog\\blog，创建一个.github/workflows/hugo-deploy.yaml文件，将以下内容复制进去，想具体了解更多，可查看Github Action文档\n1 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 name: deploy # 代码提交到main分支时触发github action on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v3 with: hugo-version: \u0026#34;latest\u0026#34; extended: true - name: Build Web run: hugo -D - name: Deploy Web uses: peaceiris/actions-gh-pages@v4 with: PERSONAL_TOKEN: ${{ secrets.你的token变量名 }} EXTERNAL_REPOSITORY: 你的github名/你的仓库名 PUBLISH_BRANCH: main PUBLISH_DIR: ./public commit_message: auto deploy 只需要改动两个地方\n1 2 PERSONAL_TOKEN: ${{ secrets.TOKEN }} EXTERNAL_REPOSITORY: ruheyun/ruheyun.github.io 设置.gitignore文件 1 2 3 4 5 6 7 # 由hugo命令自动生成的文件 public resources .hugo_build.lock # hugo程序 hugo.exe 这个文件放到主文件夹下，在git推送代码时，会忽略上述文件夹和文件。\n推送代码 将所有网站代码推送到hugo-code仓库\n在主文件夹D:\\Dev\\MyBlog\\blog的地址栏输入cmd进入命令行，依次执行下面命令\n1 2 3 4 5 6 7 8 9 10 11 12 # 初始化本地仓库 git init # 添加所有新增文件 git add . # 提交到本地仓库 git commit -m \u0026#34;first commit\u0026#34; # 设置本地分支为main git branch -M main # 连接远程仓库，需要本地git与远程github通过密钥连接后才能连接仓库 git remote add origin git@github.com:ruheyun/hugo-code.git # 将本地仓库推送到远程仓库 git push -u origin main 上传之后会自动部署静态仓库ruheyun.github.io，稍等一会儿刷新网站就可以看到已更新。\n下次更新操作 1 2 3 4 5 6 # 1.更新网站主题代码 # 2.通过 hugo new content post\\myFirstBlog\\index.md 生成新文章页面 git add . git commit -m \u0026#34;first commit0\u0026#34; git remote add origin git@github.com:ruheyun/hugo-code.git git push -u origin main 通过上面两种方式更改代码，只需要依次执行上面代码，将主文件夹内的文件上传到隐私仓库即可，静态仓库会自动部署，不用管。\n一键式脚本 经过上面的自动部署，但仍需敲一些代码，现将这些代码作成bat脚本，不用再输入代码。\nnewpost.bat：新建文章页，需要手动输入文章标题，不要含空格。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @echo off setlocal set /p title=Enter post title (e.g., Markdown Syntax): if \u0026#34;%title%\u0026#34;==\u0026#34;\u0026#34; set title=Untitled Post set \u0026#34;post_path=content\\post\\%title%\\index.md\u0026#34; if exist \u0026#34;%post_path%\u0026#34; ( echo WARNING: Post already exists at %post_path% echo Opening server anyway... ) else ( echo Creating new post: %title% hugo new \u0026#34;content/post/%title%/index.md\u0026#34; ) hugo server -D pause localRun.bat：本地运行代码查看，可不运行。\n1 2 3 4 5 6 @echo off setlocal hugo server -D pause update.bat：将本地代码推送到远程仓库，仓库名自定义。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @echo off setlocal REM 使用 PowerShell 获取当前时间（ISO 格式） for /f \u0026#34;usebackq tokens=*\u0026#34; %%i in (`powershell -Command \u0026#34;Get-Date -Format \u0026#39;yyyy-MM-dd HH:mm:ss\u0026#39;\u0026#34;`) do set \u0026#34;ts=%%i\u0026#34; REM 如果没有提供提交信息，默认使用时间戳 if \u0026#34;%~1\u0026#34;==\u0026#34;\u0026#34; ( set \u0026#34;commit_msg=Update on %ts%\u0026#34; ) else ( set \u0026#34;commit_msg=%~1\u0026#34; ) git add . git commit -m \u0026#34;%commit_msg%\u0026#34; git remote add origin git@github.com:ruheyun/hugo-code.git 2\u0026gt;nul git push -u origin main pause 将上面三个bat文件放到hugo主文件夹下D:\\Dev\\MyBlog\\blog，根据想要的功能，双击对应的bat文件即可。\n","date":"2026-01-26T12:31:44+08:00","image":"https://ruheyun.github.io/p/hugo-construction/hugo-logo-wide.svg","permalink":"https://ruheyun.github.io/p/hugo-construction/","title":"Hugo网站搭建"},{"content":"文章的前言部分，可有可无。\nHello Hugo! 测试github自动部署功能\n名言 “成功不是终点，而失败并不致命：有勇气继续下去才是最重要的。”——温斯顿·丘吉尔 “宁可在独创性上失败，也不要在模仿中成功。”——赫尔曼·梅尔维尔 “成功之路和失败之路几乎是相同的。”——科林·戴维斯 “成功通常属于那些忙于寻找成功的人。”——亨利·大卫·梭罗 “学会从失败中成功。挫折和失败是通往成功最可靠的垫脚石。”——戴尔·卡耐基 三级标题 没有内容了。。。\nhugo文档，必须要有三级标题，才会显示右侧目录\u0026hellip;\n测试是否自动更改最后更新时间\n","date":"2026-01-25T16:51:02+08:00","image":"https://ruheyun.github.io/p/myfirstblog/pawel-czerwinski-8uZPynIu-rQ-unsplash_hu_9e6bcf9cfe9a9448.jpg","permalink":"https://ruheyun.github.io/p/myfirstblog/","title":"MyFirstBlog"},{"content":"Markdown语法 一级标题用：# 标题内容\n多级标题 二级标题用：## 标题内容\n三级标题 三级标题用：### 标题内容\n以此类推，但markdown最多可有六级标题\n字体 字体加粗用：**字体内容**\nhello world！\n字体斜体用：*字体内容*\nhello world！\n字体加粗且斜体用：***字体内容***\nhello world！\n字体删除横杠用：~~字体内容~~\nhello world！\n字体加下划线用：\u0026lt;u\u0026gt;hello world!\u0026lt;/u\u0026gt;\nhello world!\n字体下标表示用：H~2~o\nH2o\n字体上标表示用：n^2^\nn^2^\n字体高亮用：==字体内容==\n==hello world!==\n表情符号 常用表情符号：:smile: :laughing: :dizzy_face: :sob: :cold_sweat: :sweat_smile: :cry: :triumph: :heart_eyes: :relaxed: :sunglasses: :weary:\n:+1: :-1: :100: :clap: :bell: :gift: :question: :bomb: :heart: :coffee: :cyclone: :bow: :kiss: :pray: :sweat_drops: :hankey: :exclamation: :anger:\n:smile: :laughing: :dizzy_face: :sob: :cold_sweat: :sweat_smile: :cry: :triumph: :heart_eyes: :relaxed: :sunglasses: :weary:\n:+1: :-1: :100: :clap: :bell: :gift: :question: :bomb: :heart: :coffee: :cyclone: :bow: :kiss: :pray: :sweat_drops: :hankey: :exclamation: :anger:\n引用 引用内容用：\u0026gt; 内容\n二级引用用：\u0026gt;\u0026gt; 内容\n两次enter键跳出引用\n我的第一篇博客\n二级引用\n分割线 常用的分割线用：---或者***回车即可\n图片 插入本地图片用：![图片名字](图片地址绝对路径)\n插入网络图片用：![图片名字](图片地址图片链接)\n本地地址和网络上图片地址可能会由于本地的更改删除或者网络图片出处的删除，而导致图片无效而显示不出来，建议大家把需要的图片上传到自己创建的图床里。\n超链接 超链接用：[链接名字](链接地址)\n点击跳转到我的主页\n自动链接用：\u0026lt;链接地址url或者邮箱\u0026gt;\nhttps://ruheyun.github.io/\n列表 有序列表用：1. 内容\na b c 无序列表用：- 内容\na b c 表格 插入表格最简单方法，直接鼠标右键选插入\u0026gt;表格即可\n名字 性别 生日 如何 男 2022.6.18 插入表格第二种方式需要用格式：\n|属性|属性|属性|\n|--|--|--|\n|内容|内容|内容|\n名字 性别 生日 如何 男 2022.6.18 代码块 编写代码用：```语言名称回车即可\n1 2 3 4 5 public class HelloWorld { public static void main(String[] args) { System.out.println(\u0026#34;Hello World!\u0026#34;); } } 行内代码用：``两点内书写内容\nHtml Markdown语法，同样支持Html语法，所以如果想要更丰富的格式，则可以借助Html、CSS、JS等实现。\n2022.6.18是我第一天注册博客园开始学习写文章，为了完成属于自己的第一篇博客，我熬夜写到半夜才完成。虽然有很多地方不足，但是我很开心。也希望自己可以在接下来学习过程中坚持写博客，不放弃，希望可以让自己在学习过程中与大家一起讨论，分享总结。最后，祝各位朋友心想事成！\n","date":"2022-06-18T11:35:06+08:00","image":"https://ruheyun.github.io/p/markdown-syntax/markdown-mark_hu_be7b23c2587dcd41.jfif","permalink":"https://ruheyun.github.io/p/markdown-syntax/","title":"Markdown语法"},{"content":"这是Hugo默认生成的文章，本网站已有类似Markdown语法文章，所以不再对此文章进行翻译。\nThis article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\nHeadings The following HTML \u0026lt;h1\u0026gt;—\u0026lt;h6\u0026gt; elements represent six levels of section headings. \u0026lt;h1\u0026gt; is the highest section level while \u0026lt;h6\u0026gt; is the lowest.\nH1 H2 H3 H4 H5 H6 Paragraph Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.\nBlockquote without attribution Tiam, ad mint andaepu dandae nostion secatur sequo quae. Note that you can use Markdown syntax within a blockquote.\nBlockquote with attribution Don\u0026rsquo;t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\nTables Tables aren\u0026rsquo;t part of the core Markdown spec, but Hugo supports supports them out-of-the-box.\nName Age Bob 27 Alice 23 Inline Markdown within tables Italics Bold Code italics bold code A B C D E F Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ultricies, sapien non euismod aliquam, dui ligula tincidunt odio, at accumsan nulla sapien eget ex. Proin eleifend dictum ipsum, non euismod ipsum pulvinar et. Vivamus sollicitudin, quam in pulvinar aliquam, metus elit pretium purus Proin sit amet velit nec enim imperdiet vehicula. Ut bibendum vestibulum quam, eu egestas turpis gravida nec Sed scelerisque nec turpis vel viverra. Vivamus vitae pretium sapien Code Blocks Code block with backticks 1 2 3 4 5 6 7 8 9 10 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block indented with four spaces \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;utf-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block with Hugo\u0026rsquo;s internal highlight shortcode 1 2 3 4 5 6 7 8 9 10 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Diff code block 1 2 3 4 5 [dependencies.bevy] git = \u0026#34;https://github.com/bevyengine/bevy\u0026#34; rev = \u0026#34;11f52b8c72fc3a568e8bb4a4cd1f3eb025ac2e13\u0026#34; - features = [\u0026#34;dynamic\u0026#34;] + features = [\u0026#34;jpeg\u0026#34;, \u0026#34;dynamic\u0026#34;] List Types Ordered List First item Second item Third item Unordered List List item Another item And another item Nested list Fruit Apple Orange Banana Dairy Milk Cheese Other Elements — abbr, sub, sup, kbd, mark GIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL + ALT + Delete to end the session.\nMost salamanders are nocturnal, and hunt for insects, worms, and other small creatures.\nHyperlinked image The above quote is excerpted from Rob Pike\u0026rsquo;s talk during Gopherfest, November 18, 2015.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2019-03-11T00:00:00Z","permalink":"https://ruheyun.github.io/p/markdown-syntax-guide/","title":"Markdown Syntax Guide"},{"content":"这篇文章是对Hugo默认生成的文章的翻译版。\n在 Hugo 项目中，可以通过使用第三方 JavaScript 库来启用数学公式支持。\n在这个例子中，我们将使用 KaTeX\n在 /layouts/partials/math.html 下创建一个 局部模板，命名为math.html。 在该 partial 中引用 Auto-render 扩展，或将这些脚本托管在本地。 像下面这样在你的模板中引入该 partial: 1 2 3 {{ if or .Params.math .Site.Params.math }} {{ partial \u0026#34;math.html\u0026#34; . }} {{ end }} 要全局启用 KaTeX，需在项目配置中将参数 math 设置为 true 要在单个页面启用 KaTeX，需在内容文件中包含参数 math: true 注意： 请参考 支持的 TeX 函数 在线文档\n例子 行内公式: $\\varphi = \\dfrac{1+\\sqrt5}{2}= 1.6180339887…$\n块级公式: $$ \\varphi = 1+\\frac{1} {1+\\frac{1} {1+\\frac{1} {1+\\cdots} } } $$","date":"2019-03-08T00:00:00Z","permalink":"https://ruheyun.github.io/p/math-typesetting/","title":"Math Typesetting"},{"content":"这篇文章是Hugo默认生成的文件，翻译版。\n在 Hugo 项目中，可通过多种方式启用 Emoji 支持。\n可在模板或内联短代码（Inline Shortcodes）中直接调用 emojify 函数。\n如需全局启用 Emoji：在站点配置文件中将 enableEmoji 设为 true，即可在内容文件中直接输入 Emoji 简写代码。例如：\n🙈 :see_no_evil: 🙉 :hear_no_evil: 🙊 :speak_no_evil:\nEmoji 速查表（cheat sheet）是查询简写代码的实用参考资源。\n注意：上述步骤可在 Hugo 中启用 Unicode 标准 Emoji 字符与序列，但实际渲染效果取决于浏览器及操作系统平台。如需自定义 Emoji 样式，可使用第三方 Emoji 字体或指定字体栈，例如：\n1 2 3 .emoji { font-family: Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, Segoe UI Symbol, Android Emoji, EmojiSymbols; } 什么是短代码？ 在 Hugo 中，内联短代码（Inline Shortcodes） 是指可以在文章内容中直接使用的简短标记语法，用于插入动态内容或特殊功能。\n短代码是一种 Hugo 提供的模板功能，允许你在 Markdown 内容中嵌入可重用的代码片段。\n内联短代码的特点： 直接嵌入内容中 - 可以在段落中间使用，不会打断文本流 语法简洁 - 使用花括号 {{ }} 包裹 可传递参数 - 可以接收参数来控制行为 示例： 这是一个段落，中间可以使用 {{\u0026lt; highlight go \u0026gt;}}这样的内联短代码 {{\u0026lt; /highlight \u0026gt;}}。\n或者调用 emoji 函数：{{% emojify \u0026ldquo;:smile:\u0026rdquo; %}}\n当你在内容中写 {{% emojify \u0026ldquo;:smile:\u0026rdquo; %}} 时，Hugo 会去 layouts/shortcodes/ 目录下寻找 emojify.html 模板文件。\n具体操作看本文5.2.3。\n与块级短代码的区别： 内联短代码：在行内使用，不独占一行 块级短代码：单独成块，通常用于插入图片、视频等较大元素 在 Emoji 场景中的使用： {{% emojify \u0026ldquo;:smile:\u0026rdquo; %}} // 会渲染为 😄\n这样你就可以在不启用全局 enableEmoji 的情况下，有选择性地在特定位置使用 Emoji 了。\n但是好像这样做不行，下面是解决方案：\nemojify 不是短代码，而是模板函数 Hugo 的 emojify 是一个模板函数（template function），不是内置短代码。因此以下写法无法直接使用：\n{{% emojify \u0026ldquo;:smile:\u0026rdquo; %}} // 无效（Hugo会报错）\n正确用法 方式 1：全局启用（推荐） 在 hugo.toml/hugo.yaml 中设置：\n1 enableEmoji = true 然后在 Markdown 中直接写：\n1 :smile: # 会自动渲染为 😄 方式 2：在模板文件中使用 在 .html 模板中调用：\n1 {{ emojify \u0026#34;Hello :smile:\u0026#34; }} 方式 3：自定义短代码（如需局部控制） 创建 layouts/shortcodes/emoji.html，下入下面代码： 1 {{ emojify (.Get 0) }} 在 Markdown 中使用：{{% emojify \u0026ldquo;:smile:\u0026rdquo; %}} 会被渲染为 😄 注意：不能更改themes文件夹下的文件，要复制到主文件夹对应文件夹下，如下图：\n总结 方法 是否可行 说明 {{% emojify \u0026ldquo;:smile:\u0026rdquo; %}} ❌ emojify 不是短代码，不能这样用 全局 enableEmoji: true + :smile: ✅ 最简单，推荐 模板中 {{ emojify \u0026quot;...\u0026quot; }} ✅ 适用于主题开发者，不推荐 自定义短代码包装 emojify ✅ 需手动创建短代码文件，推荐 所以文档示例中提到的\u0026quot;Inline Shortcodes\u0026quot;是指可以创建自定义短代码来调用 emojify 函数，而不是 emojify 本身是短代码。\n","date":"2019-03-05T00:00:00Z","image":"https://ruheyun.github.io/p/emoji-support/the-creative-exchange-d2zvqp3fpro-unsplash_hu_25e98f89e1c69204.jpg","permalink":"https://ruheyun.github.io/p/emoji-support/","title":"Emoji 支持"}]