[Sequence Modeling 02] LSTM

Vanilla RNN 的缺陷:为什么我们需要 LSTM? 在上一篇中我们提到,RNN 的核心公式是 $h_t = \tanh(W_{xh} x_t + W_{hh} h_{t-1} + b_h)$。这种设计在处理长序列时会遇到两个工程上的致命问题: 梯度消失与梯度爆炸(Vanishing/Exploding Gradients) 在反向传播计算梯度时,误差需要沿着时间步反向传递。这会导致权重矩阵 $W_{hh}$ 被连乘 $t$ 次。根据线性代数原理,如果 $W_{hh}$ 的最大特征值小于 1,连乘后梯度会呈指数级衰减趋近于 0(梯度消失);如果大于 1,则会指数级放大(梯度爆炸)。梯度消失意味着网络根本无法学习到长距离的依赖关系 信息覆盖(Information Overwrite) RNN 只有一个隐藏状态 $h_t$。在每一个时间步,新的输入 $x_t$ 都会强制与历史信息 $h_{t-1}$ 混合。没有任何机制能够保护早期非常重要但最近没有出现的信息。这就好比一个容量有限的栈,新数据不断涌入,旧数据很快就被冲刷掉了 LSTM 的核心思想:分离状态与引入门控机制 为了解决上述问题,LSTM 将内部状态拆分为两条相互配合的通路,并通过门控信号控制信息如何在通路之间流动。 细胞状态 $c_t$ (Cell State):位于上方的主干通路,负责携带长期记忆。从 $c_{t-1}$ 到 $c_t$ 的更新主要由逐元素乘法和加法构成,因此为梯度跨时间步传播提供了更顺畅的路径。 隐藏状态 $h_t$ (Hidden State):位于下方的输出通路,既参与当前时间步的门控计算,也作为当前时间步的输出,并传递给下一时间步。 门控机制 (Gating Mechanism):将上一时刻的隐藏状态 $h_{t-1}$ 与当前输入 $x_t$ 拼接后,分别计算遗忘门 $f_t$、输入门 $i_t$、输出门 $o_t$ 和候选记忆 $\tilde{c}_t$。其中三个门使用 Sigmoid,将每个维度的控制值限制在 $[0, 1]$;候选记忆使用 $\tanh$ 生成待写入的内容。 一个时间步内部的数据流可以按图中的顺序理解:遗忘门决定保留多少 $c_{t-1}$,输入门决定写入多少候选记忆,二者相加得到新的细胞状态 $c_t$;随后,$c_t$ 经过 $\tanh$ 压缩,并由输出门决定其中多少信息暴露为隐藏状态 $h_t$。 ...

March 16, 2026 · Last updated on August 19, 2026 · 3 min · KKKZOZ

[Sequence Modeling 03] Mamba

要理解 Mamba,我们需要将思维从 Transformer 的“全局注意力”切回到 RNN 的“时序状态机”,但这次,我们要解决 Vanilla RNN 和 LSTM 共同的工程死穴:训练阶段无法并行。 Mamba 的核心目标非常明确:既要拥有 Transformer 级别的高效并行训练能力,又要保持 RNN $O(1)$ 的推理复杂度和无限上下文潜力。 它主要通过整合状态空间模型(State Space Model, SSM)、**选择性机制(Selective Mechanism)和底层硬件优化(Hardware-aware Algorithm)**来实现这一目标。 以下从数学和工程的视角详细拆解 Mamba 架构。 数学基础:从连续到离散的状态空间模型 (SSM) Mamba 的前身是 S4 等状态空间模型。SSM 的思想源于控制论,它假设系统的状态演化可以用一组连续的微分方程来描述: $$h'(t) = A h(t) + B x(t)$$$$y(t) = C h(t)$$ $x(t)$ 是输入。 $h(t)$ 是隐藏状态(类比 RNN 的 $h_t$ 或 LSTM 的 $c_t$)。 $A$ 是状态转移矩阵,描述系统本身的演化规律。 $B$ 和 $C$ 是输入输出投影矩阵。 为了在深度学习中使用(处理离散的 token),必须对连续系统进行离散化(Discretization)。通过引入一个步长参数 $\Delta$(Delta),使用零阶保持(Zero-Order Hold)等数学技巧,上述方程可以转换为离散的递归形式: $$h_t = \bar{A} h_{t-1} + \bar{B} x_t$$$$y_t = C h_t$$其中 $\bar{A} = \exp(\Delta A)$。 你可以看到,离散化后的公式与 Vanilla RNN 非常相似:当前状态 $h_t$ 是前一个状态 $h_{t-1}$ 的线性变换加上当前输入 $x_t$ 的线性变换。因为它是纯线性的(没有 LSTM 那样的 $\tanh$ 或 Sigmoid 阻断),这为后续的数学化简和并行计算奠定了基础。 ...

