<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds/rss-style.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Qi</title>
        <link>https://qi7876.github.io/</link>
        <description>Qi's blog</description>
        <lastBuildDate>Wed, 07 Oct 2026 05:23:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>Astro-Theme-Retypeset with Feed for Node.js</generator>
        <language>en</language>
        <copyright>Copyright © 2026 qi7876</copyright>
        <atom:link href="https://qi7876.github.io/rss.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[My Undergraduate Journey]]></title>
            <link>https://qi7876.github.io/posts/my-undergraduate-journey/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/my-undergraduate-journey/</guid>
            <pubDate>Sat, 01 May 2027 00:00:00 GMT</pubDate>
            <description><![CDATA[经过两三年的探索，大概知道了自己的方向：Multimodal LLMs, Agentic AI, and ML Systems 然后反思了一...]]></description>
            <content:encoded><![CDATA[<p>经过两三年的探索，大概知道了自己的方向：Multimodal LLMs, Agentic AI, and ML Systems</p>
<p>然后反思了一下自身的状态：对计算机系统、深度学习系统一知半解，没有形成完整的系统思维，实践和工程能力一般。在这种状态下，当然可以继续做科研，用 Agent 水出一些东西，但不该这样，没什么意义。这个时代不缺 slop，没有好的 taste 的工作比比皆是，如果我就靠水论文度过接下来的几年，然后找个差不多的工作，继续水，那我感觉这样的人生没什么意思。</p>
<p>所以，决定在博士入学前完整系统的补全知识体系，计划放在文末。</p>
<h2>????-??</h2>
<p>已经想不起来我具体是什么时候学了这些</p>
<p>计算机通识：大一上自己摸索，因为初中后就接触过 python，配合着 ChatGPT 上手还是很快的，这个时期主要在折腾网络、linux 服务器这些东西</p>
<p>李沐的 Deep Learning 书：大概是大一下，只学了一部分</p>
<p>missing semester：大一下的暑假</p>
<p>吴恩达的 AI 系列：大二下，只学了部分课程</p>
<p>CS61A：什么时候开始学已经想不起来了，貌似是大二上</p>
<p>CTF：大二上</p>
<p>单片机：大一下的工创，顺便实践了 C 语言</p>
<p>计算机网络：似乎是大二下，惭愧没有认真听讲，但是实验还是认真做了，后面有时间了再补</p>
<p>数据库系统实验：非常惭愧，老师是工业界出来的，工程能力很强，但是我又没好好听课，项目也是糊弄的</p>
<p>操作系统：大三上，惭愧没有认真听讲，实验也没认真做，拿 AI 糊弄过去了，后面有时间了再补</p>
<p>还有一些零零散散的内容，比如 C 语言等等</p>
<h2>2026-06</h2>
<p>学完了 CS106L，感受是 C++ 的历史包袱实在是太重了</p>
<p>准备学习 CSAPP，看了 intro</p>
<p>开始准备夏令营</p>
<h2>2026-07</h2>
<p>继续忙夏令营，顺便在北京玩了几天</p>
<p>然后开始 nips 的 rebuttal，结束后继续学 CS61A</p>
<h2>2026-08</h2>
<p>结束了 CS61A，前前后后学了 2 年，终于断断续续的学完了</p>
<p>回家继续推进科研，然后度过最后 10 来天暑假假期</p>
<h2>2026-09</h2>
<p>学了目前软件工程的一些实践，日常多用用吧，不过有些最佳实践也有很多批评的声音，还是得灵活一点。</p>
<p>24 号，the book 看到第 17 章了，加油，争取国庆前结束吧，把 final project 做了然后开始准备软工实验，后面就专注 CS61B 和 CSAPP</p>
<p>25 号早晨 nips 出结果，没中，难受了一天，不想工作，痛定思痛。AC 你做人真的可以的，你做过 benchmark 不，最近几年的工作有几个给了 IAA，我做的是 Open ended 问题你告诉我怎么给 IAA，4 分 5 分审稿人一笔带过，2 分 AI 审稿哥有事实错误，你就要看就要信，自己没脑子是不是，你真做过 benchmark 能看不出来他说的是垃圾？rebuttal 里所有问题都解释了，2 分哥从头到尾连个回复都没有，最后 final meta review 说没解决 concern，我祝你全家长寿幸福安康啊。</p>
<p>29 号，the book 看到第 20 章了，最长信息量也最大的一章，加油，然后今天调整了一下计划清单</p>
<h2>2026-10</h2>
<p>1 号，the book 还剩最后一小节就到了 final project，然后又调整了一下课程清单</p>
<p><img src="https://qi7876.github.io/_astro/rustlings.BZM8wPjz_Z1enfni.webp" alt="rustlings" /></p>
<p>the book 的正文部分结束了！rustlings也同步做完了！开启最后的 project！</p>
<p>2 号，结束了 the book，开始做上周 CS61B 的作业</p>
<p>3 号，状态不是很好，整理了一些资料，然后推进了点 CS61B</p>
<p>4 号，出去爬山了</p>
<p>5 号，CS61B 同步进度了，今天还尝试了使用 Jujustu colocated with Git，真的太好用了，比 Git 的 mental model 要简单很多（Git 的 stash 机制很反人类，staging area / index 也同样有些多余，jj 直接让 commit 作为 workspace，消除了这些复杂度），概念上也消除了 Git 瞎起名带来的误解（比如 branch，实际上只是个 reference，Git 使用 branch 让人很容易误解成是从 main 分叉出的一整条 commit 链，而在 jj 中，作者使用 bookmark 来指代）</p>
<p>6 号，推进 CSAPP 105 / 1076，明天准备继续推进科研了</p>
<h2>Plan</h2>
<ul>
<li>大四上
<ul>
<li>[ ] !!! CS61B</li>
<li>[ ] !!! CSAPP Part 1 + 2 w/o Chapter 4 Processor Architecture</li>
<li>[x] ! The rust programming language</li>
<li>[ ] !! 软件工程实验课</li>
</ul>
</li>
<li>寒假
<ul>
<li>[ ] !!! CSAPP Part 3</li>
<li>[ ] !!! CS336</li>
<li>[ ] !! OSTEP/xv6</li>
</ul>
</li>
<li>大四下 + Gap Summer
<ul>
<li>[ ] !!! CS149</li>
<li>[ ] !!! MIT 6.5840</li>
<li>[ ] !! PMPP</li>
<li>[ ] !! Modern GPU Programming For MLSys</li>
<li>[ ] ! GPU Mode</li>
</ul>
</li>
</ul>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Rsut中的async时间漂移]]></title>
            <link>https://qi7876.github.io/posts/async-time-drift-in-rust/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/async-time-drift-in-rust/</guid>
            <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[有一个简单的异步程序 此时的输出为 如果我们改变一下 join! 中的两个 tx 的顺序 这时的输出变成了 这很好理解，因为 join! 是...]]></description>
            <content:encoded><![CDATA[<p>有一个简单的异步程序</p>
<pre><code>use std::time::Duration;

fn main() {
    trpl::block_on(async {
        let (tx0, mut rx) = trpl::channel();
        let tx1 = tx0.clone();

        let tx0_fut = async move {
            let vals = vec![
                String::from("tx0: 0"),
                String::from("tx0: 1"),
                String::from("tx0: 2"),
                String::from("tx0: 3"),
            ];

            for val in vals {
                tx0.send(val).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        let tx1_fut = async move {
            let vals = vec![
                String::from("tx1: 0"),
                String::from("tx1: 1"),
                String::from("tx1: 2"),
                String::from("tx1: 3"),
            ];

            for val in vals {
                tx1.send(val).unwrap();
                trpl::sleep(Duration::from_millis(1500)).await;
            }
        };

        let rx_fut = async {
            while let Some(value) = rx.recv().await {
                println!("{value}");
            }
        };

        trpl::join!(tx0_fut, tx1_fut, rx_fut);
    });
}
</code></pre>
<p>此时的输出为</p>
<pre><code>tx0: 0
tx1: 0
tx0: 1
tx0: 2
tx1: 1
tx0: 3
tx1: 2
tx1: 3
</code></pre>
<p>如果我们改变一下 <code>join!</code> 中的两个 tx 的顺序</p>
<pre><code>trpl::join!(tx1_fut, tx0_fut, rx_fut);
</code></pre>
<p>这时的输出变成了</p>
<pre><code>tx1: 0
tx0: 0
tx0: 1
tx0: 2
tx1: 1
tx0: 3
tx1: 2
tx1: 3
</code></pre>
<p>这很好理解，因为 <code>join!</code> 是有调度顺序的，但是为什么只有前两个输出的顺序变了，1500ms 时的两个输出顺序却保持不变，一直是 tx1 在前</p>
<pre><code>tx1: 1
tx0: 3
</code></pre>
<p>因为程序中出现了隐藏的时间开销，让 tx0 的调度落后了。这里程序中写了</p>
<pre><code>trpl::sleep(Duration::from_millis(500)).await;
</code></pre>
<p>但这只能保证某个 future 至少 500ms 后才能被再次 poll，并不能保证周期就是 500ms。实际上每次被 poll 都会有 do something+ 调度耗时的 time drift，最终导致 tx0 落后于 tx1。</p>
<p>我们将 500ms 缩短至 499ms，这时再交换就会发生 1500ms 处的变化了，当然这个和个人机器有关，可能无法稳定复现。</p>
<p>我们直接测出具体时间：</p>
<pre><code>use std::time::{Duration, Instant};

fn main() {
    trpl::block_on(async {
        let start = Instant::now();
        let (tx0, mut rx) = trpl::channel();
        let tx1 = tx0.clone();

        let tx0_fut = async move {
            let vals = vec![
                String::from("tx0: 0"),
                String::from("tx0: 1"),
                String::from("tx0: 2"),
                String::from("tx0: 3"),
            ];

            for val in vals {
                println!("{:?}: tx0 sending {val}", start.elapsed());
                tx0.send(val).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        let tx1_fut = async move {
            let vals = vec![
                String::from("tx1: 0"),
                String::from("tx1: 1"),
                String::from("tx1: 2"),
                String::from("tx1: 3"),
            ];

            for val in vals {
                println!("{:?}: tx1 sending {val}", start.elapsed());
                tx1.send(val).unwrap();
                trpl::sleep(Duration::from_millis(1500)).await;
            }
        };

        let rx_fut = async {
            while let Some(value) = rx.recv().await {
                println!("rx: {value}");
            }
        };

        trpl::join!(tx0_fut, tx1_fut, rx_fut);
    });
}

</code></pre>
<p>输出</p>
<pre><code>// tx0, tx1
117.833µs: tx0 sending tx0: 0
234.125µs: tx1 sending tx1: 0
rx: tx0: 0
rx: tx1: 0
502.381333ms: tx0 sending tx0: 1
rx: tx0: 1
1.004606875s: tx0 sending tx0: 2
rx: tx0: 2
1.501925375s: tx1 sending tx1: 1
rx: tx1: 1
1.505311083s: tx0 sending tx0: 3
rx: tx0: 3
3.004003375s: tx1 sending tx1: 2
rx: tx1: 2
4.506329s: tx1 sending tx1: 3
rx: tx1: 3

// tx1, tx0
143.708µs: tx1 sending tx1: 0
301µs: tx0 sending tx0: 0
rx: tx1: 0
rx: tx0: 0
502.448416ms: tx0 sending tx0: 1
rx: tx0: 1
1.004695875s: tx0 sending tx0: 2
rx: tx0: 2
1.502794666s: tx1 sending tx1: 1
rx: tx1: 1
1.506181166s: tx0 sending tx0: 3
rx: tx0: 3
3.005453375s: tx1 sending tx1: 2
rx: tx1: 2
4.507735583s: tx1 sending tx1: 3
rx: tx1: 3
</code></pre>
<p>所以，如果有固定周期的需求，应该使用 <code>interval</code> 而不是直接加一个 Duration</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Software Engineering]]></title>
            <link>https://qi7876.github.io/posts/software-engineer/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/software-engineer/</guid>
            <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[https://github.com/qi7876/dotfiles/blob/main/AGENTS.md 这是一些现代软件工程相关知识...]]></description>
            <content:encoded><![CDATA[<p>https://github.com/qi7876/dotfiles/blob/main/AGENTS.md</p>
<p>这是一些现代软件工程相关知识，基本是最佳实践。</p>
<p>如文件名所示，我也把这些内容用作 <code>AGENTS.md</code></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[生产力]]></title>
            <link>https://qi7876.github.io/posts/productivity/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/productivity/</guid>
            <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[管理结果而非任务，整个项目从粗到细分为Goal、Milestone、Task 管理结果：明确要解决的问题和验收条件 滚动规划：Goal拆成可...]]></description>
            <content:encoded><![CDATA[<h2>工作原则</h2>
<p>管理结果而非任务，整个项目从粗到细分为Goal、Milestone、Task</p>
<ol>
<li>管理结果：明确要解决的问题和验收条件</li>
<li>滚动规划：Goal拆成可验收的 milestone，再拆成Task；只详细规划最近一两周</li>
<li>优先验证风险：先解决关键未知问题，减少走偏的风险</li>
<li>任务可执行：普通任务尽量在几小时到一两天内完成；复杂工作拆分，未知问题先实验</li>
<li>单人专注、多人并行：每人一个主要任务，只有在等待时才可推进一个副任务；优先解决阻塞其他人进展的任务</li>
<li>依据证据调整：完成后留下结果与结论，负结果同样有价值，证据不足时谨慎下结论</li>
</ol>
<h2>GitHub Projects</h2>
<p>将Goal、Milestone、Task对应起来：</p>
<ol>
<li>Goal：同验收条件一起记录在README中</li>
<li>Milestone：直接使用自带的Milestone管理，可关联Issue (Task)；在README中记录当前Milestone以及验收条件；验收完成后关闭</li>
<li>Task：以Issue的形式存在，写清楚目标和验收条件，可按需补充依赖、风险等其他信息，然后在评论中持续补充进展、结果、结论、重要决定等信息；验收完成后关闭，取消任务注明原因</li>
</ol>
<p>可使用Todo → In Progress → Done三阶段的看板来管理Task</p>
<h2>OODA</h2>
<p>完成Task、Milestone后进行OODA</p>
<ol>
<li>观察（Observe）：有哪些结果、阻塞和新信息？</li>
<li>理解（Orient）：目标和假设还成立吗？最大风险是什么？</li>
<li>决策（Decide）：继续、调整或停止什么？下一步最重要的是什么？</li>
<li>行动（Act）：更新任务、负责人和范围，开始执行</li>
</ol>
<p>关键结果和阻塞及时异步更新，需要共同判断时再讨论。里程碑结束时验收成果；定期清理失去价值的待办，复盘只改一两项具体问题。</p>
<p>只保留帮助决策与协作的记录，避免重复维护任务清单、日报和周报。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Attention sinks]]></title>
            <link>https://qi7876.github.io/posts/attention-sinks/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/attention-sinks/</guid>
            <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[2026-09-25：添加了一些科研笔记，最开始的部分可能有一些错误理解，后面整理一下 Attention sinks 现象最早被发现于 L...]]></description>
            <content:encoded><![CDATA[<p>2026-09-25：添加了一些科研笔记，最开始的部分可能有一些错误理解，后面整理一下</p>
<p>Attention sinks 现象最早被发现于 LLM 中，后续被延伸到了 Image 和 Video MLLM 中，我们来依次介绍。</p>
<h2>Attention sink</h2>
<h3>LLM</h3>
<p>首先是 LLM 中的 Attention sink，原论文：Efficient Streaming Language Models with Attention Sinks</p>
<p><strong>问题</strong>：模型进行多轮对话时，文本长度超过预训练时的文本长度，使用 Dense Attention 造成模型性能迅速下降</p>
<p><strong>当前的工作</strong>：</p>
<ol>
<li>
<p>改为 Window Attention，持续复用 KV，但当文本流的前几个 token 超出 window 后，模型的 perplexity 会暴增</p>
</li>
<li>
<p>改为 Sliding Window，每次都重新计算 KV，可以保持 perplexity 但计算量大</p>
</li>
</ol>
<p><strong>motivation</strong>：能否既能复用 KV，又能保持低 perplexity？</p>
<p><strong>method</strong>：保留前几个 attention sink token，再将后续的 token 换为最新的 token，既能复用 KV 加速计算，又能保持低 perplexity，基于此提出 StreamingLLM</p>
<p>Attention sink 实际上是模型在训练过程中自发产生的一个现象，文章中作者将原因归为某些 token 不需要从其他 token 获取信息，但是 softmax 后的 attention score 需要和为 1，因此最初的几个 token 由于能被后续所有 q 看见就被用来吸收多余的 attention。作者后续还在实验中发现，这几个 attention sink token 的语意信息不太重要，替换成几个换行符也没问题。作者还测试了加入一个假的 zero sink token 来训练，有帮助但没完全解决问题，另一个是加入 Learnable Sink Token，效果很好。</p>
<p>另一方面是位置编码，window 内的 token 每次更新时，都要映射回连续的位置编码，否则会存在 position gap，并且可能超过模型见过的 position 范围，所以每次都重新计算了带新位置信息的 K，V 由于本身就不需要加位置编码所以可以直接复用</p>
<p>Window Attention 的 perplexity 非常高，究其原因是训练和推理不一致，Windows Attention 在去除前几个 token 后，复用 KV 中 attention sink 消失了，导致 attention 被迫流向其他 token，和训练时的分布差别过大，导致性能下降，Sliding Window 因为每次都重新计算 KV 所以巧合的保持了 attention sink，StreamingLLM 保留前几个 token，然后复用 KV，也保留下来了 attention sink，让训练和推理保持一致</p>
<h3>Image MLLM</h3>
<p>在非 unified multimodal model 中，视觉信息的处理流程大致分为两大块：</p>
<ol>
<li>
<p>ViT Encoder</p>
</li>
<li>
<p>Decoder</p>
</li>
</ol>
<h4>ViT Encoder</h4>
<p>论文：To Sink or Not to Sink: Visual Information Pathways in Large Vision-Language Models</p>
<p>ViT Encoder 将图片先转为 patches，然后再转为和 text embedding 相同维度的 token sequence，这其中也涉及到了 attention，所以同样有 softmax 后的 attention score 和为 1 的限制。</p>
<p>但是，ViT Encoder 中，使用的是 bidirectionnal attention，因此不像 LLM 中的 attention sink 多发生在前几个 token，ViT Encoder 中的 attention sink 主要发生在 high-norm tokens 上，这些 token 最后可能会承载 global representation</p>
<h4>Decoder</h4>
<p>论文：See What You Are Told: Visual Attention Sink in Large Multimodal Models</p>
<p>这篇论文发现 decoder 阶段有些视觉 token 会对很多不同 query 都得到很高的 attention，并且有三个特点：</p>
<ol>
<li>
<p>对应的 patch 不含提问对象</p>
</li>
<li>
<p>对应的 patch 位于背景或边缘</p>
</li>
<li>
<p>删除后不会明显降低模型性能</p>
</li>
</ol>
<p>作者说原因可能是这些 token 的某些维度数值过大，进而在计算注意力时得分高</p>
<p>文章提出这些 sink token 可能损坏性能，并提出 Visual Attention Redistribution（VAR）来将这些过高的 attention 重新分配到其他 token 上，但这个方法仅限于几个 image-centric head，如果直接用到所有 head 上，会导致性能暴跌，也就是说，在模型容忍的范围内进行重新分布是可行的，但是一旦操作过大，会导致训练推理不一致</p>
<p>从 Image MLLM 的 attention sink 工作我们可以得知，某些 attention sink token 可能承担了全局信息，同时有些 token 并没有用，是可以被删去的</p>
<p>ViT Encoder 中的 attention sink token，和 Decoder 中的 attention sink token，是可以相同的</p>
<p>此外，ViT 中还有一个 register token 的概念，专门引入一些 token 来聚合全局或暂时性的信息，也就是承担了 sink token 的功能</p>
<h3>Video MLLM</h3>
<p>Video MLLM 涉及到了 temporal，attention sink 更为复杂，从单帧视角来看，某个 patch 可能获取其他 patch 的高注意，从多帧视角来看，前面帧的某个 patch 可能持续获得了后面帧 patch 的高注意</p>
<p>在高效视频理解工作中，很多 token 会被 pruning 或者 merge，一个直觉的方法是保留高 attention 的 token，但了解过 attention sink 后，我们可以发现这个直觉是错的，高 attention 和高 semantic 并不一定相关，保留过多的 attention sink token 会挤占真正具有 semantic 的 token 空间。在 MCQA 任务上，可能由于 attention sink token 上聚合的全局信息，模型还能保持高性能，但在细粒度任务上就无能为力了</p>
<p>Sink-Token-Aware Pruning for Fine-Grained Video Understanding in Efficient Video LLMs 中提出 Sink-Token-aware Pruning，具有高 sink tendency 的 token 会被降低保留概率</p>
<p>而在另一个方向上，On the Nature of Attention Sink that Shapes Decoding Strategy in MLLMs 中说，attention sink token 会包含全局信息，加以利用可以获得性能提升。这篇文章深入到 KV 分开讨论，做的很前沿，有点没看懂，后面再看看</p>
<h3>总结</h3>
<p>attention sink token 主要有三类：</p>
<ol>
<li>
<p>稳定计算：用于吸收多余的 softmax attention，需要保留以减少训练推理间的不一致</p>
</li>
<li>
<p>聚合信息：通过高注意来聚合全局信息，需要 preserve or compression or enhance</p>
</li>
<li>
<p>挤占注意力：有害，需要 prune 或者 redistribute</p>
</li>
</ol>
<p>在高效视频理解中，我们需要压缩 token，大致就是要：</p>
<ol>
<li>pruning visual 部分只用来吸收多余 softmax attention 的 sink token，将注意力分配到其他 semantic token 上</li>
<li>preserve 和问题相关的 semantic token</li>
<li>merge 聚合全局信息的 token</li>
</ol>
<h2>On the Nature of Attention Sink that Shapes Decoding Strategy in Omni-LLMs</h2>
<p>论文第一版针对 MLLMs，主要研究图像和文本，第二版改成了 Omni-LLMs，会同时处理 video、audio 和 text</p>
<p><strong>问题</strong>：以前的工作通常将 attention sink 理解为用于吸收多余 attention 的结构性 token，或者将具有 sink 的 attention head 视为无效 head。但是，如果 sink token 真的只是在稳定 softmax 计算，那么直接消除 sink attention 应该不会损坏模型性能。文章进一步回答：</p>
<ol>
<li>
<p>在 omni-llm 中如何准确识别 sink token</p>
</li>
<li>
<p>高度 attend sink 的 attention head，就是 redundant head 吗？</p>
</li>
<li>
<p>sink token representation 是作用于所有 token 的 global signal 吗</p>
</li>
</ol>
<p>进一步，提出了 OutRo 来提高 omni-llm 在 video QA 上的性能，并且只有 1.1x 的 decoding 开销</p>
<h3>Q1：找到 sink token</h3>
<p>文章比较了两种判定方式：</p>
<ol>
<li>
<p>LLM 方法：寻找 hidden states 中的 massive activation，也就是数值远大于其他 token 的异常维度</p>
</li>
<li>
<p>VLM 方法：预先确定一些 sink dimensions，再判断每个 token 在这些维度上的归一化数值是否超过阈值</p>
</li>
</ol>
<p>实验发现，VLM 方法直接用在 omni llm 上会出现大量的误判。随着 layer 加深，大部分 token 都会被判断成 sink，其中甚至包含与问题相关的物体 token。原因是这些所谓的 sink dimensions 与普遍存在的 outlier dimensions 高度重合，高数值不一定代表 token 真的承担了 sink 功能。</p>
<p>相比之下，LLM 方法只会找到少量且稳定的 sink token。屏蔽这类 sink token 的关键维度会导致性能崩溃，而屏蔽 VLM 方法找到的其他 token 影响很小。因此，文章后续使用 LLM 方法来识别 sink token。</p>
<p>这也说明，在做 sink-aware token pruning 时，sink token 的定义非常重要。如果判定方式本身会把大量 semantic token 误判成 sink，那么后续的 pruning 或 redistribution 就失去了意义。</p>
<h3>Q2：高度 attend sink 的 attention head 就是 redundant head 吗？</h3>
<p>也并不是</p>
<p>目前的观点认为，由于 sink token 的 v 很小，所以即使 attention score 很大，最终的 o 还是很小，所以这个头基本没有，基于此，提出可以删去这些 redundant head</p>
<p>然而作者通过实验说明，删去高度 attend sink 的 head，既可能出现性能提升，也可能出现性能下跌，所以不能只根据 attention score 就判断一个 head 是否有用，还得继续看 sink token 的 KV</p>
<h3>Q3：sink token 的 representation</h3>
<p>作者先看 K 在看 V</p>
<p>sink token 中 kv 的 norm 都很接近 0，但深入到 dimension 来看，实际上存在一些 dimension，他们的值很大</p>
<p>作者假设就是 K 的这些 dimension 导致了 sink token 现象，然后将这些 dimension 的值清 0（称为 Zero-K）进行测试，发现 sink token 上的 attention score 确实降低了很多，<strong>但是性能也降低了，并且删的 dimension 越多性能降的越多</strong>，这说明我们不能靠简单的删除或者重新分配 attention 来提高性能</p>
<p>然后来到 V，作者将普通 token 经过 attention layer 的输出 O 拆成来自 sink token 和其他普通 token 的两部分</p>
<p>对于来自 sink token 部分，attention score 是普遍较高的，这就是说，这部分会在所有普通 token 的 O 中有贡献，这就形成了 global bias direction</p>
<p>所以，attention sink 可能并不是其他 token 将没用的 attention score 放过来，而是所有其他 token 都需要从这个 token 获取一个公共的 representation</p>
<p>然后作者做了两个实验：</p>
<ol>
<li>
<p>解除 sink token 的 casual mask，让他们吸收更多的 context</p>
</li>
<li>
<p>将 non sink token 朝着 sink token v 的方向旋转</p>
</li>
</ol>
<p>结果都获得了性能提升</p>
<h3>OutRo</h3>
<p>基于前面的发现，文章提出了一个 training-free 的 inference-time 方法 OutRo，分为两块：</p>
<ol>
<li>
<p>ReLU-tanh gating to align non-sink representations with the sink bias direction</p>
</li>
<li>
<p>sink information enhancement via one-time mask relaxation</p>
</li>
</ol>
<h4>gated output rotation</h4>
<p>这部分就是将 non sink token 朝着 sink token v 的方向旋转</p>
<p>首先计算目标方向，先用 LLM 方法找到 sink token，然后计算这些 token value 的平均值，就得到了 sink value direction</p>
<p>然后计算 sink value direction 和 non sink token 输出 O 的 cosine similarity，通过 ReLU–tanh gate，再计算 projection 并 normalize magnitude，只改变方向，不改变大小</p>
<p>这里还有一个参数是 rotation strength，这个参数的大小需要去搜索，并且不同模型得出的参数不同</p>
<h4>sink information enhancement</h4>
<p>这部分很简单，选择一个 layer，给所有 sink token 做 mask relaxation，这个 layer 一般选择模型的 1/7 depth</p>
<h3>实验</h3>
<p>实验显示 OutRo 带来了一些性能提升，但不多，并且有一些开销，作者还试了可以和 contrastive decoding 一块用</p>
<p>更有意思的是用 sink token query 去做 token pruning，这个实验和前面没有什么太大的关联，也没什么解释，作者假设 sink token 的 q 能判断哪些 token 是有价值的，然后通过 attention score 去 prune 掉那些没有价值的 token</p>
<p>结果发现，在 layer 5 保留前 20% 的 token 效果最好，性能还有一点提升，layer3 反而会掉性能。这里和 sink information enhancement 中选 layer 一样，layer 过早时，可能还没有形成结构化的信息</p>
<p>但是关于 query 作者并没有去详细解释，只通过这个实验去验证了一下，value 的作用论证的比较充分。整体来看，sink token 在 query 上判断哪些信息值得聚合，在 value 上将一些 signal 传播给其他 token</p>
<p>对于 query 的研究可能是后续的方向</p>
<h2>Massive Activations in Large Language Models 2024-02</h2>
<p>最早发现 massive activations 的论文，作者研究的是 residual addition 结束后的 hidden state 而不是 attention/mlp 内部的 tensor</p>
<p>某些 token：第一个 token、<code>. \n</code>、and/of，这些没什么语义的词</p>
<p>在某些层：除了最开始和最后几层，往往是在一次 layer computation 后突然出现的，最后下降消失</p>
<p>某些 feature dimension：一般是固定的，非常稀疏</p>
<p>产生了 massive activation，比普通 activation 大了几个数量级</p>
<p><img src="https://qi7876.github.io/_astro/image-20260908203809467.Vbu_87wk_Z2iAhwJ.webp" alt="image-20260908203809467" /></p>
<p><img src="https://qi7876.github.io/_astro/image-20260908203757569.DENI4wDY_MYINX.webp" alt="image-20260908203757569" /></p>
<p>这里要注意，massive activation 和 outlier feature 并不一样，后者指的是某个 feature dimension 在很多 token 上都比较大，作者通过实验发现两个定义下找到的 token 并不重叠</p>
<p>本文给出了一个 massive activation 的粗略的判断方式：</p>
<ol>
<li>某个 token 的某个 activation 绝对值大于 100</li>
<li>某个 token 的某个 activation 绝对值大于此层所有 activations 的中位数的 1000 倍</li>
</ol>
<p>二者需要同时满足，作者说了这个不是理论定义，但是能比较稳定的找到 massive activation</p>
<h3>massive activations 的用处</h3>
<p>作者发现，这些 massive activations 的大小几乎不随着输入 x 而改变，因此作者认为这很像一个 bias</p>
<p>在 LLaMA 7b 上针对 4 个 massive activation 进行了两个实验：</p>
<ol>
<li>将 massive activations 设置为 0：模型出现了明显的性能降级</li>
<li>将 massive activation 设置为它们的 mean：基本没有区别</li>
</ol>
<p>然后作者发现，massive activations 会带来 attention sink。在 attention 计算过程中，带有 massive activation 的 token 得分会略高，然后经过 softmax 后差距被放大，导致它们吸收了大部分的注意力</p>
<p>现代 LLM 中一般会使用 pre norm+RMSNorm，而 RMSNorm 对 outlier 很敏感，收到 massive activation 影响，非 massive activation 的 feature dimension 会被挤压到接近 0，导致这个 token 的 feature 非常稀疏，并且所有带有 massive activations 的 token 都长的差不多。因此，这些带有 massive activations 的 token 的 representation 变成接近固定的，成为了模型学习到的一个隐式的参数</p>
<p><img src="https://qi7876.github.io/_astro/image-20260909113358716.AYA5zhFn_Z1Byswa.webp" alt="image-20260909113358716" /></p>
<p>然后作者分解一个 token 经过 attention 后的输出，可以单独把来自 massive activation token 的那部分拿出来，这部分的值近似是固定的，也就成为了一个 implicit attention bias。所以 26 年的最新工作 OutRo 实际上和这篇工作高度相似，把 massive activations 包装成了 attention sink 又拿出来说了一遍</p>
<p><img src="https://qi7876.github.io/_astro/image-20260909113416715.BZc8X2Xk_Z1emOef.webp" alt="image-20260909113416715" /></p>
<p>那如果我们显式的加入可学习的 KV，用来充当 bias 呢？作者进行了三组实验：</p>
<ol>
<li>普通 GPT-2：作为对照</li>
<li>GPT-2 with [SINK] token：仍然存在 massive activations</li>
<li>GPT-2 with learnable k,v for each attention head：massive activations 消失了，随着 layer 变深数值平滑提高，并且性能也并没有变化</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260909133323631.D7p1KxrR_8PLlI.webp" alt="image-20260909133323631" /></p>
<h3>ViT</h3>
<p>然后作者拓展到了 ViT 中，发现 CLIP 和 DINO 中也有，但是 MAE 中没有，说明 massive activations 在 ViT 中并不是普遍现象。</p>
<p>不过 ViT 中的 massive activations 和 LLM 中的有一些区别：</p>
<ol>
<li>出现的比较晚</li>
<li>发生 massive activation 的 patch token 不固定</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260909134358192.Az6RUik3_1XvhrB.webp" alt="image-20260909134358192" /></p>
<p>但是功能是相同的，同样是充当 bias，上图右下角可以看到实验结果，设置为 0 会让模型性能降级</p>
<p>之前的 ViT 工作中，提出过加入 register token 来聚合 global image information 以提升性能。作者发现加入 register 后，所有 massive activation 都跑到了 register 3 中，并且最后一层的 [CLS] 也将 attention 集中到 register 3 上，这和 LLM 中的现象高度一致</p>
<p>然后作者做了一个更强的干预实验，直接将所有 register 的 feature 改成了 10K ImageNet 上的平均值，结果模型性能不变，这说明 register 本质上提供了 constant bias，而非我们预想的 global image information</p>
<p><img src="https://qi7876.github.io/_astro/image-20260909142735572.DO92AQZ3_hOD3B.webp" alt="image-20260909142735572" /></p>
<h2>Active-Dormant Attention Heads 2024-10</h2>
<p>实验很复杂，结论比较简单。</p>
<ol>
<li>attention sink 的本质是：attention head 进入了 dormant phase，也就是这个头在当前的输入/任务上基本没用，但是 softmax 要求 attention weights 和为 1，因此模型会把大部分 attention 放在一个 value 很小的 token 上，使得最终的 attention output 近似为 0</li>
<li>attention sink 和 value-state drain 是相关的：某个 token 的 value 越小，模型把 attention 放在它上面就越安全，而 attention 越集中在它上面，又会进一步推动其 value 变小，最终系统进入稳定状态，其中不同 query 对 sink token 的 attention 变得很大而且彼此非常接近</li>
</ol>
<h2>When Attention Sink Emerges in Language Models: An Empirical View 2024-10</h2>
<p>直接进入分析部分</p>
<p>从 massive activations 开始看，作者发现这种 token 并没有在后续形成很大的 key，但是在计算 attention 的 qk 点积时，qk 的 cosine similarity 很高，也就产生了 attention sink</p>
<p>然后作者还形式化定义了 attention sink：后续所有能看到 token k 的 query，平均给它多少 attention。然后设定一个阈值来评判</p>
<p>后续对 attention sink 从何而来的分析就没看了</p>
<h2>See What You Are Told 2025-03</h2>
<p>提出 Visual Attention Sink</p>
<p>这篇论文主要研究 text token 到 visual token 的 attention 产生的 sink</p>
<p>作者首先将获得高 attention 的 visual token 分成两类：</p>
<ol>
<li>relevant visual token：和当前 text token 语义相关</li>
<li>irrelevant visual token：固定出现，基本不随 text token 改变</li>
</ol>
<p>然后作者发现，irrelevant visual token 中也有少数固定的 feature dimension 异常大，和 LLM 中的 massive activation 很像，作者记录下了这些特殊的 dimension，然后根据这个现象给出了对 visual sink token 的定义：</p>
<p>对于一个 token x，预先确定一些 sink dimensions，再判断每个 token 的 sink dimension 数值与 RMS（所有维度）的比值是否超过阈值（文章中设置为 20）</p>
<p><img src="https://qi7876.github.io/_astro/image-20260910212348831.cDLnIStZ_sto5u.webp" alt="image-20260910212348831" /></p>
<p>从图中可以看出，这样找出的 visual sink token 的其他维度还是比较正常的，没有像 LLM 中一样基本近似为 0</p>
<p>作者发现把这些 sink token 删掉也没有影响，因此就可以把汇聚在这些 token 上的 attention 重新分配到其他 token 上来提高性能表现</p>
<h2>To Sink or Not to Sink 2025-10</h2>
<p>作者发现，VLM 中的 sink 现象由两部分组成：</p>
<ol>
<li>ViT 传播进来的 sink</li>
<li>LLM 产生的 sink</li>
</ol>
<p>这两类 sink 的性质不同，不能混为一谈</p>
<p>作者给出了 sink 的形式化定义：某个异常指标超过阈值的 token</p>
<p>而这个异常指标可以有多个定义：</p>
<ol>
<li>feature norm</li>
<li>decoding 时，输出 token 对该 token 的平均 attention</li>
<li>massive dimension</li>
<li>这里作者没提到，仅看 visual token 时，还有 text token 对 visual token 的平均注意力</li>
</ol>
<p>然后是作者的选择：</p>
<ol>
<li>ViT sink：使用 feature norm</li>
<li>LLM sink：使用 massive activation</li>
</ol>
<p>然后进入实验部分，作者发现 ViT token norm 越大，在 LLM 中获得的 attention 越大，ViT 并没有规定这个规则，这是 LLM 自身学会的。并且 decoding 阶段 ViT sink 和 llm sink 获得了差不多的 attention。</p>
<p>接着作者发现两种 sink 的 massive dimension 并不相同，因此二者确实不是同一种 sink</p>
<p>然后做了两个实验来观察 ViT sink 中到底存了什么：</p>
<ol>
<li>relevance map：**这里用的是 ViT 中的 attention。**观察一个 sink token 或者 non-sink token，找其他 token 给他的 attention 来画一张图，发现 non-sink token 的 relevance 基本集中在附近局部 patches，而 sink token 的 relevance 分布在很大范围，并且有的头主要聚合 foreground、有的头主要聚合 background。也就是说，non-sink token 聚合局部信息，sink token 聚合粗粒度的全局信息</li>
<li>decoding 时的 word distribution：把 attention 关了，抑制信息交换，然后看 LM Head 的 distribution 输出，发现 sink token 的 distribution 明显偏向画面主体，而 non-sink token 的 distribution 比较平滑，但是画面主体的 frequency 仍然很高</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260911093917389.BEQ6HHLb_2lvqvK.webp" alt="image-20260911093917389" /></p>
<p>然后又做了一个更激进的实验：</p>
<ol>
<li>去掉 sink token，只保留 non-sink token：local tasks 提升性能</li>
<li>去掉 non-sink token，只保留 sink token：global tasks 提升性能</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260911094256105.CuEFlej8_2p2sOV.webp" alt="image-20260911094256105" /></p>
<p>这里可以看到：</p>
<ol>
<li>global 任务下，只保留 sink token 获得了巨大的性能提升，只保留 non-sink token 则是巨大的性能降级</li>
<li>local 任务下，只保留 sink token 是巨大的性能降级，而只保留 non-sink token 只获得了很小的性能提升</li>
<li>mixed 任务下，丢弃任意一种 token 都会有性能下降</li>
</ol>
<h3>改进</h3>
<p>这里作者提出了两个方法：</p>
<ol>
<li>training-free：Sink-to-the-front，在将 visual token 放进 LLM 时，将 sink token 提前到第一位，同时修改 position embedding。这样后续的 token 能更早的吸收 sink token 中的全局信息</li>
<li>training-based：DIYSink，visual tokens 经过 projector 进入 LLM，将这个 projector 改成 dual-mlp，分别处理 sink token 和 non-sink token。接着处理 sink token 和 non-sink token 的权重分配问题：
<ol>
<li>用 CoT 让模型自己思考并分配</li>
<li>再用一个单独的 mlp，只根据 text tokens 来确定 sink token 和 non-sink token 的权重，然后直接把权重加权到两类 token 的 feature 上</li>
</ol>
</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260911114853379.DQ7NEKc__Z2asn1n.webp" alt="image-20260911114853379" /></p>
<h2>The Spike, the Sparse and the Sink 2026-03</h2>
<p>massive activations -&gt; spike token：residual stream 中，少数 token 的少数 channel 上出现远超正常的 activation。起全局作用，带来一个跨层的隐藏表征，作为模型的隐参数而工作</p>
<p>attention sinks -&gt; sink token：某些 token 不管重不重要，都会被大量 attention head 分配异常高的 attention mass（第一个 token，换行符等等）。起局部作用，更像是一个逐 head 的 gating 机制</p>
<p>二者经常同时出现，但这并不是 transformer 的内在属性，而是特定的模型架构和训练选择决定的</p>
<p>作者得到了 3 条核心结论：</p>
<ol>
<li>normalization（pre-norm RMSNorm）在 massive activations 和 attention sinks 间起到重要作用。但通过修改 normalization，可以做到前者消失后者保留</li>
<li>attention sink 受每个 attention head 维度以及训练时上下文长度的影响</li>
<li>两者都可以在不损害模型表现的情况下单独消除</li>
</ol>
<h3>massive activations</h3>
<ol>
<li>
<p>只存在于中间层</p>
</li>
<li>
<p>只存在于少数 channel</p>
</li>
<li>
<p>这些 spike channel 总是一起 spike</p>
</li>
<li>
<p>不同 spike channel 的 magnitude ratio 几乎固定</p>
</li>
<li>
<p>只发生在少量 token</p>
</li>
</ol>
<p><img src="https://qi7876.github.io/_astro/image-20260905090954256.DiIuBNl9_ZsrIDL.webp" alt="逐层统计" /></p>
<p>从某一层开始突然产生，通过 residual stream 传播，到最后突然消失</p>
<p>发现是 mlp 导致的，它们会把某些特殊的 channel 放大几个数量级。只有 token 的 representation 对准一个特殊方向时才会出发大幅放大</p>
<p>position 0 和 delimiter token（句号、逗号、换行）很重要，前者是位置影响的，后者是 token 本身影响的</p>
<p>massive activations 作为一个近似常量，主要用于给 attention 提供一个稳定的 reference 来形成 sink</p>
<h3>attention sink</h3>
<p>massive activations 经过一个 RMSNorm 后，由于少数 channel 有很大的 mass，导致产生了一个接近 constant 的低维数值。当 query 普遍和这个低维数值的 k 对齐时，就产生了 attention sink</p>
<p>为了形成 sink head，模型必须将 non-sink key 和 sink key 拉的很开</p>
<p><img src="https://qi7876.github.io/_astro/image-20260905092100662.DudcaW2A_Zbt0VF.webp" alt="image-20260905092100662" /></p>
<p>而 V 又很小，就导致最终的输出接近 0，于是 attention sink 成为模型自发学习出来的隐式 gated attention（On the Nature of Attention Sink that Shapes Decoding Strategy in Omni-LLMs 又说 V 是公共表示？？）</p>
<p>最后作者还发现 attention sink 是否容易形成主要取决两件事：</p>
<ol>
<li>head dimension 维度越大，sink key 和 non-sink key 越容易分离</li>
<li>训练时包含大量短 context prediction 时，模型倾向于只关注附近的上下文，其他注意力就交给 sink token 来吸收</li>
</ol>
<h2>When sinks help or hurt 2026-04 ECCV 2026 Oral Spotlight</h2>
<p>本文作者主要研究 Visual Token，先分类：</p>
<ol>
<li>V-sink：在 vision encoder 中已经成为 sink</li>
<li>L-sink：在 ViT 输出时是普通 token，进入 LLM 后才逐渐变成 sink</li>
</ol>
<p>然后形式化定义什么是 sink，这里选择了几个已知的 sink dimension，然后直接看 token 在这些 dimension 上的值是不是大于某个阈值，判断出 V-sink 和 L-sink 后，剩下的 token 就叫 ordinary token</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911200421991.CZTVn05W_BDlQ2.webp" alt="image-20260911200421991" /></p>
<p>对于 V-sink，经过 projector 后 feature 发生了混合，而 L-sink 经过某个 mlp 后变成了 sink token</p>
<p>作者发现二者在 hidden-state norm 和 per-token attention 上都很突出，以及二者都携带了 global scene summary</p>
<p>然后作者继续做 attention 干预试验，控制 V-sink 和 rest 的 attention 强度，得到 3 个观察：</p>
<ol>
<li>sink 的好坏和任务有关系：对于细粒度的任务，sink 是坏的，对于粗粒度的任务，sink 是好的</li>
<li>sink 的作用还和 layer 有关：同样的调节，在不同的 layer 深度上出现了截然不同的效果</li>
<li>把 L-sink 单独拿出来调节的效果并不大，所以后面的改进中 L-sink 和 Ordinary 被划成了一类</li>
</ol>
<h3>改进</h3>
<p>然后作者提出 Layer-wise Sink Gating（LSG）</p>
<p>作者用每层最后一个 token 的 hidden state 作为输入，用一个 mlp 来预测下一层应该多看 V-sink 还是 rest，然后直接 NTP</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911202329036.DB1RQyFN_1Amuxc.webp" alt="image-20260911202329036" /></p>
<p>同时在多层使用单独训练的 mlp 可以叠加增益</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911202339118.DZmFVHCZ_Z1NKLl3.webp" alt="image-20260911202339118" /></p>
<h2>A Unifying View of Attention Sinks 2026-06</h2>
<p>这篇论文发现 ViT 中存在两种 sink：</p>
<ol>
<li>NOP：什么都不做，v norm 需要为 0</li>
<li>Broadcast：广播信息，v 正常或较大</li>
</ol>
<p>所以不能只看 attention weight 判断 sink 的作用，还需要看 value 和 residual update</p>
<p>这个工作对 attention sink 的定义是平均累积注意力大于一个阈值</p>
<p>然后来到实验环节，作者在真实 ViT 中找到了这两类 sink token，浅层和中间层更多的是 NOP，深层更多的是 Broadcast</p>
<p>然后作者想到之前的工作通过加入几个 register token 来让模型不要把正常的 patch token 拿去承担聚合全局信息的工作</p>
<p>然后作者在有 register token 的模型上继续实验，发现 sink mass 几乎都迁移到了 register 上，并且这些 register 的角色也不同，大部分是 NOP，小部分是 Broadcast</p>
<h3>改进</h3>
<p>于是作者提出，直接用 gating attention 取代 NOP，然后让 register token 承担 broadcast 的功能</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911204640510.CfZiiuQx_qfo7N.webp" alt="image-20260911204640510" /></p>
<h2>SinkRouter 2026-04</h2>
<p>前面的分析都是研究过的内容，NOP 小 v norm 之类</p>
<h3>改进</h3>
<p>prefilling 没动</p>
<p>首先用 sink 定义，某个 query head 给 BOS 的 attention 大于一个阈值就认为这是 NOP 的</p>
<p>但是这样工程上没法做，所以改成用 query 和 BOS key 的 cosine similarity</p>
<p>对于一个 KV Group，求多个 query 的平均大于一个阈值</p>
<p>如果大于了，就直接令 attention output 为 0</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911211056869.DIi58168_ZWW6Rz.webp" alt="image-20260911211056869" /></p>
<p><img src="https://qi7876.github.io/_astro/image-20260911211116273.-sh7Tf7p_Zc4abN.webp" alt="image-20260911211116273" /></p>
<p>结果是做到了接近无损</p>
<p><img src="https://qi7876.github.io/_astro/image-20260911211151618.DlfVqFy6_ZNpKRX.webp" alt="image-20260911211151618" /></p>
<p>可以看到，上下文越长，加速越明显，但是比较短时基本没啥加速</p>
<h2>方向</h2>
<p>目前有很多工作都研究了 attention sink，并且发现了各种各样的作用然后加以利用，但其实它们研究的对象并不相同：</p>
<ol>
<li>研究的阶段不同：ViT、prefilling、decoding</li>
<li>detetor 不同，也就是对 attention sink 的形式化定义不同
<ol>
<li>attention：某个 key/token 从许多 query 接收异常大的 softmax attention</li>
<li>massive activations：某个 token 的少数 feature 跨数量级的大</li>
<li>high norm：整个 token feature vector 的范数异常大</li>
</ol>
</li>
<li>detector 找到的 token，还能继续细分，以 attention 为例
<ol>
<li>v norm 低的，作为 NOP</li>
<li>v norm 高的，聚合全局信息</li>
</ol>
</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Citation Workflow]]></title>
            <link>https://qi7876.github.io/posts/citation-workflow/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/citation-workflow/</guid>
            <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[做上一个科研工作时，我并没有很注意对引用文献的管理。最近，我稍微了解了一下这方面的内容，才发现居然存在很多需要注意的地方：zotero 中生...]]></description>
            <content:encoded><![CDATA[<p>做上一个科研工作时，我并没有很注意对引用文献的管理。最近，我稍微了解了一下这方面的内容，才发现居然存在很多需要注意的地方：</p>
<ol>
<li>zotero 中生成的 bibtex 条目有时并不是正确的，应该优先使用每个会议官方 paper 列表中生成的 bibtex 条目</li>
<li>arxiv 可以直接在相关页面生成 bibtex 条目</li>
<li>如果论文已经正式发表，应该使用会议生成的 bibtex 条目而不是 arxiv 上的</li>
<li>bib 文件建议长期手动维护，并且最好在下载 paper 时就把顺便把 bibtex 条目加进去，不然后面一个一个找太麻烦了</li>
</ol>
<p>所以我决定放弃 Zotero 了，太重，不如直接用文件夹管理。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Mac使用iPhone USB以太网时配置代理]]></title>
            <link>https://qi7876.github.io/posts/iphone-usb-proxy/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/iphone-usb-proxy/</guid>
            <pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[之前使用 iPhone USB 来连接热点时，Mac 总会无法使用代理。今天稍微 debug 了一下，找出了背后的原因。Mac 上不同网络服...]]></description>
            <content:encoded><![CDATA[<p>之前使用 iPhone USB 来连接热点时，Mac 总会无法使用代理。今天稍微 debug 了一下，找出了背后的原因。</p>
<p>Mac 上不同网络服务的代理设置是分开的，不像 Windows 一样是统一设置的。而我们常只设置 Wi-Fi 的代理，因此使用 iPhone USB 时，其代理配置并没有被设置过，因此也就无法使用代理。</p>
<p>如果只是这样的话，其实也无所谓，我们再单独设置一下 iPhone USB 的代理就行了嘛。但是，逆天的苹果并没有把 iPhone USB 的代理配置放进设置的 GUI 中，明明这是一个如此常用的功能。</p>
<p>我们只能通过命令行来配置。首先列出网络服务，看看是否有 iPhone USB：</p>
<pre><code>networksetup -listallnetworkservices
</code></pre>
<p>然后配置 http、https、socks5 三个代理并打开：</p>
<pre><code>networksetup -setwebproxy "iPhone USB" 127.0.0.1 7890 off
networksetup -setsecurewebproxy "iPhone USB" 127.0.0.1 7890 off
networksetup -setsocksfirewallproxy "iPhone USB" 127.0.0.1 7890 off

networksetup -setwebproxystate "iPhone USB" on
networksetup -setsecurewebproxystate "iPhone USB" on
networksetup -setsocksfirewallproxystate "iPhone USB" on
</code></pre>
<p>最后可以验证一下配置：</p>
<pre><code>networksetup -getwebproxy "iPhone USB"
networksetup -getsecurewebproxy "iPhone USB"
networksetup -getsocksfirewallproxy "iPhone USB"
</code></pre>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Leetcode 0056 merge-intervals]]></title>
            <link>https://qi7876.github.io/posts/leetcode-0056-merge-intervals/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/leetcode-0056-merge-intervals/</guid>
            <pubDate>Sun, 28 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[思路比较简单：按每个区间的起始点进行从小到大的排序 维护一个 res 数组作为结果，循环处理原数组，判断最开始的两个区间能否合并：如果可以合...]]></description>
            <content:encoded><![CDATA[<p>思路比较简单：</p>
<ol>
<li>按每个区间的起始点进行从小到大的排序</li>
<li>维护一个 res 数组作为结果，循环处理原数组，判断最开始的两个区间能否合并：
<ol>
<li>如果可以合并，合并然后将合并后的新区间作为第一个区间继续处理</li>
<li>如果不能合并，将第一个区间加入 res 数组，然后继续处理剩余区间</li>
</ol>
</li>
<li>返回 res</li>
</ol>
<p>根据这个逻辑可以再优化一下，当 res 为空时加入区间，不空时判断 res 的最后一个区间和 intervals 中的当前区间是否能合并，如果可以，则更新 res 的最后一个区间，否则将 intervals 中的当前区间加入到 res 中</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[和导师一起赶Deadline]]></title>
            <link>https://qi7876.github.io/posts/surviving-a-paper-deadline/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/surviving-a-paper-deadline/</guid>
            <pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[2026-05-07 是 NeurIPS 2026 的 Deadline。最终，在一位同学的帮助下，我在 DDL 前一小时左右完成了投稿。讲...]]></description>
            <content:encoded><![CDATA[<p>2026-05-07 是 NeurIPS 2026 的 Deadline。最终，在一位同学的帮助下，我在 DDL 前一小时左右完成了投稿。讲真，我感觉文章内容还有许多能打磨的地方，包括图表，但是时间确实不太够了。实际上我从 5 月 1 日就开始全力写论文了，但是现在来看，这一周我的效率并不高。作为这个月的总结，我又看了一遍陈怡然老师写的两篇公众号文章“和导师一起赶文章死线（Deadline）的十大注意事项（之一/二）”，以及偶然看到的一个学生写论文的经历。</p>
<p>我发现我对论文草稿上的批注也有一些恐惧。但显然，写论文并不是一个线性的、一下就能成功的事，作为一个开放性的问题，我们也能难说什么样的文章是最好的。不过我们可以尽力写出更好的论文，运用 OODA 循环，在快速的反馈迭代中，打磨自己的论文。</p>
<p><a href="https://mp.weixin.qq.com/s?__biz=MzI2NTY2NTU3NQ==&amp;mid=2247483755&amp;idx=1&amp;sn=21c69c10dd131ac4a4c42cd5254b5e2d">和导师一起赶文章死线（Deadline）的十大注意事项</a></p>
<p><a href="https://mp.weixin.qq.com/s?__biz=MzI2NTY2NTU3NQ==&amp;mid=2247483760&amp;idx=1&amp;sn=26dfc9ebbe321c93c683074975d7c3ec">和导师一起赶文章“死线”（Deadline）的十大注意事项（之二）</a></p>
<p><a href="https://www.science.org/content/article/i-hated-writing-until-i-learned-there-s-science-it">I hated writing—until I learned there’s a science to it</a></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[[Note] Super Study Guide: Transformers and Large Language Models]]></title>
            <link>https://qi7876.github.io/posts/super-study-guide/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/super-study-guide/</guid>
            <pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[趁着 NIPS 投稿结束，终于抽出两周时间断断续续给这本书看完了，不过其中有些部分还是稍微跳过了一些，比如最后 preference tun...]]></description>
            <content:encoded><![CDATA[<p>趁着 NIPS 投稿结束，终于抽出两周时间断断续续给这本书看完了，不过其中有些部分还是稍微跳过了一些，比如最后 preference tuning 和 model compression 的内容。</p>
<h2>Foundations</h2>
<p>这一部分的内容比较简单，主要是基础知识。</p>
<h2>Embeddings</h2>
<p>这部分讲了 embedding 相关的知识</p>
<h3>Tokenization</h3>
<p>我们需要将一句话分成 token sequence，这样才能放进 transformer 中。</p>
<p>token 的选取分为不同 level：</p>
<ol>
<li>word：单词作为 token</li>
<li>subword：子词作为 token</li>
<li>character：人类能看懂的最小字符作为 token</li>
<li>byte：byte encoding 作为 token</li>
</ol>
<p>从上到下，词汇表逐渐变小，分出的 token sequence 逐渐变长，out of vocabulary 问题逐渐变小。目前最常用的是 subword 分词，其综合性能最佳。</p>
<p>subword 分词算法中，有 BPE 和 Unigram 两种算法，其中最常用的是 BPE</p>
<h3>Token Embeddings</h3>
<p>得到 token sequence 后，我们需要将 token 转换为 embedding，也就是需要 vocabulary 中每个词到 embedding 的映射。</p>
<p>最简单的是 one hot 编码，但是其 dimension 随 vocabulary size 而增大，同时 embedding 无法反映词间的 similarity</p>
<p>目前常用的是 continuous encoding，也就是每个词的 embedding 的每一个 dimension 都是一个 float，dimension 的数量是固定的，常见的是 CBOW 和 skip gram，训练时常用的加速手段是 negative sampling，GloVe 了解一下就可以</p>
<h3>Document embeddings</h3>
<p>之前我们学习了如何将一句话分为 token sequence，并接着转为 embedding sequence。另一个问题是如何将一个文档转为一个 embedding。这里只给了 BOW、TF-IDF 这两个传统的启发式算法，二者都基于词频来决定 document embedding，目前更常用的是 BERT 的各种衍生模型或混合算法。</p>
<p>然后讲了 RNN 相关知识，这里了解一下就好</p>
<h3>Embedding operations</h3>
<p>我们通常用 cosine similarity 量化 embedding 之间的相关性。</p>
<p>然后是 t-SNE 降维算法，用来可视化高维 embedding</p>
<p>最后是给定 query embedding，找到最相似的 Top-K 向量，经典算法是 LSH</p>
<h2>Transformer</h2>
<p>前两个 subsection 讲的比较基础，对 transformer 比较熟悉的话，可以直接跳到 3.3</p>
<h3>Computational improvements</h3>
<p>首先是 position embedding，比较基础的是 learned embedding 和 sinusoid embedding，目前最常用的是 RoPE 以及其变种，推荐阅读：<a href="https://kexue.fm/archives/8265">苏剑林的 blog</a></p>
<p>然后是 layer-level 的 tricks：</p>
<ol>
<li>attention layer：原始 transformer 使用的是 MHA，为了提高性能，我们可以使用对 query 进行分组的 GQA，当 query 全部被分到一组时，最后就简化为了 MQA</li>
<li>others：其他 tricks 例如 residual connections、masking、LN、label smoothing 都比较简单</li>
</ol>
<h3>Architecture variations</h3>
<p>transformer 的原始架构是 encoder-decoder，后续衍生出了 encoder-only 和 decoder-only 的诸多变种，其中最出名的是 decoder-only 的 GPT 系列。</p>
<p>encoder-only 中最出名的是 BERT，其 pretrain 策略影响很大：</p>
<ol>
<li>Masked Language Model, MLM：挑一些 token，80% 换成 <code>[MASK]</code> 这个 special token，10% 换成随机词，10% 不变，让模型预测这些 token</li>
<li>Next Sentence Prediction, NSP：用 <code>[CLS]</code> 预测两句话是否连续</li>
</ol>
<p>后续的 finetuning 让 BERT 在特定任务上表现更好</p>
<p>其他 encoder-only 模型还有 DistilBERT、ALBERT、RoBERTa、ELECTRA</p>
<p>来到 decoder-only 模型，有两个系列：GPT、LLaMA。GPT 系列只开源到 3，后续成为了 OpenAI 的 property model 不再开源。LLaMA 来自 Meta，是开源 LLM 的经典工作，有很多变种</p>
<p>最后是 decoder-only 模型的 scaling law，来自论文 <a href="https://arxiv.org/abs/2203.15556">Training Compute-Optimal Large Language Models</a>，可以阅读这篇论文笔记：<a href="https://docsaid.org/papers/transformers/chinchilla/">DOCSAID Chinchilla</a></p>
<p>接着是传统的 encoder-decoder 模型，比较出名的是 google 的 T5，以及 ByT5、BART</p>
<p>最后是新兴的 MoE 模型，主要是对 transformer 中的 FFN/MLP 进行了修改，添加了多个并行的前馈网络，每个就作为一个专家。目前最常见的是 Top-K 专家，router 对每个 token 计算 expert 的得分，然后将 token 送入前 k 个专家，输出按权重进行合并，这个方式称为 sparse MoE，相对的有 Dense MoE，每个 token 都送入所有专家，再加权求和。Switch Transformer 是典型的 Top-1 MoE</p>
<h3>Attention computations speedup</h3>
<p>首先是不同的 sparse attention：</p>
<ol>
<li>reformer：只计算相似 token 间的 attention，这里又使用了 LSH 来寻找相似 token，复杂度降至$O(N \log{N})$</li>
<li>longformer：对 attention map 下手，部分 token 为 global，可以被所有 token 看到同时看到所有 token，其余 token 使用 sliding window attention，只能看到局部的 token，还有可选的 dilated sliding window，每隔几个 token 看一个 token</li>
</ol>
<p>然后是 low rank attention，sparse attention 直接让每个 token 只 attend 部分 token，而 low rank attention 选择使用低秩结构近似完整的 attention：</p>
<ol>
<li>linformer：为 KV 矩阵加入低秩矩阵以降低复杂度</li>
<li>performer：利用 kernel trick 降低 attention 计算复杂度</li>
</ol>
<h3>Hardware optimization</h3>
<p>最出名、常用的是 Flash attention，由 DAO Lab 提出，通过将 attention 的计算切成小块，将数据留在 SRAM 上，减少对 HBM 的使用，降低了 memory 的 IO 操作</p>
<h3>Interpretability</h3>
<p>如何对模型进行解释分析？</p>
<p>最简单的方式是画 attention map，看不同 token 的 attention score，但其实不同的 attention score 可能对应同样的 output，所以这个方法不是很准确</p>
<p>更通用的方法有 TCAV、Integrated gradients、LIME、TracIn</p>
<h2>Large language model</h2>
<h3>Notations</h3>
<p>大模型的训练一般分为三个阶段：pretraining、finetuning、preference tuning</p>
<p>pretraining 让模型学习数据的 generalities，finetuning 让模型学习特定的任务，preference tuning 让模型学习输出好的答案</p>
<p>finetuning 和 preference tuning 可以合称为 alignment，都包含在 post-training 中，post-training 的方向很多：</p>
<ol>
<li>Supervised fine-tuning / SFT</li>
<li>Preference tuning / alignment optimization</li>
<li>Reinforcement learning / RL-style post-training</li>
<li>Reasoning-oriented post-training</li>
<li>Distillation / teacher-student training</li>
<li>Domain adaptation / continual fine-tuning</li>
<li>Tool-use / agentic training</li>
<li>Safety / refusal / policy behavior training</li>
<li>Long-context / memory / retrieval-oriented training</li>
<li>Efficient adaptation: LoRA, QLoRA, adapters, prompt tuning</li>
</ol>
<p>然后是 emergent abilities，随着 model size 的增长，模型能力会在一个临界点后显著提高</p>
<h3>Response generation</h3>
<p>LLM 在生成 token 时有几种不同的策略。</p>
<p>我们已经知道了生成 token 时会计算 vocabulary 中所有词的 softmax score，那么我们直接选取得分最高的词，就是 Greedy search。总所周知，greedy 不一定能得到全局最优，那么我们可以同时探索多条生成路径，这就是 Beam search</p>
<p>目前实际上最常用的是 Sampling-based generation。首先是最最最常见的 Temperature sampling，在计算 softmax 前，对所有 logits 除以 Temperature，也就是同时进行缩放。我们知道指数函数的增长速度很恐怖，所以当 T&lt;1 时，logits 都被放大，计算 softmax 时，大的数值得分变的更高了，当 T&gt;1 时，logits 都被缩小，计算 softmax 时，得分被拉近了。</p>
<p>接着我们继续应用 Top token sampling。先来 Top-K token sampling，非常简单，取前 K 个，其他的丢了。然后是 Top-p sampling，取累积概率到 p 的最小 token 集合，其他的丢了。</p>
<p>最后进行概率归一化，然后按概率进行随机采样，得到最终 token。</p>
<h3>Pretraining</h3>
<p>首先是 data mixture，目前比较常见的数据源有：Common Crawl、C4、BookCorpus、Multilingual datasets、GitHub、StackOverflow</p>
<p>接着就开始训练了，在准备好的数据上通过 Next token prediction 任务进行大规模的 self supervised learning</p>
<h3>Prompt engineering</h3>
<p>坏输入会得到坏结果，一个好的 prompt 应该包含什么？context、instruction、input、examples、constrains</p>
<p>context window 和 context length 也需要了解一下，前者是 LLM 的最大容量，后者是总的输入长度。需要注意的是，context window 大不代表模型真的能处理的好 context window 内的所有内容，用美国豆包 gemini 来举例，gemini 的单轮或少轮对话表现还不错，但当 context length 增长到一个临界点后，gemini 的大海捞针得分会断崖式下跌（flash 和 pro 都是如此，截止 2026-05-20，google 新发布的 3.5flash 仍然如此，无愧美国豆包的名号。google 家 coding agent 垃圾也是预料之中，反观 gpt5.5 只是少量下跌，真是 codex 成功的一等功臣）。</p>
<p>接着，我们来介绍一些用来增强模型能力的 prompting strategies。</p>
<p>首先是 In Context Learning，给模型几个例子，然后给出新问题，这个方法叫 Few-shot learning，如果不给例子直接给问题，就是 Zero-shot learning。</p>
<p>然后是 CoT，通过让模型在推理时显示输出 reasoning 过程来提高模型表现，idea 就是让模型在新问题上复用训练语料中的推理模式</p>
<p>接着是 Self-consistency，让模型在不同 sampling hyperparameter 下生成答案，然后选择出现次数最高的</p>
<p>接着是 ToT，树状的去搜索答案，说实话没见过真正的应用，只能说有启发意义</p>
<p>最后是 ReAct，将 Thought、Action、Observation 交替进行从而提高模型能力，这是后续 agent 发展的基石理论。有趣的是，相近的但适用于人类的决策模型早在 1970s 就出现了：<a href="https://en.wikipedia.org/wiki/OODA_loop">Wiki pedia OODA Loop</a>，我在 Anthropic 的一个 leader 的 blog 中也看到其在使用这个决策模型，所以也写进了自己的 blog 里。</p>
<p>prompt 也存在安全问题，比如 prompt injection attack，以及 model hallucination。</p>
<h3>Finetuning</h3>
<p>首先是 SFT，SFT 提高模型在 tasks of interest 上的表现，SFT training data 需要 quality&gt;quantity，数量 k 级已经足够，pretraining 获得的 model 在 SFT training data 上继续进行 NTP 任务。相近的是 Instruction tuning，其希望模型在未见过的 instruction 上表现更好，也就是提高指令遵循能力。</p>
<p>然后是 Parameter efficient finetuning。在微调时，模型的全部参数并不都需要改变，实际上，仅仅调整一个 subset 就足够。最经典常用的工作是 LoRA，其一般作用在 QV 矩阵上，训练后能 merge 回原权重。还有 adapter，其插入了一些权重可更新的 module，微调时只调整这些 adapter。最后是 Prefix tuning，其在 KV 前加入一段 virtual token，这些 token 位于 continuous space，在微调时只更新这些 virtual token 的值，相当于给模型提供了一段虚拟的上下文用于指导输出。</p>
<h3>Preference tuning</h3>
<p>preference tuning 用来让模型生成更好的、更贴近我们 preference 的答案。训练需要 preference data，我们一般使用 pairwise data，因为其比较简单</p>
<p>接着，我们就要使用这些数据，通过 RLHF 来让模型对齐人类的偏好。RLHF 先用这些数据训练出一个 RM，然后用 RM 去评价模型的输出是否符合 preference，最后，用 PPO 更新模型权重。</p>
<p>其他比较常见的还有 rejection sampling、DPO、IPO。</p>
<h3>Model compression</h3>
<p>模型压缩主要有两条路：蒸馏和量化。这块就不再细讲了。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Raycast Technical Report]]></title>
            <link>https://qi7876.github.io/posts/raycast-technical-report/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/raycast-technical-report/</guid>
            <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Source: https://www.raycast.com/blog/a-technical-deep-dive-into-the-ne...]]></description>
            <content:encoded><![CDATA[<p>Source: <a href="https://www.raycast.com/blog/a-technical-deep-dive-into-the-new-raycast">https://www.raycast.com/blog/a-technical-deep-dive-into-the-new-raycast</a></p>
<p><img src="https://www.raycast.com/uploads/blog-technical-deep-dive-new-raycast/raycast-2-tech-stack.png" alt="Tech stack of Raycast v2" /></p>
<p>同时做到了：</p>
<ol>
<li>跨平台</li>
<li>Native Experience</li>
<li>高拓展性</li>
<li>高性能</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[论文叙事]]></title>
            <link>https://qi7876.github.io/posts/writing-paper/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/writing-paper/</guid>
            <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[在 B 站看到的一个博士生的视频 论文叙事：一个好故事，带分析很喜欢 太合乎逻辑，但前人没做过 反直觉（意料之外，情理之中） 通用（放之四海...]]></description>
            <content:encoded><![CDATA[<p>在 B 站看到的一个博士生的视频</p>
<p>论文叙事：</p>
<ol>
<li>一个好故事，带分析很喜欢</li>
<li>太合乎逻辑，但前人没做过</li>
<li>反直觉（意料之外，情理之中）</li>
<li>通用（放之四海而皆准）</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[长视频理解的发展方向]]></title>
            <link>https://qi7876.github.io/posts/the-directions-of-long-video-understanding/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/the-directions-of-long-video-understanding/</guid>
            <pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[之前一直在看流式视频理解相关的论文，长视频理解 Agent 和 Token Compression 也了解了一些，昨晚在小红书上看到了一篇讨...]]></description>
            <content:encoded><![CDATA[<p>之前一直在看流式视频理解相关的论文，长视频理解 Agent 和 Token Compression 也了解了一些，昨晚在小红书上看到了一篇讨论长视频理解的帖子，poster 给目前的方向分成了 4 类，在这里转载一下，后面系统完善一下：</p>
<ol>
<li>token compression，但从我的角度来看这些压缩的方法势必会带来信息的损耗 本质上其实是 benchmark oriented 的做法 压缩了非 benchmark 需求的信息 但已经是最 make sense 的角度之一</li>
<li>adaptive frame selection，和第一种方法有相似的缺点 同时如果 selection 与 query 相关的话基本无法应用到多轮问答上</li>
<li>流式视频领域 streaming 了解的不多但看了几个文章可能都还是在做压缩这个事情 本质上我更愿意把流式视频视作一种特殊的 interleave 来解</li>
<li>agentic 方法 目前的方式其实都很直觉 做 memory bank 或者什么 zoom in 的方法 实话说可能是目前最容易应用的方法 缺点就是计算复杂度太高</li>
</ol>
<blockquote>
<p>所以从我的角度来看更本质的解法可能在 infra 侧和数据侧 只要 infra 能支持 2048/8192 帧的高分辨率图像输入加上高质量数据 这问题自然就解了</p>
</blockquote>
<p>我的看法比较类似，这四种路径本质都是通过牺牲部分信息来换取更长时的视频理解能力，但是说 infra 侧和数据侧进步这问题就能解决有些草率了。</p>
<p>视觉和语言差异实在是太大了。如谢赛宁所说：LLM 实际上是强监督学习，语言中蕴含着人类几千年来默默标注的隐式监督信息，LLM 通过自监督学习就能学习到大量知识。</p>
<p>但到了 CV 上，就完全不是这样，视觉上没有如此强大又密集的隐式监督信息。</p>
<p>最初是图像，我们只能依靠人工标注的类别来进行监督学习，后续 OpenAI 的 CLIP 通过构建巨量的 Image-Text 对，让模型学到了深层的语义信息，同时期的 DINO 则通过自监督，让模型学习到了结构信息。</p>
<p>而到了视频上，情况又不一样了：帧数量暴增，迅速撑满上下文，需要高效压缩；视频增加了时间维度，需要额外建模时间变化。</p>
<p>视频中存在着大量的冗余信息可以被压缩，这是毋庸置疑的，但我们难以找到一个非常好的通用方案：</p>
<ol>
<li>使用 task-sufficient representation：根据 query 来决定哪些 frame/token 是有用的，并剔除冗余数据，但这也意味着我们放弃了多轮对话场景。</li>
<li>使用 heuristic sampling：人为根据我们对视频的认知经验来设置压缩算法，通用，但针对某一具体任务效果差。</li>
</ol>
<p>4.20 Update</p>
<p>又想了一下，感觉 task-sufficient representation 是比较好的方向，我的理由：</p>
<ol>
<li>参考人类本身的视觉处理过程</li>
<li>未来是 real-time、streaming 的世界，LLM 的第一个应用场景是 Web 页面聊天，但我们不能局限于这个场景。具身、智能穿戴、自驾、多模态 Agent 这些场景更广阔，并且都偏向于 real-time、streaming、多步骤推理规划（ReAct 范式）</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Some advice to anyone starting a PhD in ML]]></title>
            <link>https://qi7876.github.io/posts/advice-to-ml-phd/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/advice-to-ml-phd/</guid>
            <pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Some advice to anyone starting a PhD in ML, or things that I heard from more experienced researchers and I tried to follow: focus on a real...]]></description>
            <content:encoded><![CDATA[<p>Some advice to anyone starting a PhD in ML, or things that I heard from more experienced researchers and I tried to follow:</p>
<ol>
<li>focus on a real problem. Something tangible, that can benefit people. Talk to industry folks if you're looking for open problems. Talk to the end users to figure out what the actual issues are</li>
<li>start by doing a survey of the task. Basically a long detailed paper that summarizes the field. Use Anki to memorize techniques/papers/authors in your field</li>
<li>do a benchmark paper. Take the top open-source methods and empirically see how they perform. Keep it fair. Find out if existing metrics and datasets are relevant in the real world.</li>
<li>keep focusing on real problems and real value, instead of appeasing R2. After a survey and benchmark you should know what the main real issues are. And it probably isn't improving the results by 0.5%. Personally I did follow 1, 3, 4 (I skipped 2 because my supervisor had just published a survey), and it helped me a lot. Fun fact, I created CosPlace in 2020 as an industry project, I thought it was unpublishable so I didn't actually write a paper until over a year later, and then it got accepted at CVPR 2022 and became my most cited paper. In short, everyone back then was training on Pitts30k (a 30k images dataset) which was unrealistic IRW (images in localization domain are abundant). For an industry project, I had to come up with a technique to train on millions of images (CosPlace) which gave great results, while existing methods could not be trained on large datasets. I thought CosPlace was unpublishable because it uses more training data than competitors. I was more concerned about appeasing R2 than publishing something valuable to the community. Luckily a year later I realized that focusing on the real problem (i.e. creating a scalable training technique) was more important than appeasing R2, and wrote that paper.</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Flash Attention]]></title>
            <link>https://qi7876.github.io/posts/flash-attention/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/flash-attention/</guid>
            <pubDate>Sun, 29 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Flash Attention 没有改变 Attention 的算法复杂度，但通过底层算法优化，将数据分块并在片上完成计算，大幅降低了显存占...]]></description>
            <content:encoded><![CDATA[<p>Flash Attention 没有改变 Attention 的算法复杂度，但通过底层算法优化，将数据分块并在片上完成计算，大幅降低了显存占用和显存 IO 开销。</p>
<p>Flash Attention 的核心算法是 Online Softmax，用于替换传统的 Softmax，可以证明 Online Softmax 得到的最终结果和传统 Softmax 得到的结果相同。而 Online Softmax 的分块处理特性和增量更新机制让其计算可以在 on-chip memory 上进行，无需多次写回 HBM，解决了传统 Softmax 的显存瓶颈痛点。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Low-Dimensional Manifold 低维流形]]></title>
            <link>https://qi7876.github.io/posts/low-dimensional-manifold/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/low-dimensional-manifold/</guid>
            <pubDate>Tue, 24 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[低维流形，一个被滥用的概念。最近在 Reddit 上看到了一个 10 年前非常通俗易懂的解释：Imagine your patterned...]]></description>
            <content:encoded><![CDATA[<p>低维流形，一个被滥用的概念。最近在 Reddit 上看到了一个 10 年前非常通俗易懂的解释：</p>
<blockquote>
<p>Imagine your patterned bedsheets. They've got a nice plaid grid look to them, very easy to predict what the next few centimeters of material look like.</p>
<p>Now imagine someone tied them in a knot, tore them a little, balled them up, and made them a crumpled mess, then handed them to you. Now if you were to look at the plaid pattern, it would be very difficult to discern how the pattern is, or predict what will be the color of any point of the arbitrary 3D ball of mess you've got. But if you untangled it, you could clearly see the pattern again.</p>
<p>The data is a bunch of colors in an arbitrary 3D ball of mess with very difficult to discern patterns. But the data lies on a low dimensional manifold (the 2D bedsheet). If you could figure out the manifold (flatten the bedsheet), the data will be easy to model.</p>
</blockquote>
<p>翻译：</p>
<blockquote>
<p>想象一下你的带图案床单。它们有着漂亮的格子网格外观，很容易预测接下来几厘米的面料会是什么样子。</p>
<p>现在想象有人把它们打了个结，撕破了一点，揉成一团，弄成了一团皱巴巴的乱糟糟的东西，然后递给你。这时如果你去看那个格子图案，将会非常难以辨清图案是如何分布的，也无法预测你那团任意的三维乱糟糟球体上任意一点的颜色会是什么。但如果你把它解开摊平，就能再次清晰地看到图案。</p>
<p>数据就像是一个任意的三维乱糟糟球体中的一堆颜色，其中的模式极难辨认。但这些数据实际上位于一个低维流形上（即那张二维床单）。如果你能找出这个流形（把床单摊平），数据就会变得易于建模。</p>
</blockquote>
<p>Source: <a href="https://www.reddit.com/r/MachineLearning/comments/4huo36/what_is_low_dimensional_manifold">https://www.reddit.com/r/MachineLearning/comments/4huo36/what_is_low_dimensional_manifold</a></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[每天应该做的8件事]]></title>
            <link>https://qi7876.github.io/posts/everyday/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/everyday/</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[每天阅读 30 分钟 每天运动 30 分钟 周末去公园吸氧 每天冥想 15 分钟 每天写成功日记 刻意练习写作 生气时数 10s 不说话...]]></description>
            <content:encoded><![CDATA[<ol>
<li>每天阅读 30 分钟</li>
<li>每天运动 30 分钟</li>
<li>周末去公园吸氧</li>
<li>每天冥想 15 分钟</li>
<li>每天写成功日记</li>
<li>刻意练习写作</li>
<li>生气时数 10s 不说话</li>
<li>每天 10 分钟简单复盘</li>
</ol>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[AI时代的软件工程师]]></title>
            <link>https://qi7876.github.io/posts/software-engineers-in-the-ai-era/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/software-engineers-in-the-ai-era/</guid>
            <pubDate>Thu, 12 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Source: https://jrswab.com/blog/why-do-they-want-to-get-rid-of-software-engineers/]]></description>
            <content:encoded><![CDATA[<p>Source: <a href="https://jrswab.com/blog/why-do-they-want-to-get-rid-of-software-engineers/">https://jrswab.com/blog/why-do-they-want-to-get-rid-of-software-engineers/</a></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[关于OpenClaw]]></title>
            <link>https://qi7876.github.io/posts/about-openclaw/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/about-openclaw/</guid>
            <pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[这个世界已经疯了，懂计算机的、不懂计算机的、普通网民、自媒体、KOL、公众号等等，全都在疯狂炒作营销 OpenClaw，整个世界陷入了一场对...]]></description>
            <content:encoded><![CDATA[<p>这个世界已经疯了，懂计算机的、不懂计算机的、普通网民、自媒体、KOL、公众号等等，全都在疯狂炒作营销 OpenClaw，整个世界陷入了一场对 OpenClaw 的巨大狂欢之中，每个人都在想方设法的用上 OpenClaw，但又有多少人思考过自己要用它来解决什么问题？</p>
<p>从设计来看，OpenClaw 实际上就是对 Claude Code、Codex 的又一层封装，并且这层封装的质量……嗯，难以言表。</p>
<p>膨胀到 100 万行的屎山代码库、无数的安全漏洞、糟糕的权限管理，OpenClaw 浪费了多少电力与算力，我们不得而知。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Mean, Var and Typical Scale]]></title>
            <link>https://qi7876.github.io/posts/mean-var-and-typical-scale/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/mean-var-and-typical-scale/</guid>
            <pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[标准差衡量了一个变量的典型大小（数量级） Transformer 中，在计算 Attention 时，对于 $Q \cdot K^T$ 除了...]]></description>
            <content:encoded><![CDATA[<p>标准差衡量了一个变量的典型大小（数量级）</p>
<p>Transformer 中，在计算 Attention 时，对于 $Q \cdot K^T$ 除了一个 $\sqrt{d}$ ，这是为了将点积结果的典型大小拉回 $1$，避免 softmax 的梯度消失问题。</p>
<p>这个 $\sqrt{d}$ 就是每个向量的标准差。不过你有没有想过为什么是除以 $\sqrt{d}$ ？而不是 $d$ ?</p>
<p>因为 $d$ 是方差，如果我们设一个随机变量的均值为 0，那么可以求出 $\sigma^2=E[X^2]$，可以看到，方差和样本平方值的大小相关，所以我们需要标准差而不是方差。</p>
<p>本质上，这个问题和随机游走以及中心极限定理是相同的。</p>
<p>在人类如此复杂的作品中，概率论就这么默默的参与其中，一个小小的 $\sqrt{d}$ 联系起了 Transformer 与随机游走，这种感觉还是很奇妙的。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[[Note] How to fix your entire life in 1 day]]></title>
            <link>https://qi7876.github.io/posts/how-to-fix-your-entire-life-in-1-day/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/how-to-fix-your-entire-life-in-1-day/</guid>
            <pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[来自 Dan Koe，原文 两种改变：改变行动，不断取得进展直到成功（次优先） 改变自己，让行动自然而然的发生（最优先） If you wa...]]></description>
            <content:encoded><![CDATA[<p>来自 Dan Koe，<a href="https://letters.thedankoe.com/p/how-to-fix-your-entire-life-in-1">原文</a></p>
<h2>你不能实现你想要的，是因为你不是那个能实现的人</h2>
<p>两种改变：</p>
<ol>
<li>改变行动，不断取得进展直到成功（次优先）</li>
<li>改变自己，让行动自然而然的发生（最优先）</li>
</ol>
<blockquote>
<p>If you want a specific outcome in life, you must have the <em>lifestyle</em> that creates that outcome long before you reach it.</p>
</blockquote>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Coding Agent Guide]]></title>
            <link>https://qi7876.github.io/posts/coding-agent-guide/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/coding-agent-guide/</guid>
            <pubDate>Tue, 13 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[2026-09-23 Update：按照 codex cli 0.156.0 版本更新了一些内容 现在是一个 Coding Agent 井喷...]]></description>
            <content:encoded><![CDATA[<p><strong>2026-09-23 Update</strong>：按照 codex cli 0.156.0 版本更新了一些内容</p>
<p>现在是一个 Coding Agent 井喷式爆发的时期，网络上出现了开源的、闭源的各种各样的 Coding Agent，再加之各路 KOL 的营销炒作，令人眼花缭乱。那么我们该如何挑选一个省心又好用的 Coding Agent 呢？</p>
<h2>TL;DR</h2>
<p>用 Claude Code 和 Codex。</p>
<p>而对于这两个 Coding Agent，具体用哪个取决你的个人需求：</p>
<ul>
<li>Claude Code：闭源，API 成本高，效果可能更好一些，前后端兼通</li>
<li>Codex：开源，API 成本极低，在后端上效果基本和 Claude Code 持平甚至超越，前端能力稍薄弱</li>
</ul>
<p>对我个人而言，Codex 是绝对的最佳选择。</p>
<p><strong>2026-09-23 Update</strong>：现在可以加一个 dsh，deepseek v4.1 flash 的性能速度以及价格很均衡，处理一些简单机械任务很不错</p>
<h2>其他 Coding Agent</h2>
<p>除了 Claude Code 和 Codex，市面上还有其他许多 Coding Agent，例如 Kimi CLI、Gemini CLI 等等。</p>
<p>这些 Coding Agent 在价格和免费额度上可能有一些优势，能力上也许能做到 Claude Code 和 Codex 的六七成，但这是建立在使用官方 API 的基础上的。而当我们使用中转站 API，Codex 逆向能做到极低的价格，性价比极高，再加上 Codex 本身的成熟设计，那我们已经完全没有理由使用其他任何 Coding Agent 了。</p>
<p>至于 Github Copilot，除了学生包免费之外已经基本没有什么使用的理由了，能力和 Claude Code、Codex 差太多，不建议使用。</p>
<p><strong>2026-09-23 Update</strong>：最近发生了 ZCode、Grok 等 Agent 自动上传整个 Code repo 的恶性偷数据事件，提醒尽量使用 Codex、dsh、Pi 这种开源 Agent，或者 Claude Code 这种使用人数极大的闭源 Agent。</p>
<h2>安装与配置</h2>
<p>下面我以我个人常用的 Codex 为例，讲讲从配置到实战的全流程。</p>
<h3>安装前置</h3>
<p>要使用 Codex，我们需要先安装 node</p>
<p>Windows：</p>
<pre><code>winget install -e --id OpenJS.NodeJS
</code></pre>
<p>macOS：</p>
<pre><code>brew install node
</code></pre>
<p>linux：</p>
<p>根据具体的包管理器，安装 node</p>
<p><strong>2026-09-23 Update</strong>：实际上并不需要安装 node，只是使用 npm 下载一下 binary 而已，你甚至可以直接用官方的 shell 脚本安装。</p>
<h3>安装 Codex</h3>
<p>安装完 node 后，我们就可以安装 Codex 了：</p>
<pre><code>npm install -g @openai/codex
</code></pre>
<p>此教程原先使用了 bun 来安装 codex，但根据其他用户报告，以及我个人的使用体验，使用 bun 安装的 codex 可能出现内存泄露，而 npm 安装的 codex 不存在这个问题。只能说 bun 还得练啊，碰到 edge case 就跪了，目前还是用更稳定的 node/npm 吧。</p>
<h3>配置 Codex</h3>
<p>安装完 Codex 后，我们还需要对其进行一些配置才能正常使用。</p>
<h4>API Key</h4>
<p>首先，我们需要一个能接入到 Codex 的 API Key。这里对模型没有限制，可以使用 gpt 系列，也能使用其他开源模型。但考虑到 Codex 逆向出来的 gpt 价格如此之低，我仍然强烈推荐你直接使用 gpt。</p>
<p>对于中转站，我推荐 ikuncode，低价且稳定，aff 链接：<a href="https://api.ikuncode.cc/register?aff=wAM2">https://api.ikuncode.cc/register?aff=wAM2</a></p>
<p>如果你也想使用这个中转站，可以考虑点击我的 aff 链接给我一些邀请奖励。</p>
<p><strong>2026-09-23 Update</strong>：实际上并没有邀请奖励 hh</p>
<h4>Codex config</h4>
<p>获取完 API Key 后，我们还需要为 Codex 配置一下，我们需要创建并修改两个文件：</p>
<p><code>~/.codex/config.toml</code>:</p>
<pre><code>model_provider = "ikuncode"
model = "gpt-5.4"
model_reasoning_effort = "xhigh"
network_access = "enabled"
disable_response_storage = true
web_search = "live"
personality = "pragmatic"

[model_providers.ikuncode]
name = "ikuncode"
base_url = "https://api.ikuncode.cc/v1"
wire_api = "responses"
requires_openai_auth = true

[sandbox_workspace_write]
network_access = true
</code></pre>
<p><code>~/.codex/auth.json</code>:</p>
<pre><code>{
  "OPENAI_API_KEY": "your api key"
}
</code></pre>
<p>注意你需要在 <code>~/.codex/auth.json</code> 文件中放入你自己的 API Key。</p>
<p><strong>2026-09-23 Update</strong>：下面的 config 只适用于 codex cli 0.156.0 及以上版本。</p>
<p>我主要做出了以下几个改动：</p>
<ol>
<li>模型更新到最新</li>
<li>调整 reasoning effort 至 medium，平衡性能与价格</li>
<li>关闭 sandbox，改用 YOLO 模式。现在的模型已经基本不会做危险行为了，sandbox 应该用在 agent 训练中，而不是在实际使用中浪费人的时间，可以回忆一下你是不是无脑 approve。</li>
<li>增加了 timeout 设置，减少重连现象</li>
<li>一些外观上的调整，个人喜好，你可以随意自定义</li>
</ol>
<pre><code>model = "gpt-6-sol"
model_reasoning_effort = "medium"
web_search = "live"
plan_mode_reasoning_effort = "medium"
sandbox_mode = "danger-full-access"
approval_policy = "never"
service_tier = "default"

model_provider = "api"

[model_providers.api]
name = "api"
base_url = "https://api.ikuncode.cc/v1"
wire_api = "responses"
requires_openai_auth = true
stream_idle_timeout_ms = 1200000

[tui]
theme = "ansi"
status_line = ["model-with-reasoning", "five-hour-limit", "weekly-limit", "git-branch"]
status_line_use_colors = false
session_picker_view = "dense"
screen_reader_detection_done = true

[tui.effects]
starfield = false
shimmer = false
welcome = false
effort = false
progress = true
title = false
</code></pre>
<h2>实战</h2>
<p>安装和配置完成后，我们就可以在项目中使用 Codex 了，随意以一个项目为例，我们运行命令进入 Codex。</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310114517.D5ITnS8f_Z1AP1ca.webp" alt="" /></p>
<p>在首次进入一个项目时，Codex 会让我们确定一些基础的权限，对于有 version control 的项目，可以直接给予 Codex 编辑和运行部分命令的权限，运行其他命令仍然需要你手动同意。当然，为了最高的权限控制，你也可以让 Codex 的每次修改文件和运行命令都要经过你的同意。</p>
<p><strong>2026-09-23 Update</strong>：别浪费时间</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310113843.BxOzieTm_Z2kOLMG.webp" alt="" /></p>
<p>我们选择 1</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310114534.Co1wWf9c_YRgBW.webp" alt="" /></p>
<p>现在的界面就很熟悉了，一个简单的对话框，但这次对话框后是一个全副武装的 Coding Agent。</p>
<p>你可以随意开始对话，让 Codex 帮你理解项目结构、开发新功能、写测试案例、补全项目文档。</p>
<p>此外，还有一些特殊的命令。</p>
<h4>commands</h4>
<p>在对话框中输入 <code>/</code>，Codex 会自动展示命令列表，通过上下方向键可以快速选择命令。</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310115422.B7ZfLV3u_1croCl.webp" alt="" /></p>
<p>命令后有对应的作用描述，比较常用的命令有：</p>
<ul>
<li>/resume</li>
<li>/new</li>
<li>/fork</li>
<li>/init</li>
<li>/rename</li>
<li>/plan</li>
<li>/review</li>
<li>/ps</li>
<li>/exit</li>
</ul>
<h4>skills</h4>
<p>在对话框中输入 <code>$</code>，Codex 会自动展示 skills 列表，通过上下方向键可以快速选择 Skill。</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310115504.7Yevb-Tw_ZlvIl7.webp" alt="" /></p>
<p>也可以使用 Codex 自带的 Skill Creator 创建自己的 Skill。</p>
<h4>指定文件</h4>
<p>在对话框中输入 <code>@</code>，可以快速选择文件路径，Codex 会在对话中自行调用工具读取。</p>
<p><img src="https://qi7876.github.io/_astro/Pasted%20image%2020260310125319.cyNYRAGz_Z2vfjN7.webp" alt="" /></p>
<p>注意，如果你已经输入了一些文字，然后想使用 <code>@</code>指定文件路径，你需要在文本和<code>@</code> 之间先打上一个空格。</p>
<h2>关于 Prompt</h2>
<p>在 Codex 的助力下，管理上下文、调用工具、指定读取文件等操作都变得极为简单，但你的 Prompt 也变得更为重要。Codex 的特点是指令遵循能力强，你说什么，他就做什么。你说对了，他就基本能做对，但你要是说错了，他可能也会被你带歪。</p>
<p>Codex 能帮你从机械重复的 Coding 中解放出来，让你有更多时间和精力来思考关于架构设计、系统结构的问题，但这显然也要求使用者本身具有极高的工程思维，并能准确的在 Prompt 中表述自己的思想。</p>
<p>而工程思维的培养，以及如何将自己的思想准确转化具体的、有逻辑的文字，这两件事实际上是很难的，前者需要大量的工程实践，后者需要培养逻辑与不断的输出练习。而在 AI 时代，我们逐渐习惯：不懂的就问 AI，获取到相关知识点，当场使用然后遗忘。这其中基本完全没有我们个人的工程实践和输出，更多的是我们在充当 AI 与具体问题环境间的桥梁，信息在桥梁上来来往往，但桥梁最终什么也没留下。我在之前的<strong>什么是知识</strong>那篇文章介绍过知识与知识点的区别，同时转载的<strong>记录的力量</strong>中也提到过记录，也就是不断输出的重要性。</p>
<p>庆幸，我本人在大学刚开始时，AI 的能力还没那么强，同时我自己对于计算机也有强烈的兴趣，这也就促使我自己不断接触各种计算机场景与问题，并与 AI 协作解决：实践-&gt;遇到问题-&gt;思考并开始解决-&gt;遇到不懂的地方-&gt;从 AI 获取知识点-&gt;思考并解决问题-&gt;写笔记记录-&gt;继续实践。这让我有了比较好的工程能力底子，在随后 AI 的不断发展中，也进一步强化了自己的能力。</p>
<p>而相反的是，我在学院开设的工程实践创新课程上，发现大部分同学对于计算机的理解只能说是惨不忍睹，AI 能力在不断强化，导致他们遇到问题时下意识就不思考并去询问 AI 来解决问题，并且毫无输出，导致自己的能力一直得不到提升，在日后每次遇到相似问题时都会浪费大量的时间来解决，并且由于 AI 回答带来的信息茧房，他们很难接触到最新的、更易用的工具链。像 micromamba、uv、docker 这些现代化开发工具，能极大的加速代码开发流程，但我至今没看到身边有多少人在使用，更多还是业界和开源项目中先用起来，要经过很长时间才能扩散到整个社群。</p>
<p><strong>2026-09-23 Update</strong>：不要滥用 AI！不要滥用 AI！不要滥用 AI！这会毁了你的工程素养和系统思维。你应该在学习时独立自主的探索，遇到不懂的可以询问 AI，但绝不要让 AI 帮你做 hw、lab、proj！</p>
<p>然后在实习与工作中和 Agent 结对推进，继续提升自己的能力。当你认为自己已经对计算机系统、GPU 编程模型等等你所工作的领域了如指掌后，你才应该化身 leader 指挥 agent。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[21.04 RoPE]]></title>
            <link>https://qi7876.github.io/posts/2021-04-rope/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/2021-04-rope/</guid>
            <pubDate>Sun, 14 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[林剑苏的代表作，也是目前使用最多的 position embedding 其 blog 中详细记录了研究过程，可以阅读一下：苏剑林的 blo...]]></description>
            <content:encoded><![CDATA[<p>林剑苏的代表作，也是目前使用最多的 position embedding</p>
<p>其 blog 中详细记录了研究过程，可以阅读一下：<a href="https://kexue.fm/archives/8265">苏剑林的 blog</a></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[Nanochat Guide]]></title>
            <link>https://qi7876.github.io/posts/nanochat-guide/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/nanochat-guide/</guid>
            <pubDate>Wed, 10 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[通过 Super Study Guide: Transformers and Large Language Models，我们学习了 LLM...]]></description>
            <content:encoded><![CDATA[<p>通过 Super Study Guide: Transformers and Large Language Models，我们学习了 LLM 相关的知识，现在我们通过 nanochat 这个项目来实践一下我们学习到的知识。</p>
<p>Source: <a href="https://github.com/karpathy/nanochat">https://github.com/karpathy/nanochat</a></p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
        <item>
            <title><![CDATA[25.10 StreamingVLM]]></title>
            <link>https://qi7876.github.io/posts/2025-10-streamingvlm/</link>
            <guid isPermaLink="false">https://qi7876.github.io/posts/2025-10-streamingvlm/</guid>
            <pubDate>Tue, 02 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[训练与推理的对齐 作者发现目前模型在处理无限长视频流时，存在以下这几个问题：全注意力机制：会导致计算成本呈平方级增长，很快就会引发 OOM...]]></description>
            <content:encoded><![CDATA[<p>训练与推理的对齐</p>
<h2>发现问题</h2>
<p>作者发现目前模型在处理无限长视频流时，存在以下这几个问题：</p>
<ul>
<li>全注意力机制：会导致计算成本呈平方级增长，很快就会引发 OOM，并且在处理超出训练长度的超长视频时性能会大幅下降。</li>
<li>无重叠滑动窗口：虽然限制了内存，但频繁重置上下文会打破生成的连贯性。</li>
<li>带重叠滑动窗口：保留了部分历史信息，但每个窗口都需要进行大量的冗余注意力重计算，导致高延迟，无法满足实时推理的需求。</li>
<li>训练与推理不一致：要在推理时处理无限长的视频流，但受限于计算资源，模型无法在极其漫长的视频上进行训练。如何用短视频片段训练模型，却让它具备在无限流上进行稳定推理的能力，是一个未充分解决的难题。</li>
</ul>
<h2>解决问题</h2>
<p>为了解决上述问题，作者提出了 StreamingVLM，这是一个将训练和流式推理完美对齐的统一框架。其核心解决策略包括：</p>
<ul>
<li><strong>流式感知的 KV Cache（推理阶段）</strong>：模型在推理时维护一个紧凑且稳定的 KV Cache。它不对旧画面进行重复计算，而是复用三种状态：(1) <strong>注意力池（Attention Sink）</strong>，如系统提示词和早期文本；(2) <strong>较长的近期文本窗口</strong>，用于保持长期记忆；(3) <strong>较短的近期视觉窗口（如 16 秒）</strong>，用于捕捉当前动作。当超出预算时，优先淘汰最旧的视觉 Token。</li>
<li><strong>连续旋转位置编码（Contiguous RoPE）</strong>：为了防止旧 Token 被淘汰后产生位置信息的偏移，模型在推理时调整 RoPE 索引，使其与最后保留的 Token 保持数值上的连续性。这样，位置索引就能被限制在一个固定的范围内，确保了超长推理时的数值稳定性。</li>
<li><strong>重叠块的 SFT 训练策略（训练阶段）</strong>：模型并不在超长视频上训练，而是将视频切分为有时间重叠的短片段（如长度 24 秒，重叠 12 秒），并在片段内应用全注意力机制。并且，模型将视觉和文本 Token 以 1 秒 为间隔交替排列（而非像传统 VLM 那样把视频 Token 全堆在文本前面）。这种重叠的短片段训练能够完美近似推理时的“注意力池 + 近期视觉 + 长期文本”的模式，教会模型何时该说话、何时该保持沉默。</li>
<li><strong>数据流构建</strong>：构建了一个名为 <code>Inf-Streams</code> 的大型体育解说数据集，并通过 GPT 进行了严格的数据清洗。此外，还提取了一批“高质量退火数据”专门用于强化对场上实时动作的解说能力。</li>
</ul>
<h2>讨论</h2>
<ul>
<li><strong>卓越的准确性与长视频能力</strong>：在平均长度超 2 小时的新测试基准 <code>Inf-Streams-Eval</code> 上，StreamingVLM 实现了无限流模式下的连续解说，以 66.18% 的胜率击败了 GPT-4o mini。同时，该模型能够在其长达两小时的视频切片的不同阶段均保持同样高水准的性能表现，不会随着时间推移而退化。</li>
<li><strong>提升了通用的 VQA（视觉问答）能力</strong>：令人惊喜的是，即便没有使用特定的 VQA 数据进行微调，StreamingVLM 的流式训练策略依然全面提升了基础模型的视觉理解能力，例如在 LongVideoBench 上提升了 +4.30，在 OVOBench Realtime 上提升了 +5.96。</li>
<li><strong>极高且稳定的推理效率</strong>：相比于全注意力机制引发的 OOM，以及滑动窗口带来的延迟尖峰，StreamingVLM 的单 Token 延迟极低且非常平稳。它在单张 NVIDIA H100 显卡上最高支持 <strong>8 FPS</strong> 的实时稳定推理。</li>
<li><strong>消融实验验证</strong>：实验表明，如果不使用 Contiguous RoPE，模型在无限视频流上的性能会急剧下降；而将视觉窗口大小设定为 16 秒 则是权衡近期动作捕捉和计算效率的最佳选择；最后，添加高质量退火数据大幅提升了生成效果。</li>
</ul>
<h2>结论</h2>
<p>StreamingVLM 为现有的视觉语言模型引入了实时流式感知能力，成功搭建了一个训练与推理高度一致的框架。它有效解决了长视频处理中的计算冗余和记忆遗忘问题，在资源有限的单卡（H100）上实现了超过 3 小时的平稳、实时的视频解说能力。同时，作者开源的 <code>Inf-Streams</code> 数据集和评测基准为要求秒级对齐的长视频理解设立了新标准。这项工作为 VLM 在机器人、自动驾驶、实时 AI 助手等真实场景中的大规模落地铺平了道路。</p>
]]></content:encoded>
            <author>qi7876</author>
        </item>
    </channel>
</rss>