March 16, 2026 · Last updated on August 19, 2026 · 10 min · KKKZOZ

[Sequence Modeling 04] Linear Attention

linear_attention 是把 Mamba2 的 gating 机制 和 DeltaNet 的 delta rule 结合起来形成的新结构 先简单分析一下 线性注意力是什么 Overview 从 Transformer 视角 标准 causal self-attention 的一层,大致是: $$ Q = XW_Q,\quad K = XW_K,\quad V = XW_V $$$$ A = \text{softmax}(QK^\top + \text{mask}),\quad O = AV $$对第 $t$ 个 token 来说,本质上是在做: $$ o_t = \sum_{i \le t} \alpha_{t,i} v_i $$ O(n, t) 中的每一行是把 attn_map 中的对应行作为权重,对 value 矩阵的行进行线性组合(加权) 也就是:当前 token 用 query 去和历史所有 key 打分,再把历史 value 加权求和。这给了 Transformer 很强的“按内容检索历史”的能力,但代价是训练时通常要处理完整的 token-token 交互矩阵。Mamba2、DeltaNet、Gated DeltaNet 这一类工作,核心目标就是:尽量保留这种“从历史取信息”的能力,但不要每次都真的显式查看全部历史 token。 ...

March 16, 2026 · Last updated on August 19, 2026 · 5 min · KKKZOZ

Triton: Notes and Paradigms

Kernel Paradigm triton 的 kernel 有两种写法: 传统 kernel Persistent Kernel 传统 Kernel grid = (num_tiles,) 每个 block 处理一个 tile → 结束 每个 SM 从 grid 里领一个 work item,做完就退出, CTA 调度由硬件自动完成 Persistent Kernel @triton.jit def kernel(..., n_tiles: tl.constexpr, ...): pid = tl.program_id(0) n_progs = tl.num_programs(0) # grid(0) 启动的 program 数 tile = pid while tile < n_tiles: # 处理 tile 对应的那一块工作 # ... tile += n_progs # 跳到下一个属于自己的 tile 每个 CTA 长期驻留在 SM 上,自己软件调度 work persistent kernel 常见动机: 任务总 tile 数不够多(比如小 batch、小矩阵、很多小 GEMM / MoE / grouped GEMM):普通写法 programs 数 < SM,GPU 吃不满;persistent 让每个 SM 都有活干,并通过循环把剩余工作吃完。 ...

February 27, 2026 · Last updated on August 11, 2026 · 1 min · KKKZOZ

PyTorch Notes

Tensor Operations clamp torch.clamp(或 Tensor 的实例方法 .clamp)是 PyTorch 中用于数值截断(clipping)的常用操作。它的主要作用是将输入张量(Tensor)中的所有元素限制在一个指定的范围内 $[min, max]$。 Example: import torch # Initialize a tensor with values ranging from -10 to 10 data = torch.tensor([-10.0, -5.0, 0.5, 5.0, 10.0]) print(f"Original: {data}") # 1. Clamp between a min and max range [-1, 1] # Values < -1 become -1; Values > 1 become 1 clamped_both = data.clamp(min=-1.0, max=1.0) print(f"Range [-1, 1]: {clamped_both}") # 2. Clamp with only a lower bound (min=-2) # Values < -2 become -2; No upper limit clamped_min = data.clamp(min=-2.0) print(f"Min -2 only: {clamped_min}") # 3. Clamp with only an upper bound (max=3) # Values > 3 become 3; No lower limit clamped_max = data.clamp(max=3.0) print(f"Max 3 only: {clamped_max}") Advanced Indexing x[y] 是 PyTorch(以及 NumPy)中非常强大且灵活的**高级索引(Advanced Indexing)**语法 ...

January 15, 2026 · Last updated on August 11, 2026 · 11 min · KKKZOZ

Server Management

组内有三台 Ubuntu 的服务器是我在管,这里记录一些常用操作 创建用户相关 sudo adduser [username] # 查看一个用户所属的所有组 groups [username] # 查看一个组里面有哪些用户 getent group groupname # 创建组 sudo groupadd <groupname> # 将一个用户添加到某个组里面 sudo usermod -aG groupname username 硬盘管理相关 # 查看整体使用情况 df -h # 查看某个路径下的文件夹大小(注意不包括文件) du -h -d 1 | sort -hr

January 8, 2026 · Last updated on January 8, 2026 · 1 min · KKKZOZ

Triton: Built-in Tutorial

Background GPU Memory Model SRAM (Static RAM) Located inside the GPU core, it utilizes Registers, L1 Cache, and L2 Cache: Registers — These are tiny, ultra-fast memory locations within each GPU core. Registers store immediate values that a core is actively processing, making them the fastest type of memory. L1 Cache — This is the first-level cache inside a Streaming Multiprocessor (SM). It stores frequently accessed data to speed up calculations and reduce access to slower memory (like DRAM). L2 Cache — This is a larger, second-level cache that is shared across multiple SMs. It helps store and reuse data that might not fit in L1 cache, reducing reliance on external memory (VRAM). HBM Bigger capacity ...

January 7, 2026 · Last updated on August 11, 2026 · 12 min · KKKZOZ

Software Router

记录一下折腾软路由的过程,我主要是用于旁路由 很早之前买了一个电犀牛的 R66s,大三大四还有研一在用,回所后吃灰了一段时间 第一步是刷机,可以从这里获取镜像 刷到内存卡上,然后用网线连接路由器的 LAN 和你的电脑 默认管理后台是 http://192.168.1.1 打开后主要设置网络接口,把软路由 LAN 口的属性固定下来: IP: 一个固定的 IP 网关:实际路由器的 IP DNS:实际路由器的 IP 最重要的一点,记得关闭这个口的 DHCP 设置好后,在 PassWall 或者类似的插件中设置一下,然后把软路由的 LAN 口连接到路由器的 LAN 口就行了 对于要上网的设备来说,还是正常连接路由器,然后手动设置 IP IP: 一个固定的 IP 网关:软路由的 IP DNS:软路由的 IP

January 5, 2026 · Last updated on January 8, 2026 · 1 min · KKKZOZ

Sync Dot Files with Chezmoi

Keeping dotfiles consistent across multiple machines (macOS, Ubuntu, etc.) is a common challenge. Traditionally, tools like GNU Stow were used to symlink files from a repository into $HOME. Today, chezmoi provides a more powerful, template-driven approach that integrates seamlessly with Git and makes managing dotfiles across systems straightforward. This post will walk you through: Installing chezmoi Setting it up on your first machine Committing to a remote repository Applying and syncing your configuration on other hosts Handling OS-specific configuration differences 1. Installing chezmoi On macOS (via Homebrew): ...

October 4, 2025 · Last updated on October 4, 2025 · 3 min · KKKZOZ

Clang on Apple

最近在 macOS 上尝试编译 llama.cpp 的过程中,踩了不少坑。最后的结论其实很简单:在 macOS 上,最稳妥的方案就是直接用系统自带的 Apple Clang。这样几乎不需要额外配置,避免了各种 ABI、SDK 的兼容性问题。 遇到的问题 一开始我用的是 Homebrew 安装的 LLVM/Clang: brew install llvm 然后在 CMake 的 toolchain 或者 preset 里,把编译器指定成了: /opt/homebrew/opt/llvm/bin/clang /opt/homebrew/opt/llvm/bin/clang++ 结果一跑,问题接踵而至: SDK 找不到 链接时提示: ld: library 'System' not found 这是因为 Homebrew 的 clang 默认不会自动找到 macOS SDK,导致 libSystem 等核心库无法链接。 ABI 不兼容 在修复 SDK 之后,又遇到了链接报错: Undefined symbols for architecture arm64: "std::__1::__hash_memory(void const*, unsigned long)", ... 这些符号来自 libc++ 21 的新 ABI(Homebrew 的 LLVM),但链接时却跑去用了 Apple SDK 里的老版本 libc++。结果头文件和库的版本不一致,出现了典型的 ABI mismatch。 ...

September 12, 2025 · Last updated on September 12, 2025 · 1 min · KKKZOZ

Git Essentials

Essential Understandings about Git. Basic Concept Working Directory & Staging Area & Branch Working Directory 是你当前正在进行工作的、实实在在的磁盘文件集合 可以是“干净的”,即与仓库中某个版本完全一致;也可以是“脏的”,即包含了修改过或未跟踪的文件 Staging Area 是一个临时区域,用于保存即将提交到版本库的文件快照 通过 git add 命令将工作目录中的修改添加到暂存区 Branch 是 Git 中用于并行开发的核心概念 每个分支都是一个独立的开发线,可以在上面进行修改而不影响其他分支 Remote & Upstream Remote 是指你本地仓库关联的远程 Git 仓库的引用。 # 添加 remote git remote add origin https://github.com/user/repo.git # 添加多个 remote git remote add upstream https://github.com/original/repo.git git remote add fork https://github.com/your-fork/repo.git # 删除 remote git remote remove origin # 重命名 remote git remote rename origin github Upstream 是指本地分支跟踪的远程分支,建立了"上下游"关系。 ...

August 8, 2025 · Last updated on September 1, 2025 · 12 min · KKKZOZ

VS Code Essentials

Essential Understandings about VSCode. This post will continue to update to cover every major update of VSCode. Concepts Workspace VSCode 的工作区有两种: 单文件夹工作区 (Single-Folder Workspace) 这是最常见、最简单的一种。当你使用 File -> Open Folder 打开一个文件夹时,这个文件夹就成为了你的当前工作区。VSCode 的所有操作和配置(比如在 .vscode 目录下的文件)都是相对于这个根文件夹的。 多根工作区 (Multi-root Workspace) 一个多根工作区可以包含多个不同位置的文件夹,但它们都在同一个 VSCode 窗口中管理。 场景:想象一个复杂的项目,它的前端代码在一个仓库(比如 my-webapp),后端代码在另一个完全独立的仓库(比如 my-api-server)。你希望同时能看到并编辑这两个项目的代码。 操作: 先打开其中一个文件夹(例如 my-webapp)。 然后点击 File -> Add Folder to Workspace,并选择 my-api-server. 此时文件浏览器里会同时出现这两个文件夹。 最后,点击 File -> Save Workspace As..., VSCode 会创建一个后缀为 .code-workspace 的文件。 以后只需要直接打开这个 .code-workspace 文件,就能恢复包含多个项目文件夹的工作环境。 总结:所以,“工作区”是你当前在 VSCode 中的项目上下文。它可以是一个简单的文件夹,也可以是一个由 .code-workspace 文件定义的、包含多个文件夹的集合。 ...

August 6, 2025 · Last updated on August 11, 2026 · 4 min · KKKZOZ