<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Yuyao Ge 葛钰峣 | YuyaoGe's Website</title><link>https://geyuyao.com/authors/admin/</link><atom:link href="https://geyuyao.com/authors/admin/index.xml" rel="self" type="application/rss+xml"/><description>Yuyao Ge 葛钰峣</description><generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Thu, 11 Jun 2026 00:00:00 +0000</lastBuildDate><image><url>https://geyuyao.com/authors/admin/avatar_hu78592bd8e8d0b01cb10371578770d82e_2037136_270x270_fill_q99_lanczos_center.jpg</url><title>Yuyao Ge 葛钰峣</title><link>https://geyuyao.com/authors/admin/</link></image><item><title>更复杂的 Agent 能带来更好的性能吗？</title><link>https://geyuyao.com/post/swe-agent-vs-mini-swe-agent/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/swe-agent-vs-mini-swe-agent/</guid><description>&lt;style>
.li-lang-bar{display:flex;justify-content:flex-end;gap:8px;margin:0 0 20px 0;}
.li-lang-bar button{border:1px solid rgba(127,127,127,.35);background:transparent;color:inherit;padding:4px 14px;border-radius:0;font-size:13px;cursor:pointer;transition:all .15s ease;}
.li-lang-bar button:hover{background:rgba(127,127,127,.12);}
.li-lang-bar button.active{background:#2563eb;color:#fff;border-color:#2563eb;}
.li-lang-zh{display:none;}
body[data-li-lang="zh"] .li-lang-zh{display:block;}
body[data-li-lang="zh"] .li-lang-en{display:none;}
body[data-li-lang="en"] .li-lang-zh{display:none;}
body[data-li-lang="en"] .li-lang-en{display:block;}
&lt;/style>
&lt;script>
(function(){
try{
var lang=null;
try{var q=new URL(window.location.href).searchParams.get('lang');if(q==='en'||q==='zh')lang=q;}catch(_){}
if(!lang){try{var s=localStorage.getItem('li_lang');if(s==='en'||s==='zh')lang=s;}catch(_){}}
if(!lang){var n=(navigator.language||navigator.userLanguage||'en').toLowerCase();lang=n.indexOf('zh')===0?'zh':'en';}
if(document.body){document.body.setAttribute('data-li-lang',lang);}
else{document.documentElement.setAttribute('data-li-lang',lang);document.addEventListener('DOMContentLoaded',function(){document.body.setAttribute('data-li-lang',lang);});}
}catch(_){}
})();
&lt;/script>
&lt;div class="li-lang-bar">
&lt;button type="button" data-lilang="zh" onclick="window.__setLILang &amp;&amp; window.__setLILang('zh')">中文&lt;/button>
&lt;button type="button" data-lilang="en" onclick="window.__setLILang &amp;&amp; window.__setLILang('en')">English&lt;/button>
&lt;/div>
&lt;div class="li-lang-zh" markdown="1">
&lt;p>TLDR: 更复杂的SWE-Agent在SWE-pro bench上相比于mini-swe-agent表现更差且出现了实例卡死&lt;/p>
&lt;p>ps：本文AI率低于20%&lt;/p>
&lt;p>首先抛出一个常见的直觉：&lt;strong>agent 框架做得越完善，性能应该越强。&lt;/strong> 尽管直觉上大家都这么认为，但是目前没有人严谨地证明过。为此，我希望在SWE任务上验证这个直觉是否是正确的🤔。&lt;/p>
&lt;p>💡思路如下：&lt;/p>
&lt;p>在SWE Pro Bench上测试两个复杂度不同的Agent Framework，对比他们各自的得分。&lt;/p>
&lt;p>结果却发现&lt;strong>简单的Agent框架反而获得了更高的性能&lt;/strong>🤯。&lt;/p>
&lt;div class="alert alert-note">
&lt;div>
&lt;p>&lt;strong>背景知识&lt;/strong>&lt;/p>
&lt;p>&lt;strong>什么是 SWE 任务？&lt;/strong> SWE（Software Engineering）任务衡量的是 agent 的端到端真实开发能力：给定一个真实代码仓库和一个 GitHub issue，让 agent 自主地读代码、定位问题、跨文件修改、写出 patch（代码补丁），最后由测试判定是否&amp;quot;解决&amp;quot;。SWE-bench Pro 就是针对这一任务的 benchmark。&lt;/p>
&lt;p>&lt;strong>SWE-agent 与 mini-swe-agent&lt;/strong> 是两个面向 SWE 场景的 agent 框架：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>SWE-agent&lt;/strong> 的核心论点是 Agent-Computer Interface（ACI），即为 agent 精心设计一套专用工具：给它配多种自定义工具、每个工具各有接口；执行则交给独立的 &lt;a href="https://github.com/SWE-agent/SWE-ReX" target="_blank" rel="noopener">&lt;code>SWE-ReX&lt;/code>&lt;/a> 后端，用持久 pexpect 交互式 shell（工作目录、环境变量跨命令保留），且每条命令先过 bashlex 预解析（切分、语法校验、精确抠退出码）。&lt;/li>
&lt;li>&lt;strong>mini-swe-agent&lt;/strong> 是 SWE-agent 的最小实现（整个 agent 类约 100 行 Python）：只有 bash 一个&amp;quot;工具&amp;quot;，连模型的 tool-calling 接口都不用；用 &lt;code>subprocess.run&lt;/code> 执行每条命令，每个 action 完全独立。&lt;/li>
&lt;/ul>
&lt;/div>
&lt;/div>
&lt;p>介绍完背景，那么问题来了：&lt;strong>在同模型、同 benchmark 下，相比于mini-SWE-Agent，SWE-Agent这套&amp;quot;更完善&amp;quot;的工程，是否能带来更高的收益呢？？&lt;/strong>&lt;/p>
&lt;h2 id="更完善的-swe-agent-并没有更强">更完善的 SWE-agent 并没有更强&lt;/h2>
&lt;p>我使用 Claude Sonnet 4.5 分别在两个 Agent Framework 上，对 SWE-bench Pro 的全部 731 题进行全量测试，限制了最大调用次数为 50 次。&lt;/p>
&lt;p>结果如下：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Agent Framework&lt;/th>
&lt;th>N&lt;/th>
&lt;th>resolved&lt;/th>
&lt;th>通过率&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>mini-swe-agent&lt;/strong>&lt;/td>
&lt;td>731&lt;/td>
&lt;td>322&lt;/td>
&lt;td>&lt;strong>44.0%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>SWE-agent&lt;/strong>&lt;/td>
&lt;td>731&lt;/td>
&lt;td>302&lt;/td>
&lt;td>&lt;strong>41.3%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>参照：官方对 Sonnet 4.5 的测试结果约为 43.6%&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>，mini 的 44.0% 与之吻合，说明了我们实验的可信性。&lt;/p>
&lt;/blockquote>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="分语言通过率对比" srcset="
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_385de0308e1f839c65be1f56e7d58fcb.webp 400w,
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_240e4bf4e45fc54693a0874eb7a5ba71.webp 760w,
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_385de0308e1f839c65be1f56e7d58fcb.webp"
width="760"
height="380"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>极简的 mini-swe-agent 比 swe-agent 还高了 2.7%。令人意外的是 &lt;strong>SWE-agent 全量跑到 722/731 后，最后 9 个实例直接卡死&lt;/strong>——容器 Up 5–12 小时、日志连续几小时无更新，只能kill掉。而 mini-swe-agent 跑同样这 9 道题却没有此问题。&lt;/p>
&lt;p>于我而言，比起结果上的意外，我更好奇为什么这九个实例会卡死🤔。&lt;/p>
&lt;h2 id="为什么会有-9-个被卡死的容器">为什么会有 9 个被卡死的容器&lt;/h2>
&lt;p>Kill掉容器前，我抓了每个卡死容器的 &lt;code>docker logs&lt;/code>，显示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">INFO ... 200 OK POST /run_in_session
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">🦖 ERROR Bashlex fail: here-document at line 0 delimited by end-of-file (wanted &amp;#34;&amp;#39;EOF&amp;#39;&amp;#34;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>容器没死、&lt;code>swerex-remote&lt;/code> 进程还在正常返回 &lt;code>200 OK&lt;/code>——&lt;strong>是 agent 在空转&lt;/strong>。顺着 agent 的 trace 看，它在用 &lt;strong>heredoc 写大文件&lt;/strong>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cat &amp;gt; some_file.go &lt;span class="s">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">... 一大段 Go 代码 ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>根因找到了：SWE-agent 的执行后端 &lt;code>swe-rex&lt;/code>，会先用 &lt;code>bashlex&lt;/code>（一个纯 Python 写的 bash 解析器）把每条命令解析一遍，再送进容器执行。&lt;/p>
&lt;p>麻烦正出在这一步。&lt;code>bashlex&lt;/code> 对 heredoc 的支持并不完整，碰到 &lt;code>cat &amp;lt;&amp;lt;'EOF' … 一大段代码 … EOF&lt;/code> 这种大块写文件，它会直接解析失败，抛出 &lt;code>Bashlex fail&lt;/code>。&lt;/p>
&lt;p>解析一旦垮掉，swe-rex 就判断不出这条命令到底有没有跑完、退出码是几；agent 收到一份残缺的反馈，又不会换种写法自救，只能把同一条命令一遍遍重试，容器就这样一卡就是 5 到 12 个小时。&lt;/p>
&lt;h2 id="swe-agent-为什么要多此一举地先解析命令">SWE-Agent 为什么要多此一举地先解析命令？&lt;/h2>
&lt;p>swe-rex 维持着一个长期存活的 shell 会话，让工作目录、环境变量、激活的虚拟环境这些状态能在多条命令之间延续。&lt;/p>
&lt;p>但代价是，当命令在一个不断流动的会话里执行时，&amp;ldquo;它到哪儿算结束、返回码是多少&amp;quot;就不再像跑完一个独立进程那样一目了然，只能靠 &lt;code>bashlex&lt;/code> 把命令切开、再注入哨兵字符串去输出流里把退出码捞回来。&lt;/p>
&lt;p>好处是：命令既然被解析成了结构，还能做安全检查、命令改写之类更精细的封装，也正是 SWE-agent 主打的 Agent-Computer Interface 思路。它用额外的复杂度，换来了更强的会话语义。&lt;/p>
&lt;p>而 mini-swe-agent 则相反，走的是极简路线。它根本不维持会话，每条命令都用一句 &lt;code>subprocess.run(shell=True)&lt;/code> 直接丢给系统真正的 shell：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># minisweagent/environments/local.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shell&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 交给系统 shell（/bin/sh -c）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cwd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">cwd&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">timeout&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stdout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">PIPE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">stderr&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">STDOUT&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这么做丢掉了会话状态，每条命令都从头开始，agent 得自己把路径和环境写全；但也正因如此，它绕开了所有&amp;quot;自己解析 bash&amp;quot;的麻烦。heredoc 再大也是真 shell 的本职工作，命令跑完、进程一退出，退出码自然就有了。&lt;/p>
&lt;p>于是同一条写大文件的命令，在 SWE-agent 撞上 &lt;code>bashlex&lt;/code> 的短板、把容器拖死，在 mini-swe-agent 这边却平平无奇地跑了过去。这就是一组很典型的工程取舍——swe-rex 用更高的复杂度换更强的会话语义，也因此多背了一类失败面；mini 放弃了会话的便利，换来更小、更可控的出错空间。&lt;/p>
&lt;h2 id="结语">结语&lt;/h2>
&lt;p>从广义的意义来说，这次的发现证明了奥卡姆剃刀原则：越简单的东西反而是越有效的（也可能是第一性原理）。&lt;/p>
&lt;p>当然，我认为这只是一个非常简单的 toy experiment。这并不能说明更复杂、更精密的 agent 效果就不好，可能只是因为 SWE-agent 恰好有这么一个 bug。也许一个经过精细调教的、更复杂的 agent 可以比 mini agent 更好。&lt;/p>
&lt;p>当然，anyway，这只是一些猜测。接下来我会用更严谨的实验深挖开头提到的问题，感兴趣的朋友欢迎持续关注。&lt;/p>
&lt;h2 id="附录">附录&lt;/h2>
&lt;h3 id="分语言对比">分语言对比&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>语言&lt;/th>
&lt;th>mini&lt;/th>
&lt;th>SWE-agent&lt;/th>
&lt;th>谁优&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>go&lt;/td>
&lt;td>95/280 = &lt;strong>34%&lt;/strong>&lt;/td>
&lt;td>78/280 = 28%&lt;/td>
&lt;td>mini +6pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>python&lt;/td>
&lt;td>139/266 = 52%&lt;/td>
&lt;td>143/266 = &lt;strong>54%&lt;/strong>&lt;/td>
&lt;td>SWE-agent +2pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>js&lt;/td>
&lt;td>77/165 = &lt;strong>47%&lt;/strong>&lt;/td>
&lt;td>73/165 = 44%&lt;/td>
&lt;td>mini +3pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ts&lt;/td>
&lt;td>11/20 = &lt;strong>55%&lt;/strong>&lt;/td>
&lt;td>8/20 = 40%&lt;/td>
&lt;td>mini（N=20，小样本不稳）&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>mini 的优势几乎全部来自 Go，高出 6 个百分点、差 17 题，而这里面光 &lt;code>gravitational/teleport&lt;/code> 一个仓就占了大头（仅 mini 解出的有 16 道，仅 SWE-agent 解出的只有 5 道）。这其实并不意外：Go 题大多是体量大、改动多的重仓，正好是最容易触发 SWE-agent heredoc 卡死的地方。可一旦换到 Python，SWE-agent 反而还略高了 2 个百分点。&lt;/p>
&lt;h3 id="配对显著性">配对显著性&lt;/h3>
&lt;p>再看配对显著性。把 731 题按 instance_id 一一对齐，能分成四类：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>数量&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>都过&lt;/td>
&lt;td>245&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>仅 mini 过&lt;/td>
&lt;td>77&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>仅 SWE-agent 过&lt;/td>
&lt;td>57&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>都没过&lt;/td>
&lt;td>352&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>真正分出胜负的是那 134 道一边过、一边不过的题，其中 mini 占 77、SWE-agent 占 57，确实偏向 mini，但 McNemar 精确检验给出的 p 值是 0.10，谈不上显著。更能说明问题的是另外两类：245 道两边都解得出、352 道两边都解不出，这说明它们能覆盖的题其实高度重叠。&lt;/p>
&lt;h3 id="卡死的公平性核算">卡死的公平性核算&lt;/h3>
&lt;p>最后补一笔公平账，对于那 9 个卡死的实例（flipt 5 个、teleport 2 个，加上 vuls 和 tutanota 各 1 个）逐题核对下来，真正算得上&amp;quot;不公平丢分&amp;quot;的其实只有 2 个，也就是 mini 能解、而 SWE-agent 仅仅因为卡死被记了 0 分的 &lt;code>vuls e4728e38&lt;/code> 和 &lt;code>teleport 47530e1f&lt;/code>。就算把这 2 分补回去，SWE-agent 也不过从 302 升到 304（41.6%），mini 仍是 44.0%，差距反而更小，&amp;ldquo;不显著&amp;quot;的结论丝毫没变。况且换个角度想，执行后端稳不稳本来就是一个 agent 端到端能力的一部分，在&amp;quot;衡量整套 scaffold&amp;quot;的口径下，记 0 并不算冤枉它😅。&lt;/p>
&lt;/div>
&lt;div class="li-lang-en" markdown="1">
&lt;p>&lt;strong>TL;DR.&lt;/strong> On SWE-bench Pro, the more elaborate SWE-agent underperforms the minimalist mini-swe-agent, and additionally suffers from instances that hang indefinitely.&lt;/p>
&lt;p>A widely held intuition holds that &lt;strong>the more complete an agent framework is, the better it should perform.&lt;/strong> Although this assumption is rarely questioned, to my knowledge it has never been rigorously verified. I therefore set out to test it on a software-engineering (SWE) task.&lt;/p>
&lt;p>The design is simple: evaluate two agent frameworks of differing complexity on SWE-bench Pro and compare their scores. The result was counterintuitive: &lt;strong>the simpler framework achieved the higher score.&lt;/strong>&lt;/p>
&lt;div class="alert alert-note">
&lt;div>
&lt;p>&lt;strong>Background&lt;/strong>&lt;/p>
&lt;p>&lt;strong>What is an SWE task?&lt;/strong> A software-engineering (SWE) task measures an agent&amp;rsquo;s end-to-end, real-world development ability: given a real code repository and a GitHub issue, the agent must autonomously read the code, localize the problem, make cross-file edits, and produce a patch, which is then judged &amp;ldquo;resolved&amp;rdquo; by a suite of hidden tests. SWE-bench Pro is a benchmark targeting exactly this kind of task.&lt;/p>
&lt;p>&lt;strong>SWE-agent and mini-swe-agent&lt;/strong> are two agent frameworks built for the SWE setting:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>SWE-agent&lt;/strong> is organized around the notion of an Agent-Computer Interface (ACI): a carefully designed set of dedicated tools, each with its own interface. Execution is delegated to a separate &lt;a href="https://github.com/SWE-agent/SWE-ReX" target="_blank" rel="noopener">&lt;code>SWE-ReX&lt;/code>&lt;/a> backend, which maintains a persistent &lt;code>pexpect&lt;/code> interactive shell (the working directory and environment variables persist across commands) and pre-parses every command with &lt;code>bashlex&lt;/code> (splitting, syntax validation, and precise exit-code extraction).&lt;/li>
&lt;li>&lt;strong>mini-swe-agent&lt;/strong> is a minimal reimplementation (the agent class is roughly 100 lines of Python): it exposes a single tool, bash, and does not even rely on the model&amp;rsquo;s tool-calling interface; each command is executed through &lt;code>subprocess.run&lt;/code>, with every action fully independent.&lt;/li>
&lt;/ul>
&lt;/div>
&lt;/div>
&lt;p>With this background in place, the central question becomes: &lt;strong>under the same model and the same benchmark, does SWE-agent&amp;rsquo;s heavier engineering actually translate into a higher payoff than mini-swe-agent?&lt;/strong>&lt;/p>
&lt;h2 id="the-more-elaborate-swe-agent-is-not-stronger">The more elaborate SWE-agent is not stronger&lt;/h2>
&lt;p>Using Claude Sonnet 4.5, I evaluated both frameworks on the full 731-problem SWE-bench Pro public set, capping the call budget at 50 per problem.&lt;/p>
&lt;p>The results are as follows:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Agent framework&lt;/th>
&lt;th>N&lt;/th>
&lt;th>resolved&lt;/th>
&lt;th>resolve rate&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>mini-swe-agent&lt;/strong>&lt;/td>
&lt;td>731&lt;/td>
&lt;td>322&lt;/td>
&lt;td>&lt;strong>44.0%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>SWE-agent&lt;/strong>&lt;/td>
&lt;td>731&lt;/td>
&lt;td>302&lt;/td>
&lt;td>&lt;strong>41.3%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>For reference, the officially reported figure for Sonnet 4.5 is around 43.6%&lt;sup id="fnref1:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>; mini&amp;rsquo;s 44.0% aligns closely with it, which lends credibility to the present setup.&lt;/p>
&lt;/blockquote>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Per-language resolve rate" srcset="
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_385de0308e1f839c65be1f56e7d58fcb.webp 400w,
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_240e4bf4e45fc54693a0874eb7a5ba71.webp 760w,
/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/swe-agent-vs-mini-swe-agent/figures/lang_compare_hu04fac4dd4ff9f738eeed95b0b0ae5b98_87878_385de0308e1f839c65be1f56e7d58fcb.webp"
width="760"
height="380"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The minimalist mini-swe-agent is, in fact, 2.7 percentage points higher than SWE-agent. More surprisingly, &lt;strong>after SWE-agent had completed 722 of the 731 instances, its final 9 instances hung outright&lt;/strong>: the containers stayed up for 5 to 12 hours with no log activity for hours on end, and had to be killed manually (and thus scored 0). Running the very same 9 problems, mini-swe-agent exhibited no such behavior.&lt;/p>
&lt;p>For me, beyond the surprise in the numbers, the more intriguing question was why these 9 instances hung in the first place.&lt;/p>
&lt;h2 id="why-did-9-containers-hang">Why did 9 containers hang?&lt;/h2>
&lt;p>Before killing the containers, I captured the &lt;code>docker logs&lt;/code> of each one:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">INFO ... 200 OK POST /run_in_session
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">🦖 ERROR Bashlex fail: here-document at line 0 delimited by end-of-file (wanted &amp;#34;&amp;#39;EOF&amp;#39;&amp;#34;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The containers were alive and &lt;code>swerex-remote&lt;/code> was still returning &lt;code>200 OK&lt;/code>; in other words, the agent was merely spinning in place. Tracing the agent back, it was writing a large file via a heredoc:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cat &amp;gt; some_file.go &lt;span class="s">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">... a large block of Go code ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This pins down the root cause: SWE-agent&amp;rsquo;s execution backend, &lt;code>swe-rex&lt;/code>, first parses every command with &lt;code>bashlex&lt;/code> (a pure-Python bash parser) before dispatching it into the container.&lt;/p>
&lt;p>That is precisely where things break. &lt;code>bashlex&lt;/code>&amp;rsquo;s support for heredocs is incomplete; confronted with a large block-write such as &lt;code>cat &amp;lt;&amp;lt;'EOF' … a large block of code … EOF&lt;/code>, it fails outright and raises &lt;code>Bashlex fail&lt;/code>.&lt;/p>
&lt;p>Once parsing collapses, swe-rex can no longer determine whether the command finished or what its exit code was. The agent receives a malformed observation, does not recover by attempting a different approach, and simply retries the same command over and over, leaving the container hung for 5 to 12 hours.&lt;/p>
&lt;h2 id="why-does-swe-agent-bother-parsing-commands-in-the-first-place">Why does SWE-agent bother parsing commands in the first place?&lt;/h2>
&lt;p>The answer follows from its design goals. swe-rex maintains a long-lived shell session, so that state such as the working directory, environment variables, and any activated virtual environment persists across commands.&lt;/p>
&lt;p>The cost, however, is that when commands run inside a continuously flowing session, &amp;ldquo;where a command ends and what its return code is&amp;rdquo; is no longer as self-evident as it is when a standalone process exits. swe-rex must therefore rely on &lt;code>bashlex&lt;/code> to split commands and inject sentinel strings in order to recover exit codes from the output stream.&lt;/p>
&lt;p>The benefit is that, once a command has been parsed into a structured form, the backend can additionally perform safety checks, command rewriting, and other fine-grained wrapping. This is exactly the Agent-Computer Interface philosophy that SWE-agent champions; on its own terms, the design is sound, trading extra complexity for stronger session semantics.&lt;/p>
&lt;p>mini-swe-agent takes the opposite, minimalist route. It maintains no session at all; every command is handed directly to the system&amp;rsquo;s real shell through a single &lt;code>subprocess.run(shell=True)&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># minisweagent/environments/local.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shell&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># hand it to the system shell (/bin/sh -c)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cwd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">cwd&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">timeout&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stdout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">PIPE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">stderr&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">STDOUT&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This sacrifices session state (each command starts afresh, and the agent must spell out paths and environment itself), but for exactly that reason it sidesteps all the trouble of parsing bash in-process. A heredoc, however large, is the real shell&amp;rsquo;s native job; once the command finishes and the process exits, the exit code is simply there.&lt;/p>
&lt;p>As a result, the same large-file-writing command that crashes the container under SWE-agent, by hitting &lt;code>bashlex&lt;/code>&amp;rsquo;s limitation, runs uneventfully under mini-swe-agent. This is a textbook engineering trade-off: swe-rex buys stronger session semantics at the price of an additional failure surface, whereas mini forgoes the convenience of a session in exchange for a smaller and more controllable space of errors.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>Broadly speaking, this finding echoes Occam&amp;rsquo;s razor: when capability is comparable, the simpler solution is often the more effective, and arguably the more robust, one.&lt;/p>
&lt;p>That said, this is admittedly a small toy experiment. It does not establish that more complex, more sophisticated agents are necessarily worse; SWE-agent&amp;rsquo;s shortfall here is, to a large extent, dragged down by one specific bug. A carefully tuned, more elaborate agent could well surpass mini.&lt;/p>
&lt;p>These remain, for now, preliminary conjectures. In follow-up work I intend to investigate the opening question more rigorously: whether a more complete agent is genuinely worth it. Stay tuned.&lt;/p>
&lt;h2 id="appendix">Appendix&lt;/h2>
&lt;h3 id="per-language-comparison">Per-language comparison&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Language&lt;/th>
&lt;th>mini&lt;/th>
&lt;th>SWE-agent&lt;/th>
&lt;th>Winner&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>go&lt;/td>
&lt;td>95/280 = &lt;strong>34%&lt;/strong>&lt;/td>
&lt;td>78/280 = 28%&lt;/td>
&lt;td>mini +6pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>python&lt;/td>
&lt;td>139/266 = 52%&lt;/td>
&lt;td>143/266 = &lt;strong>54%&lt;/strong>&lt;/td>
&lt;td>SWE-agent +2pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>js&lt;/td>
&lt;td>77/165 = &lt;strong>47%&lt;/strong>&lt;/td>
&lt;td>73/165 = 44%&lt;/td>
&lt;td>mini +3pp&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ts&lt;/td>
&lt;td>11/20 = &lt;strong>55%&lt;/strong>&lt;/td>
&lt;td>8/20 = 40%&lt;/td>
&lt;td>mini (N=20, small sample)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>mini&amp;rsquo;s advantage comes almost entirely from Go, where it leads by 6 percentage points (17 problems); within Go, a single repository, &lt;code>gravitational/teleport&lt;/code>, accounts for most of it (16 solved only by mini versus 5 only by SWE-agent). This is unsurprising: Go problems tend to involve large, heavily modified repositories, which is precisely where SWE-agent&amp;rsquo;s heredoc hang is most likely to be triggered. On Python, by contrast, SWE-agent is actually 2 points higher.&lt;/p>
&lt;h3 id="paired-significance">Paired significance&lt;/h3>
&lt;p>Aligning all 731 problems by &lt;code>instance_id&lt;/code> yields four categories:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Count&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Both solved&lt;/td>
&lt;td>245&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Only mini&lt;/td>
&lt;td>77&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Only SWE-agent&lt;/td>
&lt;td>57&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Neither&lt;/td>
&lt;td>352&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>What actually separates the two are the 134 problems solved by exactly one side: 77 for mini and 57 for SWE-agent. The tilt favors mini, but McNemar&amp;rsquo;s exact test yields p = 0.10, which is not significant. More telling are the other two categories: 245 problems solved by both and 352 solved by neither, indicating that the two scaffolds cover a highly overlapping set of problems.&lt;/p>
&lt;h3 id="fairness-accounting-for-the-hangs">Fairness accounting for the hangs&lt;/h3>
&lt;p>Finally, a fairness check. Of the 9 hung instances (5 from flipt, 2 from teleport, and one each from vuls and tutanota), only 2 constitute genuinely &amp;ldquo;unfair&amp;rdquo; losses, i.e., problems that mini solved but on which SWE-agent was scored 0 purely because it hung: &lt;code>vuls e4728e38&lt;/code> and &lt;code>teleport 47530e1f&lt;/code>. Even crediting those 2 back, SWE-agent rises only from 302 to 304 (41.6%), while mini remains at 44.0%; the gap narrows but the &amp;ldquo;not significant&amp;rdquo; conclusion is unchanged. Moreover, the robustness of the execution backend is itself part of an agent&amp;rsquo;s end-to-end capability, so scoring 0 is not unfair under a &amp;ldquo;whole-scaffold&amp;rdquo; evaluation.&lt;/p>
&lt;/div>
&lt;script>
(function(){
function getInitialLang(){
try{
var q=new URL(window.location.href).searchParams.get('lang');
if(q==='en'||q==='zh')return q;
var s=localStorage.getItem('li_lang');
if(s==='en'||s==='zh')return s;
}catch(_){}
var n=(navigator.language||navigator.userLanguage||'en').toLowerCase();
return n.indexOf('zh')===0?'zh':'en';
}
function setLang(lang){
if(lang!=='en'&amp;&amp;lang!=='zh')lang='en';
document.body.setAttribute('data-li-lang',lang);
try{localStorage.setItem('li_lang',lang);}catch(_){}
try{var url=new URL(window.location.href);url.searchParams.set('lang',lang);window.history.replaceState({},'',url.toString());}catch(_){}
document.querySelectorAll('.li-lang-bar [data-lilang]').forEach(function(b){
b.classList.toggle('active',b.getAttribute('data-lilang')===lang);
});
}
window.__setLILang=setLang;
setLang(getInitialLang());
})();
&lt;/script>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>SWE-bench Pro, &lt;a href="https://arxiv.org/abs/2509.16941" target="_blank" rel="noopener">https://arxiv.org/abs/2509.16941&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&amp;#160;&lt;a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>利用 SKILL让 Agent 自动筛选 &amp; 解读 Huggingface 的每日论文</title><link>https://geyuyao.com/post/auto_paper_reader/</link><pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/auto_paper_reader/</guid><description>&lt;p style="display:flex;gap:16px;flex-wrap:wrap;align-items:center;justify-content:center;margin:10px 0 30px;">
&lt;a href="https://github.com/YuyaoGe/Paper_Agent_Skill" target="_blank" rel="noopener">
&lt;img src="https://img.shields.io/badge/SKILL-2563EB?style=for-the-badge&amp;logo=github&amp;logoColor=white" alt="SKILL" style="height:56px;">
&lt;/a>
&lt;a href="https://yuyaoge.github.io/paper_reader/" target="_blank" rel="noopener">
&lt;img src="https://img.shields.io/badge/WebSite-16A34A?style=for-the-badge&amp;logo=googlechrome&amp;logoColor=white" alt="WebSite" style="height:56px;">
&lt;/a>
&lt;/p>
&lt;style>
.li-lang-bar{display:flex;justify-content:flex-end;gap:8px;margin:0 0 20px 0;}
.li-lang-bar button{border:1px solid rgba(127,127,127,.35);background:transparent;color:inherit;padding:4px 14px;border-radius:0;font-size:13px;cursor:pointer;transition:all .15s ease;}
.li-lang-bar button:hover{background:rgba(127,127,127,.12);}
.li-lang-bar button.active{background:#2563eb;color:#fff;border-color:#2563eb;}
/* 默认仅显示英文，待 JS 决定语言后再切换，避免双语闪烁 */
.li-lang-zh{display:none;}
body[data-li-lang="zh"] .li-lang-zh{display:block;}
body[data-li-lang="zh"] .li-lang-en{display:none;}
body[data-li-lang="en"] .li-lang-zh{display:none;}
body[data-li-lang="en"] .li-lang-en{display:block;}
&lt;/style>
&lt;script>
/* 尽早设置语言，避免用户看到双语闪烁 */
(function(){
try{
var lang=null;
try{var q=new URL(window.location.href).searchParams.get('lang');if(q==='en'||q==='zh')lang=q;}catch(_){}
if(!lang){try{var s=localStorage.getItem('li_lang');if(s==='en'||s==='zh')lang=s;}catch(_){}}
if(!lang){var n=(navigator.language||navigator.userLanguage||'en').toLowerCase();lang=n.indexOf('zh')===0?'zh':'en';}
if(document.body){document.body.setAttribute('data-li-lang',lang);}
else{document.documentElement.setAttribute('data-li-lang',lang);document.addEventListener('DOMContentLoaded',function(){document.body.setAttribute('data-li-lang',lang);});}
}catch(_){}
})();
&lt;/script>
&lt;div class="li-lang-bar">
&lt;button type="button" data-lilang="zh" onclick="window.__setLILang &amp;&amp; window.__setLILang('zh')">中文&lt;/button>
&lt;button type="button" data-lilang="en" onclick="window.__setLILang &amp;&amp; window.__setLILang('en')">English&lt;/button>
&lt;/div>
&lt;div class="li-lang-zh" markdown="1">
&lt;h2 id="起因">起因&lt;/h2>
&lt;p>作为研究生，我们每天都要读很多论文。但除了读论文本身，&lt;strong>挑选论文同样很耗费时间和精力&lt;/strong>。&lt;/p>
&lt;p>能帮忙分析论文的软件其实不少，比如：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;a href="https://www.alphaxiv.org/" target="_blank" rel="noopener">AlphaXiv&lt;/a>&lt;/strong>：可以非常系统地精读某一篇论文。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://papers.cool/" target="_blank" rel="noopener">papers.cool&lt;/a>&lt;/strong>：由&lt;a href="https://kexue.fm/" target="_blank" rel="noopener">苏神&lt;/a>开发，每天爬取 arXiv 新论文，用 Kimi 给出中文解读，并支持在 Kimi 里继续追问、深入分析。&lt;/li>
&lt;/ol>
&lt;p>尽管这些工具在论文解读上做得很深入，但它们有一个共同的缺点：&lt;strong>没有起到筛选的作用&lt;/strong>。它们能把某一篇论文读得很细，可“从每天几十篇里挑出值得读的”仍然得我自己来做，它们也不会帮我打标签。此外，更麻烦的是，即便发现一篇不错的论文、想 follow 它的工作，也常常会发现它的 GitHub repo 是空的，甚至根本没有链接，最后白忙活一场。&lt;/p>
&lt;p>这样的沉没成本其实很高：follow 一篇论文，可能写了很久的代码，最后才发现某个输入对不上，或者某一步根本复现不了。&lt;/p>
&lt;p>所以我想把这个工具做得真正有用、能投入真正使用，可以把时间花在有意义的工作上。&lt;/p>
&lt;h1 id="思路">思路&lt;/h1>
&lt;h2 id="需求">需求&lt;/h2>
&lt;p>具体来说，我希望它能帮我筛选每天 &lt;a href="https://huggingface.co/papers" target="_blank" rel="noopener">HuggingFace Daily Papers&lt;/a> 里的论文，并且能按分类整理好。&lt;/p>
&lt;blockquote>
&lt;p>Hugginface daily paper中的论文是论文作者自主上传的，这种积极性使得相比于arXiv，daily paper中的论文的完善度、可信度和质量更高&lt;/p>
&lt;/blockquote>
&lt;p>这个产品要做两件事：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>自动分类&lt;/strong>：为每篇论文打上标签。&lt;/li>
&lt;li>&lt;strong>验证论文的真实性，以及“容易 follow”的程度&lt;/strong>。&lt;/li>
&lt;li>&lt;strong>自动生成论文摘要&lt;/strong>（类似于&lt;a href="https://papers.cool/" target="_blank" rel="noopener">papers.cool&lt;/a>）&lt;/li>
&lt;/ol>
&lt;p>其中“容易 follow”，定义为：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>(a)&lt;/strong> 论文应该对应有 GitHub 的 repo；&lt;/li>
&lt;li>&lt;strong>(b)&lt;/strong> repo 里的代码必须是完善的——比如有些 repo 里只有一个 README，由于难以复现，因此应该被排除；&lt;/li>
&lt;li>&lt;strong>(c)&lt;/strong> 数据集等资源也应是开源的。&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="HuggingFace Daily Papers 每日列表" srcset="
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_e1e3e9c73e64b5b7c5c3a39df7b3933a.webp 400w,
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_5a6b0d89873c23f7049f285a2061e7f2.webp 760w,
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_e1e3e9c73e64b5b7c5c3a39df7b3933a.webp"
width="760"
height="464"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>HuggingFace Daily Papers：每天几十篇论文需要我们自己点进去逐个挑选&lt;/em>&lt;/p>
&lt;h2 id="tex源码-or-pdf">Tex源码 or PDF&lt;/h2>
&lt;p>关于论文分析的真实性和技术实现，我有两点考虑：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>真实性&lt;/strong>：论文发表的单位应当是frontier的高校/机构&lt;/li>
&lt;li>&lt;strong>流程&lt;/strong>：为了便于分析，应该让 Agent 直接读取论文的 &lt;strong>tex 源码&lt;/strong>，而不是PDF。&lt;/li>
&lt;/ol>
&lt;p>之所以不建议读 PDF，是因为 PDF 在解析时容易出现各种问题，而且也难以进行字符串匹配（比如要在正文里找 &lt;code>github.com/&lt;/code> 这样的链接）。&lt;/p>
&lt;hr>
&lt;h1 id="实现">实现&lt;/h1>
&lt;h2 id="先python初筛再交给-agent-自主执行">先Python初筛，再交给 Agent 自主执行&lt;/h2>
&lt;p>我希望它每天自动爬取，让我无感地拿到当天的论文。整体分两步：&lt;strong>先用 Python 脚本初筛，再交给 Agent 做判断和整理&lt;/strong>。&lt;/p>
&lt;p>对于初筛，HuggingFace 有公开接口，按日期就能取到当天列表，所以我写了个零依赖脚本 &lt;a href="https://github.com/YuyaoGe/Paper_Agent_Skill/blob/main/scripts/fetch_hf_papers.py" target="_blank" rel="noopener">&lt;code>fetch_hf_papers.py&lt;/code>&lt;/a>，用关键词规则粗筛一遍：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># scripts/fetch_hf_papers.py —— 直接调用 HF 公开接口，无需 API Key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;https://huggingface.co/api/daily_papers?date=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">date_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 标题命中这些关键词 → 排除&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">TITLE_EXCLUDE_KEYWORDS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;benchmark&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;benchmarking&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;bench&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;speech&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;audio&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;video&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;3d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;compiler&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;cuda&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;kernel&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;triton&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tpu&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;xla&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;quantization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;quantisation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;distillation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 摘要必须命中其一 → 确认是 LLM/VLM 领域&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ABSTRACT_REQUIRE_ANY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;large language model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;llm&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;vision language model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;vlm&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;multimodal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;reasoning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;reinforcement learning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;instruction tuning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;fine-tuning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;alignment&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;chain-of-thought&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;in-context learning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>只需纯标准库（&lt;code>urllib&lt;/code> + &lt;code>json&lt;/code>）就够，且不需要 API key。这一步可以把把几十篇筛选到十几篇，剩下的论文需要留给 Agent 来盘。&lt;/p>
&lt;p>其次是对论文的判断&amp;amp;分析。
考虑到目前的模型已经可以很好的平衡指令遵循能力与成本，因此决定不做过多的harmness，而是全权交给Agent自主判断。
为此，我将需求写为 &lt;a href="https://github.com/YuyaoGe/Paper_Agent_Skill/blob/main/SKILL.md" target="_blank" rel="noopener">Skill&lt;/a>。&lt;/p>
&lt;hr>
&lt;h2 id="skill-pipline-design">SKILL Pipline Design&lt;/h2>
&lt;p>SKILL将每篇候选论文分为三个步骤：&lt;/p>
&lt;p>&lt;strong>第一步&lt;/strong>，提取 GitHub 链接：优先用 HF 接口的 &lt;code>githubRepo&lt;/code> 字段，如果此字段为空，就去 arXiv 的 tex 源码里检索 &lt;code>github.com/&lt;/code>。&lt;/p>
&lt;p>&lt;strong>第二步&lt;/strong>，调用 GitHub Contents API 验证仓库里有没有实质代码：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">API: https://api.github.com/repos/{owner}/{repo}/contents
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">保留（满足其一）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - 根目录有 .py / .sh / .ipynb 文件
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - 有 src / scripts / train / model / code 等目录
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">丢弃（命中其一）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - 只有 README.md / LICENSE / assets 这类非代码文件
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - API 返回 404（仓库不存在或为空）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - 仓库名 / 描述含 &amp;#34;coming-soon&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>第三步&lt;/strong>，写一段&lt;strong>一眼就能看懂&lt;/strong>的中文摘要，再从一套固定标签里打标签以便筛选：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">RL · 微调 · 无需训练 · 长文本 · VLM · MeM(Agent记忆) · API · 扩散模型
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最后落成一条 JSON：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2026-03-12&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Prism-Δ: Differential Subspace Steering for Prompt Highlighting in Large Language Models&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;arxiv_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2603.10705&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;github&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://github.com/YuyaoGe/PRISM-DELTA&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;abstract&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;PRISM-Δ 是一种提示高亮方法，使 LLM 在生成时优先关注用户指定的文本片段。核心思路是分解正负交叉协方差矩阵的差值以最大化判别能量、消除共享方向，每个注意力头获得连续 softplus 重要性权重（弱但有用的头以降低强度贡献），并扩展到 Value 表示以捕获内容通道信号。在 4 个基准、5 个模型上，PRISM-Δ 在 20 个配置中的 19 个匹配或超越最佳现有方法，相对增益最高 +10.6%，流畅度损失减半，长文本检索场景相对增益最高 +4.8%。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;tags&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;无需训练&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="harmness-engineering-design">Harmness Engineering Design&lt;/h2>
&lt;p>有了SKILL接下来就是设计 Agent (或者是Subagent) 与 SKILL 的调用关系。&lt;/p>
&lt;p>这里两个选择：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>主从调度&lt;/strong>：一个主 Agent 去调度多个子 Agent&lt;/li>
&lt;li>&lt;strong>并行调度&lt;/strong>：每天各起一个独立 Agent&lt;/li>
&lt;/ul>
&lt;p>对于主从调度，我使用OpenClaw实现，最大subagent数设置为5。&lt;/p>
&lt;p>然而经常出现超时的问题，具体而言，让claw调研某 10 天的论文，尽管它会起多个 sub-agent，但超时&amp;amp;超出上下文的问题频频出现，极不稳定。&lt;/p>
&lt;p>因此，后来选择了后者的方案：每天一个独立 Agent 并行跑，各自写一个 JSON，最后用主程序合并。一天生成一个论文列表，事实证明，越简单越稳定。&lt;/p>
&lt;p>并行用 &lt;code>xargs -P&lt;/code> 就够：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># backfill_papers.sh —— 批量补录历史日期，默认并发 6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;%s\n&amp;#39;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">MISSING&lt;/span>&lt;span class="p">[@]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="p">|&lt;/span> xargs -P &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CONCURRENCY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -I&lt;span class="o">{}&lt;/span> bash &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SCRIPT_DIR&lt;/span>&lt;span class="s2">/run_kimi_one_day.sh&amp;#34;&lt;/span> &lt;span class="o">{}&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PAPER_READER_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>合并脚本 &lt;code>merge_batches.py&lt;/code> 也只做确定的事：扫 &lt;code>paper_batches/*.json&lt;/code>，跳过已有日期，按日期把缺的追加进去。&lt;/p>
&lt;h2 id="关于agent框架的选择">关于Agent框架的选择&lt;/h2>
&lt;p>选 Agent 有个硬条件：&lt;strong>能在命令行非交互式启动&lt;/strong>，而不是用进入终端手动操作。&lt;/p>
&lt;p>比如：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cursor &amp;amp; Claude Code&lt;/strong>：需要进GUI界面或者终端操作&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://moonshotai.github.io/kimi-cli/" target="_blank" rel="noopener">Kimi CLI&lt;/a>&lt;/strong>：可以将 prompt 作为CLI启动命令中的一个形参，可以很方便的调用，而且KIMI价格便宜&lt;/li>
&lt;/ul>
&lt;p>所以对于每一天的处理就是一行命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># run_kimi_one_day.sh —— 用 Kimi CLI 处理单天，结果写入 batch JSON&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kimi --print --quiet &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --work-dir &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PAPER_READER_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --add-dir /Users/yuyaoge/Project/Paper_Agent_Skill &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PROMPT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &amp;gt; &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOG_FILE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 2&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>尽管如此，目前还是需要每天手动启动工作流，我们希望可以对于用户无感运行。因此，希望可以设置一个适配于Macos的自动启动脚本。&lt;/p>
&lt;h2 id="在macos上的自动启动脚本">在Macos上的自动启动脚本&lt;/h2>
&lt;p>自动脚本用 macOS 的 &lt;code>launchd&lt;/code>，配置 &lt;code>com.yuyaoge.paper-daily-fetch.plist&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- 登录 / load 时立即跑一次 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;key&amp;gt;&lt;/span>RunAtLoad&lt;span class="nt">&amp;lt;/key&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;true/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- 之后每 2 小时再跑一次 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;key&amp;gt;&lt;/span>StartInterval&lt;span class="nt">&amp;lt;/key&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;integer&amp;gt;&lt;/span>7200&lt;span class="nt">&amp;lt;/integer&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>daily_fetch.sh&lt;/code> 里有两个Feature值得一提：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>不处理今日论文&lt;/strong>：HuggingFace 在当天是会根据用户的上传而实时更新的，当天爬会漏掉当前时间点后面提交的论文。所以默认抓“昨天往前数 7 天”，而不包括当天的论文，顺便也补上关机那几天的论文。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>幂等&lt;/strong>：不应该每日定时启动，因此不确定所定的时间点是否已经开机。因此，设定为自开机后，每 2 小时跑一次，如果已有结果就跳过，但若是空结果先执行一次；如果git没变化就不 push。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="quick-start">Quick Start&lt;/h1>
&lt;blockquote>
&lt;p>&lt;strong>环境要求&lt;/strong>：macOS、Python 3，以及已安装并登录的 &lt;a href="https://moonshotai.github.io/kimi-cli/" target="_blank" rel="noopener">Kimi CLI&lt;/a>。&lt;/p>
&lt;/blockquote>
&lt;p>&lt;strong>1. 克隆仓库&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/YuyaoGe/Paper_Agent_Skill.git &lt;span class="c1"># Skill + 脚本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone https://github.com/YuyaoGe/paper_reader.git &lt;span class="c1"># 数据 + 前端&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. 安装 Skill 到 Kimi&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> Paper_Agent_Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir -p ~/.kimi/skills
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ln -sfn &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PWD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> ~/.kimi/skills/hf-paper-filter
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. 手动验证链路&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># run_kimi_one_day.sh YYYY-MM-DD [paper_reader 路径]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./scripts/run_kimi_one_day.sh 2026-06-01 /path/to/paper_reader
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>4.（可选）批量补录历史区间&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># backfill_papers.sh 起始日期 结束日期 [并发数] [paper_reader 路径]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./scripts/backfill_papers.sh 2026-04-25 2026-05-26 &lt;span class="m">6&lt;/span> /path/to/paper_reader
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 ./scripts/merge_batches.py /path/to/paper_reader
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>5. 安装定时任务，实现无人值守&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cp scripts/com.yuyaoge.paper-daily-fetch.plist ~/Library/LaunchAgents/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">launchctl load -w ~/Library/LaunchAgents/com.yuyaoge.paper-daily-fetch.plist
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h1 id="前端展示">前端展示&lt;/h1>
&lt;p>最终列表汇总到 &lt;code>paper_list.md&lt;/code> 中，以便于 Agent 可以很方便的在文件末尾追加，同时易于前端解析。&lt;/p>
&lt;p>&lt;a href="https://yuyaoge.github.io/paper_reader/" target="_blank" rel="noopener">前端&lt;/a> 设计为纯静态页面，运行时把 Markdown 拉下来解析成卡片，支持按标签筛、按日期检索：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-js" data-lang="js">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// 前端运行时直接拉取 Markdown 数据源并解析
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">fetch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;paper_list.md&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// 每条格式：- **Title** `[Tag]` — [id](url) | [GitHub](url)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// &amp;gt; 中文摘要
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">currentPapers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">push&lt;/span>&lt;span class="p">({&lt;/span> &lt;span class="nx">title&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">tags&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">links&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">desc&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>托管在 GitHub Pages，定时脚本每天把更新后的 &lt;code>paper_list.md&lt;/code> push 到云端，页面同步更新。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="paper_reader 界面" srcset="
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_37c8ed392cc707c0b52f7778a03fa896.webp 400w,
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_ca258df559b5167a6518656aa5b65f4c.webp 760w,
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_37c8ed392cc707c0b52f7778a03fa896.webp"
width="760"
height="612"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>paper_reader：筛选、打标签、生成中文摘要后的样子，可以按标签筛选、按日期排序。&lt;/em>&lt;/p>
&lt;h1 id="整体流程">整体流程&lt;/h1>
&lt;p>综上，整条流程如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> macOS launchd ──▶ daily_fetch.sh （每 2h 触发，幂等）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ 按天拆分，并行
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> run_kimi_one_day.sh × N (xargs -P 6)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ Kimi CLI 加载 hf-paper-filter Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ fetch_hf_papers.py Python 初筛
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ GitHub Contents API 验证有无代码
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ 写中文摘要 + 打标签
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ 每天一个 JSON
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paper_batches/YYYY-MM-DD.json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ merge_batches.py 合并
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paper_list.md ──git push──▶ GitHub Pages（前端 fetch 渲染）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>用到的东西也都很常规：Python 标准库做初筛、Kimi CLI 做判断、&lt;code>xargs -P&lt;/code> 并行、&lt;code>launchd&lt;/code> 定时、一个 &lt;code>paper_list.md&lt;/code> 当数据源、一个静态页面做展示。&lt;/p>
&lt;!-- # 项目链接
- Agent Skill（核心逻辑）：[github.com/YuyaoGe/Paper_Agent_Skill](https://github.com/YuyaoGe/Paper_Agent_Skill)
- 前端展示源码：[github.com/YuyaoGe/paper_reader](https://github.com/YuyaoGe/paper_reader)
- 在线 Demo：[yuyaoge.github.io/paper_reader](https://yuyaoge.github.io/paper_reader/)
- 依赖工具：[Kimi CLI](https://moonshotai.github.io/kimi-cli/) · [HuggingFace Daily Papers](https://huggingface.co/papers) -->
&lt;/div>
&lt;div class="li-lang-en" markdown="1">
&lt;h2 id="motivation">Motivation&lt;/h2>
&lt;p>As graduate students, we read a lot of papers every day. But beyond reading the papers themselves, &lt;strong>deciding which papers to read is just as time- and energy-consuming&lt;/strong>.&lt;/p>
&lt;p>There is no shortage of tools for analyzing papers, for example:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;a href="https://www.alphaxiv.org/" target="_blank" rel="noopener">AlphaXiv&lt;/a>&lt;/strong>: reads a single paper very systematically.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://papers.cool/" target="_blank" rel="noopener">papers.cool&lt;/a>&lt;/strong>: built by &lt;a href="https://kexue.fm/" target="_blank" rel="noopener">Su Jianlin&lt;/a>; it crawls new arXiv papers daily, uses Kimi to produce Chinese explanations, and lets you keep asking follow-up questions inside Kimi.&lt;/li>
&lt;/ol>
&lt;p>These tools go deep on &lt;em>reading&lt;/em> a paper, but they share one shortcoming: &lt;strong>they do not help with filtering&lt;/strong>. They can read a given paper in great detail, yet &amp;ldquo;picking the few worth reading out of the dozens each day&amp;rdquo; is still on me, and they will not tag papers either. Worse, even when I find a promising paper and want to follow up on its work, I often discover that its GitHub repo is empty, or that there is no link at all — and the effort is wasted.&lt;/p>
&lt;p>The sunk cost here is high: when following a paper, I might write code for a long time only to find that some input does not match, or that a reproduction step simply does not work.&lt;/p>
&lt;p>So I wanted to build something genuinely useful and actually usable in daily work, so that time goes to work that matters.&lt;/p>
&lt;h1 id="idea">Idea&lt;/h1>
&lt;h2 id="requirements">Requirements&lt;/h2>
&lt;p>Concretely, I want it to filter the papers in &lt;a href="https://huggingface.co/papers" target="_blank" rel="noopener">HuggingFace Daily Papers&lt;/a> every day, and organize them by category.&lt;/p>
&lt;blockquote>
&lt;p>Papers in HuggingFace Daily Papers are submitted by the authors themselves. That initiative tends to make daily-paper submissions more complete, more credible, and higher in quality than arXiv at large.&lt;/p>
&lt;/blockquote>
&lt;p>The product needs to do three things:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Auto-classification&lt;/strong>: tag every paper.&lt;/li>
&lt;li>&lt;strong>Verify a paper&amp;rsquo;s authenticity and how &amp;ldquo;easy to follow&amp;rdquo; it is&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>Auto-generate a paper summary&lt;/strong> (similar to &lt;a href="https://papers.cool/" target="_blank" rel="noopener">papers.cool&lt;/a>).&lt;/li>
&lt;/ol>
&lt;p>Here &amp;ldquo;easy to follow&amp;rdquo; is defined as:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>(a)&lt;/strong> the paper should have a corresponding GitHub repo;&lt;/li>
&lt;li>&lt;strong>(b)&lt;/strong> the code in that repo must be substantial — a repo with only a README, for instance, is hard to reproduce and should be excluded;&lt;/li>
&lt;li>&lt;strong>(c)&lt;/strong> datasets and other resources should be open-sourced as well.&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="HuggingFace Daily Papers list" srcset="
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_e1e3e9c73e64b5b7c5c3a39df7b3933a.webp 400w,
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_5a6b0d89873c23f7049f285a2061e7f2.webp 760w,
/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/auto_paper_reader/figures/hf_huc3ea2232ca5d15f85d999e66ebff611e_1555544_e1e3e9c73e64b5b7c5c3a39df7b3933a.webp"
width="760"
height="464"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>HuggingFace Daily Papers: dozens of papers a day that you have to click into and sift through one by one.&lt;/em>&lt;/p>
&lt;h2 id="tex-source-vs-pdf">Tex Source vs. PDF&lt;/h2>
&lt;p>On authenticity and implementation, I had two considerations:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Authenticity&lt;/strong>: the publishing institution should be a frontier university / lab.&lt;/li>
&lt;li>&lt;strong>Pipeline&lt;/strong>: for ease of analysis, the Agent should read the paper&amp;rsquo;s &lt;strong>tex source&lt;/strong> directly rather than the PDF.&lt;/li>
&lt;/ol>
&lt;p>The reason to avoid PDFs is that PDF parsing breaks in all sorts of ways, and string matching is hard (e.g., searching the body for a &lt;code>github.com/&lt;/code> link).&lt;/p>
&lt;hr>
&lt;h1 id="implementation">Implementation&lt;/h1>
&lt;h2 id="python-pre-filter-first-then-hand-off-to-the-agent">Python Pre-filter First, Then Hand Off to the Agent&lt;/h2>
&lt;p>I want it to crawl automatically every day, so I get the day&amp;rsquo;s papers effortlessly. The whole thing is two steps: &lt;strong>a Python script does a coarse pre-filter first, then an Agent handles judgment and organizing&lt;/strong>.&lt;/p>
&lt;p>For the pre-filter: HuggingFace has a public API, and you can fetch a given day&amp;rsquo;s list by date, so I wrote a zero-dependency script &lt;a href="https://github.com/YuyaoGe/Paper_Agent_Skill/blob/main/scripts/fetch_hf_papers.py" target="_blank" rel="noopener">&lt;code>fetch_hf_papers.py&lt;/code>&lt;/a> that filters coarsely by keyword rules:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># scripts/fetch_hf_papers.py — call the public HF API directly, no API key needed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;https://huggingface.co/api/daily_papers?date=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">date_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Titles matching these keywords → excluded&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">TITLE_EXCLUDE_KEYWORDS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;benchmark&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;benchmarking&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;bench&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;speech&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;audio&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;video&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;3d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;compiler&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;cuda&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;kernel&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;triton&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tpu&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;xla&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;quantization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;quantisation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;distillation&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Abstract must match at least one → confirm it is in the LLM/VLM space&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ABSTRACT_REQUIRE_ANY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;large language model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;llm&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;vision language model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;vlm&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;multimodal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;reasoning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;reinforcement learning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;instruction tuning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;fine-tuning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;alignment&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;chain-of-thought&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;in-context learning&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The standard library (&lt;code>urllib&lt;/code> + &lt;code>json&lt;/code>) is enough, and no API key is needed. This step narrows dozens of papers down to a dozen or so; the rest is left for the Agent to weigh.&lt;/p>
&lt;p>Next comes judging and analyzing the papers. Since today&amp;rsquo;s models already balance instruction-following and cost well, I decided not to add much harness and instead hand full judgment to the Agent. To that end, I wrote the requirements as a &lt;a href="https://github.com/YuyaoGe/Paper_Agent_Skill/blob/main/SKILL.md" target="_blank" rel="noopener">Skill&lt;/a>.&lt;/p>
&lt;hr>
&lt;h2 id="skill-pipeline-design">SKILL Pipeline Design&lt;/h2>
&lt;p>The SKILL splits each candidate paper into three steps:&lt;/p>
&lt;p>&lt;strong>Step 1&lt;/strong>, extract the GitHub link: prefer the &lt;code>githubRepo&lt;/code> field from the HF API; if it is empty, search the paper&amp;rsquo;s arXiv tex source for &lt;code>github.com/&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Step 2&lt;/strong>, call the GitHub Contents API to verify whether the repo has substantial code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">API: https://api.github.com/repos/{owner}/{repo}/contents
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Keep (any one of):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - .py / .sh / .ipynb files in the repo root
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - directories such as src / scripts / train / model / code
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Drop (any one of):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - only non-code files like README.md / LICENSE / assets
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - API returns 404 (repo missing or empty)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> - repo name / description contains &amp;#34;coming-soon&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Step 3&lt;/strong>, write a concise summary that is &lt;strong>understandable at a glance&lt;/strong>, then assign tags from a fixed set (so the frontend can filter):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">RL · Fine-tuning · Training-free · Long-context · VLM · MeM (Agent Memory) · API · Diffusion
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally it lands as one JSON record:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2026-03-12&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Prism-Δ: Differential Subspace Steering for Prompt Highlighting in Large Language Models&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;arxiv_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2603.10705&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;github&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://github.com/YuyaoGe/PRISM-DELTA&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;abstract&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;PRISM-Δ is a prompt-highlighting method that makes an LLM prioritize user-specified text spans during generation. The core idea is to decompose the difference between the positive and negative cross-covariance matrices to maximize discriminative energy and eliminate shared directions; each attention head gets a continuous softplus importance weight (weak-but-useful heads contribute at reduced strength), and the method is extended to the Value representation to capture content-channel signals. Across 4 benchmarks and 5 models, PRISM-Δ matches or surpasses the best existing methods in 19 of 20 configurations, with relative gains up to +10.6%, fluency loss halved, and up to +4.8% relative gain in long-context retrieval.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;tags&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;Training-free&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="agent-orchestration-design">Agent Orchestration Design&lt;/h2>
&lt;p>With the SKILL in place, the next question is the calling relationship between the Agent (or Subagent) and the SKILL.&lt;/p>
&lt;p>There are two choices:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Master–worker&lt;/strong>: one master Agent dispatches multiple sub-Agents.&lt;/li>
&lt;li>&lt;strong>Parallel&lt;/strong>: spin up an independent Agent for each day.&lt;/li>
&lt;/ul>
&lt;p>For master–worker, I implemented it with OpenClaw, capping sub-agents at 5. But timeouts kept happening: asking Claw to survey, say, 10 days of papers, it would launch several sub-agents, yet timeouts and context overruns appeared constantly — very unstable.&lt;/p>
&lt;p>So I went with the latter: one independent Agent per day, running in parallel, each writing its own JSON, then a main program merges them. One paper list per day — and as it turns out, the simpler it is, the more stable.&lt;/p>
&lt;p>Parallelism is just &lt;code>xargs -P&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># backfill_papers.sh — batch-backfill historical dates, default concurrency 6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;%s\n&amp;#39;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">MISSING&lt;/span>&lt;span class="p">[@]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="p">|&lt;/span> xargs -P &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CONCURRENCY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -I&lt;span class="o">{}&lt;/span> bash &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SCRIPT_DIR&lt;/span>&lt;span class="s2">/run_kimi_one_day.sh&amp;#34;&lt;/span> &lt;span class="o">{}&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PAPER_READER_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The merge script &lt;code>merge_batches.py&lt;/code> also only does deterministic work: scan &lt;code>paper_batches/*.json&lt;/code>, skip dates already present, and append the missing ones in date order.&lt;/p>
&lt;h2 id="choosing-the-agent-framework">Choosing the Agent Framework&lt;/h2>
&lt;p>There is one hard requirement for the Agent: &lt;strong>it must launch non-interactively from the command line&lt;/strong>, not require manual operation in a terminal.&lt;/p>
&lt;p>For example:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cursor &amp;amp; Claude Code&lt;/strong>: require a GUI or terminal interaction.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://moonshotai.github.io/kimi-cli/" target="_blank" rel="noopener">Kimi CLI&lt;/a>&lt;/strong>: lets you pass the prompt as an argument to the launch command — easy to invoke, and Kimi is cheap.&lt;/li>
&lt;/ul>
&lt;p>So processing a single day is one line:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># run_kimi_one_day.sh — process a single day with Kimi CLI, write the batch JSON&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">kimi --print --quiet &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --work-dir &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PAPER_READER_DIR&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --add-dir /Users/yuyaoge/Project/Paper_Agent_Skill &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PROMPT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &amp;gt; &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOG_FILE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 2&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Even so, the workflow still has to be started manually each day, whereas I want it to run transparently. Hence an auto-start script tailored for macOS.&lt;/p>
&lt;h2 id="auto-start-script-on-macos">Auto-start Script on macOS&lt;/h2>
&lt;p>The auto-start uses macOS &lt;code>launchd&lt;/code>, configured via &lt;code>com.yuyaoge.paper-daily-fetch.plist&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Run once at login / load --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;key&amp;gt;&lt;/span>RunAtLoad&lt;span class="nt">&amp;lt;/key&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;true/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Then run again every 2 hours --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;key&amp;gt;&lt;/span>StartInterval&lt;span class="nt">&amp;lt;/key&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;integer&amp;gt;&lt;/span>7200&lt;span class="nt">&amp;lt;/integer&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Two features in &lt;code>daily_fetch.sh&lt;/code> are worth mentioning:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>It does not process &amp;ldquo;today&amp;rsquo;s&amp;rdquo; papers&lt;/strong>: HuggingFace updates the same-day list in real time as authors submit, so crawling today would miss papers submitted later. By default it grabs &amp;ldquo;the 7 days before yesterday&amp;rdquo; rather than today, and conveniently backfills the days the machine was off.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Idempotency&lt;/strong>: it should not rely on a fixed daily trigger, since there is no guarantee the machine is on at that moment. So it runs every 2 hours after boot — skip if a day already has results, but run once for empty results; if git has no changes, do not push.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h1 id="quick-start-1">Quick Start&lt;/h1>
&lt;blockquote>
&lt;p>&lt;strong>Requirements&lt;/strong>: macOS, Python 3, and an installed &amp;amp; logged-in &lt;a href="https://moonshotai.github.io/kimi-cli/" target="_blank" rel="noopener">Kimi CLI&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;strong>1. Clone the repos&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">git clone https://github.com/YuyaoGe/Paper_Agent_Skill.git &lt;span class="c1"># Skill + scripts&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git clone https://github.com/YuyaoGe/paper_reader.git &lt;span class="c1"># data + frontend&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>2. Install the Skill into Kimi&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> Paper_Agent_Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir -p ~/.kimi/skills
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ln -sfn &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PWD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> ~/.kimi/skills/hf-paper-filter
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>3. Verify the pipeline manually&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># run_kimi_one_day.sh YYYY-MM-DD [paper_reader path]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./scripts/run_kimi_one_day.sh 2026-06-01 /path/to/paper_reader
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>4. (Optional) Backfill a historical range&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># backfill_papers.sh START_DATE END_DATE [CONCURRENCY] [paper_reader path]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">./scripts/backfill_papers.sh 2026-04-25 2026-05-26 &lt;span class="m">6&lt;/span> /path/to/paper_reader
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 ./scripts/merge_batches.py /path/to/paper_reader
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>5. Install the scheduled job for unattended runs&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cp scripts/com.yuyaoge.paper-daily-fetch.plist ~/Library/LaunchAgents/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">launchctl load -w ~/Library/LaunchAgents/com.yuyaoge.paper-daily-fetch.plist
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h1 id="frontend">Frontend&lt;/h1>
&lt;p>The final list is aggregated into &lt;code>paper_list.md&lt;/code>, so the Agent can easily append to the end of the file and the frontend can easily parse it.&lt;/p>
&lt;p>The &lt;a href="https://yuyaoge.github.io/paper_reader/" target="_blank" rel="noopener">frontend&lt;/a> is a pure static page: at runtime it pulls the Markdown down and parses it into cards, supporting tag filtering and date search:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-js" data-lang="js">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// The frontend fetches the Markdown data source and parses it at runtime
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">fetch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;paper_list.md&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Each entry: - **Title** `[Tag]` — [id](url) | [GitHub](url)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// &amp;gt; Chinese summary
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">currentPapers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">push&lt;/span>&lt;span class="p">({&lt;/span> &lt;span class="nx">title&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">tags&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">links&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">desc&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It is hosted on GitHub Pages; the scheduled script pushes the updated &lt;code>paper_list.md&lt;/code> to the cloud every day, and the page updates in sync.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="paper_reader UI" srcset="
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_37c8ed392cc707c0b52f7778a03fa896.webp 400w,
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_ca258df559b5167a6518656aa5b65f4c.webp 760w,
/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/auto_paper_reader/figures/paper_reader_hu9a8b7f4fe92c042fe5de7df5ae912fac_576522_37c8ed392cc707c0b52f7778a03fa896.webp"
width="760"
height="612"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>paper_reader: what it looks like after filtering, tagging, and Chinese-summary generation — filterable by tag and sortable by date.&lt;/em>&lt;/p>
&lt;h1 id="overall-pipeline">Overall Pipeline&lt;/h1>
&lt;p>Putting it all together, the full pipeline is:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> macOS launchd ──▶ daily_fetch.sh (every 2h, idempotent)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ split by day, run in parallel
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> run_kimi_one_day.sh × N (xargs -P 6)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ Kimi CLI loads the hf-paper-filter Skill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ fetch_hf_papers.py Python pre-filter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├─ GitHub Contents API verify code presence
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └─ write Chinese summary + tags
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ one JSON per day
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paper_batches/YYYY-MM-DD.json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │ merge_batches.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ▼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> paper_list.md ──git push──▶ GitHub Pages (frontend fetch + render)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The pieces are all pretty ordinary: the Python standard library for pre-filtering, Kimi CLI for judgment, &lt;code>xargs -P&lt;/code> for parallelism, &lt;code>launchd&lt;/code> for scheduling, a single &lt;code>paper_list.md&lt;/code> as the data source, and a static page for display.&lt;/p>
&lt;/div>
&lt;script>
(function(){
function getInitialLang(){
try{
var q=new URL(window.location.href).searchParams.get('lang');
if(q==='en'||q==='zh')return q;
var s=localStorage.getItem('li_lang');
if(s==='en'||s==='zh')return s;
}catch(_){}
var n=(navigator.language||navigator.userLanguage||'en').toLowerCase();
return n.indexOf('zh')===0?'zh':'en';
}
function setLang(lang){
if(lang!=='en'&amp;&amp;lang!=='zh')lang='en';
document.body.setAttribute('data-li-lang',lang);
try{localStorage.setItem('li_lang',lang);}catch(_){}
try{var url=new URL(window.location.href);url.searchParams.set('lang',lang);window.history.replaceState({},'',url.toString());}catch(_){}
document.querySelectorAll('.li-lang-bar [data-lilang]').forEach(function(b){
b.classList.toggle('active',b.getAttribute('data-lilang')===lang);
});
}
window.__setLILang=setLang;
setLang(getInitialLang());
})();
&lt;/script></description></item><item><title>Kimi K2.6: Advancing Open-Source Coding</title><link>https://geyuyao.com/publication/team2026kimi-2.6/</link><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/team2026kimi-2.6/</guid><description>&lt;p>We are open sourcing our latest model, Kimi K2.6, featuring state-of-the-art coding, long-horizon execution, and agent swarm capabilities. Kimi K2.6 is now available via Kimi.com, the Kimi App, the API, and Kimi Code.&lt;/p></description></item><item><title>PromptCD: Test-Time Behavior Enhancement via Polarity-Prompt Contrastive Decoding</title><link>https://geyuyao.com/publication/bi2026promptcd/</link><pubDate>Tue, 24 Feb 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/bi2026promptcd/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>We present PromptCD, a test-time method for controlling LLM behavior without additional training. The approach creates paired positive and negative guiding prompts for a target behavior and contrasts model responses at the token-probability level for LLMs and through visual attention patterns for VLMs. The method targets the 3H alignment objectives &amp;ndash; helpfulness, honesty, and harmlessness &amp;ndash; and demonstrates that post-trained models can achieve meaningful self-enhancement purely at test time. For vision-language models, PromptCD improves VQA performance by reinforcing behavior-consistent visual grounding. PromptCD is a simple, general, and cost-efficient strategy for reliable behavior control across modalities.&lt;/p></description></item><item><title>Kimi K2.5: Visual Agentic Intelligence</title><link>https://geyuyao.com/publication/team2026kimi/</link><pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/team2026kimi/</guid><description/></item><item><title>Gated Differentiable Working Memory for Long-Context Language Modeling</title><link>https://geyuyao.com/publication/mei2026gated/</link><pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/mei2026gated/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Long contexts challenge transformers as attention scores dilute across thousands of tokens and critical information is often lost in the middle. We reframe test-time adaptation as a budget-constrained memory consolidation problem and propose Gdwm (Gated Differentiable Working Memory), which introduces a write controller that estimates Contextual Utility, an information-theoretic measure of long-range contextual dependence, to allocate gradient steps efficiently. Experiments on ZeroSCROLLS and LongBench v2 show Gdwm achieves comparable or superior performance with 4x fewer gradient steps than uniform baselines, establishing a new efficiency-performance Pareto frontier for test-time adaptation.&lt;/p></description></item><item><title>Long-Insight: Long-running Agent Trajectory Analysis</title><link>https://geyuyao.com/project/long-insight/</link><pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate><guid>https://geyuyao.com/project/long-insight/</guid><description>&lt;style>
.li-lang-bar{
position:sticky;top:0;z-index:50;
display:flex;justify-content:flex-end;gap:8px;
padding:8px 0;margin:-8px 0 16px 0;
backdrop-filter:blur(6px);
}
.li-lang-bar button{
border:1px solid rgba(127,127,127,.35);
background:transparent;
color:inherit;
padding:4px 12px;
border-radius:999px;
font-size:13px;
cursor:pointer;
transition:all .15s ease;
}
.li-lang-bar button:hover{background:rgba(127,127,127,.12);}
.li-lang-bar button.active{
background:#667eea;color:#fff;border-color:#667eea;
}
/* Safe default: until JS decides language, show only EN to avoid flashing both sections */
.li-lang-zh{display:none;}
body[data-li-lang="zh"] .li-lang-zh{display:block;}
body[data-li-lang="zh"] .li-lang-en{display:none;}
body[data-li-lang="en"] .li-lang-zh{display:none;}
body[data-li-lang="en"] .li-lang-en{display:block;}
&lt;/style>
&lt;script>
/* Run as early as possible so the correct language div is visible before user sees the page. */
(function(){
try{
var lang = null;
try{
var url = new URL(window.location.href);
var q = url.searchParams.get('lang');
if(q === 'en' || q === 'zh') lang = q;
}catch(_){}
if(!lang){
try{
var stored = localStorage.getItem('li_lang');
if(stored === 'en' || stored === 'zh') lang = stored;
}catch(_){}
}
if(!lang){
var nav = (navigator.language || navigator.userLanguage || 'en').toLowerCase();
lang = nav.indexOf('zh') === 0 ? 'zh' : 'en';
}
if(document.body){
document.body.setAttribute('data-li-lang', lang);
} else {
document.documentElement.setAttribute('data-li-lang', lang);
document.addEventListener('DOMContentLoaded', function(){
document.body.setAttribute('data-li-lang', lang);
});
}
}catch(_){}
})();
&lt;/script>
&lt;div class="li-lang-bar">
&lt;button type="button" data-lilang="zh" onclick="window.__setLILang &amp;&amp; window.__setLILang('zh')">中文&lt;/button>
&lt;button type="button" data-lilang="en" onclick="window.__setLILang &amp;&amp; window.__setLILang('en')">English&lt;/button>
&lt;/div>
&lt;div class="li-lang-zh" markdown="1">
&lt;h1 id="long-insight长程轨迹分析平台">Long-Insight：长程轨迹分析平台&lt;/h1>
&lt;h2 id="背景当-agent-轨迹长到无法阅读">背景：当 Agent 轨迹长到无法阅读&lt;/h2>
&lt;p>当我们用前沿大模型去解决真实的软件工程任务时，它们会产生极其漫长的执行轨迹。以某 Long-running 数据集的 370 条轨迹为例：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模型&lt;/th>
&lt;th>平均 Token 数&lt;/th>
&lt;th>相当于 128K 的倍数&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Kimi-K2-0905&lt;/strong>&lt;/td>
&lt;td>6,837,594&lt;/td>
&lt;td>&lt;strong>52.1 倍&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>DeepSeek-V3.1&lt;/strong>&lt;/td>
&lt;td>5,059,423&lt;/td>
&lt;td>&lt;strong>38.5 倍&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>GLM-4.6&lt;/strong>&lt;/td>
&lt;td>2,616,703&lt;/td>
&lt;td>&lt;strong>19.9 倍&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Claude-Sonnet-4&lt;/strong>&lt;/td>
&lt;td>977,747&lt;/td>
&lt;td>&lt;strong>7.4 倍&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>一条 &lt;code>application_development&lt;/code> 类型的轨迹平均有 &lt;strong>810 万 Token&lt;/strong>，是 128K 上下文窗口的 &lt;strong>61.9 倍&lt;/strong>。370 条轨迹中&lt;strong>至少 85% 超出了任何模型的上下文窗口&lt;/strong>。&lt;/p>
&lt;p>这意味着两个现实问题：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>人无法阅读&lt;/strong> — 400+ 轮次的交互日志，无论多么耐心的工程师都无法逐行审阅&lt;/li>
&lt;li>&lt;strong>模型也无法处理&lt;/strong> — 即便是百万级上下文窗口，大多数轨迹仍然放不进去&lt;/li>
&lt;/ol>
&lt;p>但这些轨迹中蕴含着极其宝贵的信息。正如我们在 SWE SFT 数据筛选中总结的核心原则：&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>&amp;ldquo;沙子里面有金子就可以，不一定全是金子，但沙子里不能有玻璃碴。&amp;rdquo;&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>我们需要的不是盲目挑选&amp;quot;看起来好&amp;quot;的轨迹，而是&lt;strong>精确识别和过滤坏模式（bad patterns）&lt;/strong>。为此，我们需要一套工具来&lt;strong>理解&lt;/strong>这些超长轨迹在做什么、做得好不好。&lt;/p>
&lt;p>这就是 Long-Insight 的由来。&lt;/p>
&lt;h2 id="核心思路">核心思路&lt;/h2>
&lt;p>Long-Insight 解决三个问题：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>看不懂&lt;/strong> → 将线性轨迹分解为结构化的步骤 DAG，每个步骤都有类型、摘要、父子依赖&lt;/li>
&lt;li>&lt;strong>放不下&lt;/strong> → 智能压缩轨迹，在保留因果结构的前提下减少 60–80% 的 Token&lt;/li>
&lt;li>&lt;strong>评不了&lt;/strong> → 两阶段 LLM 自动评分，量化轨迹的难度和质量&lt;/li>
&lt;/ol>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="启发" srcset="
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_9cafd98d00676ed5f3924480c73b0ab9.webp 400w,
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_f6dfbafd07a75b25d3eb2b8ee98a13af.webp 760w,
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_9cafd98d00676ed5f3924480c73b0ab9.webp"
width="760"
height="427"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;hr>
&lt;h2 id="第一部分轨迹步骤分解">第一部分：轨迹步骤分解&lt;/h2>
&lt;h3 id="设计思路">设计思路&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>初始化&lt;/strong>：创建空的 JSON 文件&lt;/li>
&lt;li>&lt;strong>循环&lt;/strong>：逐个读取轨迹 turn → 调用 LLM 分析 → 判断&amp;quot;新步骤&amp;quot;还是&amp;quot;续写&amp;quot; → 更新步骤 DAG&lt;/li>
&lt;li>&lt;strong>结束&lt;/strong>：得到完整的步骤划分 JSON，包含 8 种步骤类型、因果叙述和父子依赖关系&lt;/li>
&lt;/ul>
&lt;p>每个步骤被分类为：任务理解、项目探索、环境准备、代码实现、测试验证、问题调试、文档记录、总结规划。&lt;/p>
&lt;h3 id="宏观分析">宏观分析&lt;/h3>
&lt;p>以一条 Sonnet 4.5 在 SWE-bench 上的轨迹为例：&lt;/p>
&lt;iframe class="li-demo-iframe" data-src="https://geyuyao.com/demos/long-insight/demo_dag_sonnet_12-15.html" src="https://geyuyao.com/demos/long-insight/demo_dag_sonnet_12-15.html?lang=zh" style="width:100%; height:600px; border:1px solid rgba(255,255,255,0.1); border-radius:8px;" loading="lazy">&lt;/iframe>
&lt;p>虽然从宏观上看，轨迹整体呈线形结构，但仔细观察就会发现，Agent 并不是简单地&amp;quot;一条路走到黑&amp;quot;。它在不断地进行&lt;strong>发散（信息收集）→ 收敛（总结规划）→ 试错（回滚）→ 再执行&lt;/strong>的循环。&lt;/p>
&lt;p>整个轨迹可以划分为六个行为阶段：&lt;/p>
&lt;h4 id="第一阶段环境感知与基线建立steps-124">第一阶段：环境感知与基线建立（Steps 1–24）&lt;/h4>
&lt;p>Agent 非常注重&lt;strong>测试优先&lt;/strong>，花费大量精力分析 &lt;code>test_package.py&lt;/code>，通过阅读测试代码来反推需求，而不是盲目猜测。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="第一阶段 DAG" srcset="
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_c5d15d84f51c6a1a131d1fcacafd58bd.webp 400w,
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_e23d0916b791bdd78290dd498686e286.webp 760w,
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_c5d15d84f51c6a1a131d1fcacafd58bd.webp"
width="526"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="第二阶段策略调整与重规划steps-2534">第二阶段：策略调整与重规划（Steps 25–34）&lt;/h4>
&lt;p>经历了步骤 28 的回滚后，Agent 没有急于再次编码，而是转入&amp;quot;测试发现阶段&amp;quot;，通过非侵入式脚本去探测项目状态。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="第二阶段 DAG" srcset="
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1c2abde1ad276dd748074b4d98e4f431.webp 400w,
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1f16de73ffd2b272106da6e4d7280785.webp 760w,
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1c2abde1ad276dd748074b4d98e4f431.webp"
width="759"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="第三阶段基础设施建设steps-3851">第三阶段：基础设施建设（Steps 38–51）&lt;/h4>
&lt;p>在触碰核心算法前，先修复/实现底层依赖，例如 &lt;code>Dimension&lt;/code> 类构造方法和工具函数 &lt;code>execute_decomposition_method&lt;/code>。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="第三阶段 DAG" srcset="
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_6ee14c95b64e256a39cf4ee726a02fd9.webp 400w,
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_17eea17b42f1c5661c4ffdeb9bb5e191.webp 760w,
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_6ee14c95b64e256a39cf4ee726a02fd9.webp"
width="566"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="第四阶段核心算法的逐个实现steps-5279">第四阶段：核心算法的逐个实现（Steps 52–79）&lt;/h4>
&lt;p>这是轨迹中&lt;strong>最长的一段&lt;/strong>。Agent 采用&amp;quot;类比克隆&amp;quot;策略：先攻克最难的基类 &lt;code>PDDP&lt;/code> 的 &lt;code>fit&lt;/code> 方法，一旦跑通，迅速复制到子类 &lt;code>DePDDP&lt;/code>、&lt;code>IPDDP&lt;/code>、&lt;code>KMPDDP&lt;/code>、&lt;code>BisectingKmeans&lt;/code>。每个实现后紧跟单元测试（TDD 模式）。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="第四阶段 DAG" srcset="
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_f7d65e1fb4bd1d826f8e08870820bed4.webp 400w,
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_88c68c453950b9caa831ac4bfb065fe9.webp 760w,
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_f7d65e1fb4bd1d826f8e08870820bed4.webp"
width="571"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="第五阶段修复错误steps-80110">第五阶段：修复错误（Steps 80–110）&lt;/h4>
&lt;p>Agent 不仅修复了一个类，而是&lt;strong>系统性地遍历所有相关类&lt;/strong>，在 &lt;code>fit&lt;/code> 方法入口处统一添加输入验证逻辑。这展示了 Agent 的 &lt;strong>全局一致性（Consistency）&lt;/strong> 意识。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="第五阶段 DAG" srcset="
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_4c16f92971e6f162bf1ce8960b5e2d6c.webp 400w,
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_f0932d87cfcaf6f8af9be236ff1c0363.webp 760w,
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_4c16f92971e6f162bf1ce8960b5e2d6c.webp"
width="417"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="第六阶段全量回归与交付steps-111120">第六阶段：全量回归与交付（Steps 111–120）&lt;/h4>
&lt;p>运行全量测试套件（57 个测试用例全过），在真实场景下验证，生成交付文档并提交。&lt;/p>
&lt;h3 id="局部结构分析">局部结构分析&lt;/h3>
&lt;h4 id="汇聚结构fan-in">汇聚结构（Fan-in）&lt;/h4>
&lt;p>步骤 15（&lt;code>创建 TODO 和 OVERVIEW 笔记&lt;/code>）的父亲是 &lt;code>[12, 13, 14]&lt;/code> — Agent 在分别查找函数定义、类定义并验证数据加载后，将分散的信息汇聚成一份项目文档。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="汇聚结构" srcset="
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_d8edb61335f6565190bd8ab5e12beab9.webp 400w,
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_fc4ce839a11cfe5ca9e42415d2b6d178.webp 760w,
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_d8edb61335f6565190bd8ab5e12beab9.webp"
width="760"
height="652"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>类似的汇聚模式：&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="汇聚结构 2" srcset="
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1c78f0b9eb5b25ddf78ccb85bb9f1e94.webp 400w,
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_eaa112241cf6ede8497aec62b6d78726.webp 760w,
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1c78f0b9eb5b25ddf78ccb85bb9f1e94.webp"
width="760"
height="395"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="汇聚结构 3" srcset="
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e8c84fe4c43f5d3d3ada8d6709570420.webp 400w,
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e2ed45f8a43b9ada704f91b02aed55fc.webp 760w,
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e8c84fe4c43f5d3d3ada8d6709570420.webp"
width="760"
height="493"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="回溯结构backtrace">回溯结构（Backtrace）&lt;/h4>
&lt;p>步骤 28（&lt;code>中断实施并重新审视&lt;/code>）— Agent 执行了 &lt;code>git checkout&lt;/code> 或 &lt;code>git reset --hard&lt;/code>，代表&lt;strong>对死胡同的剪枝&lt;/strong>。Agent 意识到当前路径是错误的，切断分支，退回之前的状态。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="回溯结构" srcset="
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_49be02e7470797e8685f16887a3f5f8a.webp 400w,
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_a02e8d58db6167aa3cde08f690c7bb3b.webp 760w,
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_49be02e7470797e8685f16887a3f5f8a.webp"
width="760"
height="418"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;hr>
&lt;h2 id="第二部分轨迹压缩">第二部分：轨迹压缩&lt;/h2>
&lt;h3 id="为什么必须压缩">为什么必须压缩？&lt;/h3>
&lt;p>不同任务类别的 Token 消耗差异巨大：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>任务类别&lt;/th>
&lt;th>平均 Token 数&lt;/th>
&lt;th>超出 128K 的倍数&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>application_development&lt;/strong>&lt;/td>
&lt;td>8,135,018&lt;/td>
&lt;td>61.9 倍&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>build_deployment&lt;/strong>&lt;/td>
&lt;td>3,784,482&lt;/td>
&lt;td>28.8 倍&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ui_optimization&lt;/strong>&lt;/td>
&lt;td>1,412,891&lt;/td>
&lt;td>10.7 倍&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>machine_learning&lt;/strong>&lt;/td>
&lt;td>643,637&lt;/td>
&lt;td>4.9 倍&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>frontend_development&lt;/strong>&lt;/td>
&lt;td>294,325&lt;/td>
&lt;td>可处理&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>核心问题：85% 的轨迹超出上下文窗口、过长输入导致评测 LLM 性能下降、API 成本剧增。&lt;/p>
&lt;h3 id="压缩策略">压缩策略&lt;/h3>
&lt;p>核心原则：&lt;strong>保留 Agent 决策相关的所有内容，删除系统元数据和冗余信息。&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>删除&lt;/strong>：&lt;code>uuid&lt;/code>、&lt;code>parentUuid&lt;/code>、&lt;code>timestamp&lt;/code>、&lt;code>sessionId&lt;/code>、&lt;code>version&lt;/code> 等元数据；&lt;code>toolUseResult&lt;/code>（Agent 不可见的系统内部记录）&lt;/li>
&lt;li>&lt;strong>完整保留&lt;/strong>：Agent 的思考过程、代码输出、工具调用（含代码、参数、Todo List）&lt;/li>
&lt;li>&lt;strong>选择性截断&lt;/strong>：用户消息截断至 200 字符、工具结果超过 200 字符时截断&lt;/li>
&lt;/ul>
&lt;h3 id="压缩效果">压缩效果&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>指标&lt;/th>
&lt;th>压缩前&lt;/th>
&lt;th>压缩后&lt;/th>
&lt;th>改善&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>字符数&lt;/strong>&lt;/td>
&lt;td>41,659&lt;/td>
&lt;td>17,296&lt;/td>
&lt;td>&lt;strong>-58.5%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>行数&lt;/strong>&lt;/td>
&lt;td>538&lt;/td>
&lt;td>216&lt;/td>
&lt;td>&lt;strong>-59.9%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>估算 Token&lt;/strong>&lt;/td>
&lt;td>~20,800&lt;/td>
&lt;td>~8,600&lt;/td>
&lt;td>&lt;strong>-58.7%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>核心内容&lt;/strong>&lt;/td>
&lt;td>100%&lt;/td>
&lt;td>100%&lt;/td>
&lt;td>&lt;strong>无损保留&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="第三部分自动评分">第三部分：自动评分&lt;/h2>
&lt;h3 id="评分体系">评分体系&lt;/h3>
&lt;p>我们设计了两阶段评分系统，从&lt;strong>任务难度&lt;/strong>和&lt;strong>提升潜力&lt;/strong>两个维度对轨迹进行自动评价：&lt;/p>
&lt;p>&lt;strong>阶段一：任务难度评分（0–10）&lt;/strong>&lt;/p>
&lt;p>输入字段包括问题描述、Issue 数量、评测结果（是否解决、补丁状态、测试日志）、总 Token 数和总轮次数。评估维度：&lt;/p>
&lt;ul>
&lt;li>问题本质复杂度（涉及文件数量、逻辑复杂程度）&lt;/li>
&lt;li>修复难度（需要多深的架构理解）&lt;/li>
&lt;li>问题描述清晰度&lt;/li>
&lt;li>项目复杂度（Issue 数量反映项目规模）&lt;/li>
&lt;li>实际解决难度（Token 消耗、轮次数、测试结果）&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>阶段二：提升潜力评分（0–10）&lt;/strong>&lt;/p>
&lt;p>输入为经压缩的完整对话历史 &lt;code>messages&lt;/code>。分数越高代表轨迹质量越好。定义了多种典型不良模式，不良情况越多，分数越低：&lt;/p>
&lt;ul>
&lt;li>测试尊重度 — 是否认真对待失败的测试&lt;/li>
&lt;li>验证闭环完整性 — 发现→分析→修复→验证 的闭环是否完整&lt;/li>
&lt;li>问题定位准确性 — 是否找到了真正的根因&lt;/li>
&lt;li>行为重复度 — 是否在重复无效操作&lt;/li>
&lt;li>探索效率 — 是否进行了有效的代码探索&lt;/li>
&lt;li>错误应对能力 — 是否良好应对报错信息&lt;/li>
&lt;li>推理质量 — thinking 块是否有实质内容&lt;/li>
&lt;li>轨迹稳定性 — 是否频繁偏离主线&lt;/li>
&lt;li>行为有效性 — 后期操作是否仍然有意义&lt;/li>
&lt;/ul>
&lt;h3 id="实际应用">实际应用&lt;/h3>
&lt;p>我们对 &lt;strong>12,839 条&lt;/strong> Sonnet 4.5 SWE-bench 轨迹进行了自动评分。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="评分分布" srcset="
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_a7faf91365c93184e4a6b3f1edcce891.webp 400w,
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_d31556507b117630306c2e3697bc0ff8.webp 760w,
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_a7faf91365c93184e4a6b3f1edcce891.webp"
width="760"
height="305"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>根据评分结果进行数据筛选：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>筛选阈值&lt;/th>
&lt;th>保留轨迹数&lt;/th>
&lt;th>保留比例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>提升潜力 ≥ 8 分&lt;/td>
&lt;td>11,381&lt;/td>
&lt;td>88.6%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>提升潜力 ≥ 9 分&lt;/td>
&lt;td>999&lt;/td>
&lt;td>7.8%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>评分结果适合用于 SWE SFT 训练数据的质量过滤 — 通过去除低分轨迹中的坏模式（bad patterns），提升训练数据质量，而不是简单地按难度或领域做选择性偏差。&lt;/p>
&lt;/div>
&lt;div class="li-lang-en" markdown="1">
&lt;h1 id="long-insight-a-platform-for-long-running-agent-trajectory-analysis">Long-Insight: A Platform for Long-running Agent Trajectory Analysis&lt;/h1>
&lt;h2 id="background-when-agent-trajectories-are-too-long-to-read">Background: When Agent Trajectories Are Too Long to Read&lt;/h2>
&lt;p>When frontier LLMs tackle real software-engineering tasks, the resulting execution traces are staggeringly long. Take a recent Long-running benchmark of 370 trajectories as an example:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Model&lt;/th>
&lt;th>Avg. Tokens&lt;/th>
&lt;th>Multiples of 128K&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Kimi-K2-0905&lt;/strong>&lt;/td>
&lt;td>6,837,594&lt;/td>
&lt;td>&lt;strong>52.1×&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>DeepSeek-V3.1&lt;/strong>&lt;/td>
&lt;td>5,059,423&lt;/td>
&lt;td>&lt;strong>38.5×&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>GLM-4.6&lt;/strong>&lt;/td>
&lt;td>2,616,703&lt;/td>
&lt;td>&lt;strong>19.9×&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Claude-Sonnet-4&lt;/strong>&lt;/td>
&lt;td>977,747&lt;/td>
&lt;td>&lt;strong>7.4×&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>A single &lt;code>application_development&lt;/code> trajectory averages &lt;strong>8.1M tokens&lt;/strong> — &lt;strong>61.9×&lt;/strong> a 128K context window. &lt;strong>At least 85% of the 370 trajectories exceed any model&amp;rsquo;s context window.&lt;/strong>&lt;/p>
&lt;p>This creates two concrete problems:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Humans can&amp;rsquo;t read them&lt;/strong> — no matter how patient an engineer, 400+ turns of interaction logs cannot be reviewed line by line.&lt;/li>
&lt;li>&lt;strong>Models can&amp;rsquo;t process them&lt;/strong> — even with million-token context windows, most trajectories still won&amp;rsquo;t fit.&lt;/li>
&lt;/ol>
&lt;p>Yet these trajectories contain extremely valuable signals. As we summarized while filtering SWE SFT data:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>&amp;ldquo;It&amp;rsquo;s fine if there&amp;rsquo;s only some gold in the sand — but there can&amp;rsquo;t be broken glass.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>What we need is not blind selection of &amp;ldquo;good-looking&amp;rdquo; trajectories, but &lt;strong>precise identification and filtering of bad patterns&lt;/strong>. To do that, we need tools that &lt;strong>understand&lt;/strong> what these ultra-long trajectories are doing — and how well.&lt;/p>
&lt;p>That is the origin of Long-Insight.&lt;/p>
&lt;h2 id="core-idea">Core Idea&lt;/h2>
&lt;p>Long-Insight solves three problems:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Unreadable&lt;/strong> → decompose linear trajectories into a structured step DAG with types, summaries, and parent–child dependencies.&lt;/li>
&lt;li>&lt;strong>Doesn&amp;rsquo;t fit&lt;/strong> → smart compression that cuts 60–80% of tokens while preserving causal structure.&lt;/li>
&lt;li>&lt;strong>Hard to score&lt;/strong> → a two-stage LLM auto-scorer that quantifies trajectory difficulty and quality.&lt;/li>
&lt;/ol>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Inspiration" srcset="
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_9cafd98d00676ed5f3924480c73b0ab9.webp 400w,
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_f6dfbafd07a75b25d3eb2b8ee98a13af.webp 760w,
/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_hu6f5ce95f944f138ef609bc187e73138b_118672_9cafd98d00676ed5f3924480c73b0ab9.webp"
width="760"
height="427"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;hr>
&lt;h2 id="part-1-trajectory-step-decomposition">Part 1: Trajectory Step Decomposition&lt;/h2>
&lt;h3 id="design">Design&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Initialization&lt;/strong>: create an empty JSON file.&lt;/li>
&lt;li>&lt;strong>Loop&lt;/strong>: read trajectory turns one by one → call an LLM to analyze → decide &amp;ldquo;new step&amp;rdquo; vs. &amp;ldquo;continuation&amp;rdquo; → update the step DAG.&lt;/li>
&lt;li>&lt;strong>Finalization&lt;/strong>: produce a complete step-partition JSON with 8 step types, causal narratives, and parent–child links.&lt;/li>
&lt;/ul>
&lt;p>Each step is classified into one of: Task Understanding, Project Exploration, Environment Setup, Code Implementation, Test Validation, Problem Debugging, Documentation, and Summary &amp;amp; Planning.&lt;/p>
&lt;h3 id="macro-level-analysis">Macro-level Analysis&lt;/h3>
&lt;p>Below is one Sonnet 4.5 trajectory on SWE-bench:&lt;/p>
&lt;iframe class="li-demo-iframe" data-src="https://geyuyao.com/demos/long-insight/demo_dag_sonnet_12-15.html" src="https://geyuyao.com/demos/long-insight/demo_dag_sonnet_12-15.html?lang=en" style="width:100%; height:600px; border:1px solid rgba(255,255,255,0.1); border-radius:8px;" loading="lazy">&lt;/iframe>
&lt;p>Although the trajectory looks roughly linear at the macro level, a closer look reveals that the Agent isn&amp;rsquo;t simply &amp;ldquo;marching straight to the end.&amp;rdquo; It continuously cycles through &lt;strong>diverge (gather information) → converge (summarize &amp;amp; plan) → trial-and-error (rollback) → execute again&lt;/strong>.&lt;/p>
&lt;p>The whole trajectory naturally splits into six behavioral phases:&lt;/p>
&lt;h4 id="phase-1-environment-sensing-and-baseline-building-steps-124">Phase 1: Environment Sensing and Baseline Building (Steps 1–24)&lt;/h4>
&lt;p>The Agent is decidedly &lt;strong>test-first&lt;/strong>, spending substantial effort analyzing &lt;code>test_package.py&lt;/code> and reverse-engineering requirements from test code rather than guessing blindly.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Phase 1 DAG" srcset="
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_c5d15d84f51c6a1a131d1fcacafd58bd.webp 400w,
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_e23d0916b791bdd78290dd498686e286.webp 760w,
/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%283%29_hu503a984001ecb3cdccf44d8827767745_336075_c5d15d84f51c6a1a131d1fcacafd58bd.webp"
width="526"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="phase-2-strategy-adjustment-and-replanning-steps-2534">Phase 2: Strategy Adjustment and Replanning (Steps 25–34)&lt;/h4>
&lt;p>After the rollback at step 28, the Agent doesn&amp;rsquo;t rush back into coding. Instead, it enters a &amp;ldquo;test-discovery phase,&amp;rdquo; probing project state with non-invasive scripts.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Phase 2 DAG" srcset="
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1c2abde1ad276dd748074b4d98e4f431.webp 400w,
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1f16de73ffd2b272106da6e4d7280785.webp 760w,
/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_hucb10cbd15dd4e81cd70ea2a2b14b46f6_414454_1c2abde1ad276dd748074b4d98e4f431.webp"
width="759"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="phase-3-infrastructure-construction-steps-3851">Phase 3: Infrastructure Construction (Steps 38–51)&lt;/h4>
&lt;p>Before touching the core algorithms, the Agent fixes/implements low-level dependencies — for example, the &lt;code>Dimension&lt;/code> class constructor and the utility function &lt;code>execute_decomposition_method&lt;/code>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Phase 3 DAG" srcset="
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_6ee14c95b64e256a39cf4ee726a02fd9.webp 400w,
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_17eea17b42f1c5661c4ffdeb9bb5e191.webp 760w,
/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%285%29_hu65fb11108f65949068717b6af1492b61_290221_6ee14c95b64e256a39cf4ee726a02fd9.webp"
width="566"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="phase-4-core-algorithms-one-by-one-steps-5279">Phase 4: Core Algorithms, One by One (Steps 52–79)&lt;/h4>
&lt;p>This is the &lt;strong>longest stretch&lt;/strong> of the trajectory. The Agent adopts an &amp;ldquo;analogy-clone&amp;rdquo; strategy: first crack the hardest base class &lt;code>PDDP&lt;/code>&amp;rsquo;s &lt;code>fit&lt;/code> method, then quickly replicate it to subclasses &lt;code>DePDDP&lt;/code>, &lt;code>IPDDP&lt;/code>, &lt;code>KMPDDP&lt;/code>, and &lt;code>BisectingKmeans&lt;/code>. Each implementation is immediately followed by unit tests (TDD style).&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Phase 4 DAG" srcset="
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_f7d65e1fb4bd1d826f8e08870820bed4.webp 400w,
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_88c68c453950b9caa831ac4bfb065fe9.webp 760w,
/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%286%29_hu57553b610404cabc366393e60a015494_436445_f7d65e1fb4bd1d826f8e08870820bed4.webp"
width="571"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="phase-5-fixing-errors-steps-80110">Phase 5: Fixing Errors (Steps 80–110)&lt;/h4>
&lt;p>The Agent doesn&amp;rsquo;t just patch a single class — it &lt;strong>systematically walks through every related class&lt;/strong>, uniformly adding input validation at the entry point of &lt;code>fit&lt;/code> methods. This demonstrates the Agent&amp;rsquo;s awareness of &lt;strong>global consistency&lt;/strong>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Phase 5 DAG" srcset="
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_4c16f92971e6f162bf1ce8960b5e2d6c.webp 400w,
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_f0932d87cfcaf6f8af9be236ff1c0363.webp 760w,
/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%287%29_hu35240c3ac3dc7bf556eb32e066b3bb44_496711_4c16f92971e6f162bf1ce8960b5e2d6c.webp"
width="417"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="phase-6-full-regression-and-delivery-steps-111120">Phase 6: Full Regression and Delivery (Steps 111–120)&lt;/h4>
&lt;p>Run the full test suite (all 57 cases pass), validate in real scenarios, generate delivery documentation, and submit.&lt;/p>
&lt;h3 id="local-structure-analysis">Local Structure Analysis&lt;/h3>
&lt;h4 id="fan-in">Fan-in&lt;/h4>
&lt;p>Step 15 (&lt;code>Create TODO and OVERVIEW notes&lt;/code>) has parents &lt;code>[12, 13, 14]&lt;/code> — after separately searching function definitions, class definitions, and verifying data loading, the Agent fuses the scattered information into one project document.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Fan-in 1" srcset="
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_d8edb61335f6565190bd8ab5e12beab9.webp 400w,
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_fc4ce839a11cfe5ca9e42415d2b6d178.webp 760w,
/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%288%29_hudf785de7a78070806996a47f8c4765cc_260019_d8edb61335f6565190bd8ab5e12beab9.webp"
width="760"
height="652"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Similar fan-in patterns:&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Fan-in 2" srcset="
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1c78f0b9eb5b25ddf78ccb85bb9f1e94.webp 400w,
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_eaa112241cf6ede8497aec62b6d78726.webp 760w,
/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%289%29_huf11e7570515067a3124dd0a61d228c19_218408_1c78f0b9eb5b25ddf78ccb85bb9f1e94.webp"
width="760"
height="395"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Fan-in 3" srcset="
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e8c84fe4c43f5d3d3ada8d6709570420.webp 400w,
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e2ed45f8a43b9ada704f91b02aed55fc.webp 760w,
/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%2810%29_hufdc39511fc7efdabc7d4ef6b1353ca4b_314844_e8c84fe4c43f5d3d3ada8d6709570420.webp"
width="760"
height="493"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="backtrace">Backtrace&lt;/h4>
&lt;p>Step 28 (&lt;code>Abort implementation and reassess&lt;/code>) — the Agent executed &lt;code>git checkout&lt;/code> or &lt;code>git reset --hard&lt;/code>, representing &lt;strong>pruning a dead-end branch&lt;/strong>. It realized the current path was wrong, cut the branch, and reverted to an earlier state.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Backtrace" srcset="
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_49be02e7470797e8685f16887a3f5f8a.webp 400w,
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_a02e8d58db6167aa3cde08f690c7bb3b.webp 760w,
/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/image_%2811%29_hu50d42a63f6720231e004a2a3bba72b1e_269993_49be02e7470797e8685f16887a3f5f8a.webp"
width="760"
height="418"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;hr>
&lt;h2 id="part-2-trajectory-compression">Part 2: Trajectory Compression&lt;/h2>
&lt;h3 id="why-compression-is-mandatory">Why Compression Is Mandatory&lt;/h3>
&lt;p>Token consumption varies dramatically across task categories:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Task Category&lt;/th>
&lt;th>Avg. Tokens&lt;/th>
&lt;th>Multiples of 128K&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>application_development&lt;/strong>&lt;/td>
&lt;td>8,135,018&lt;/td>
&lt;td>61.9×&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>build_deployment&lt;/strong>&lt;/td>
&lt;td>3,784,482&lt;/td>
&lt;td>28.8×&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ui_optimization&lt;/strong>&lt;/td>
&lt;td>1,412,891&lt;/td>
&lt;td>10.7×&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>machine_learning&lt;/strong>&lt;/td>
&lt;td>643,637&lt;/td>
&lt;td>4.9×&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>frontend_development&lt;/strong>&lt;/td>
&lt;td>294,325&lt;/td>
&lt;td>fits&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Core issues: 85% of trajectories exceed any model&amp;rsquo;s context window, over-long inputs degrade the judging LLM&amp;rsquo;s performance, and API costs balloon.&lt;/p>
&lt;h3 id="compression-strategy">Compression Strategy&lt;/h3>
&lt;p>Core principle: &lt;strong>preserve everything relevant to the Agent&amp;rsquo;s decisions; drop system metadata and redundancy.&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Drop&lt;/strong>: metadata such as &lt;code>uuid&lt;/code>, &lt;code>parentUuid&lt;/code>, &lt;code>timestamp&lt;/code>, &lt;code>sessionId&lt;/code>, &lt;code>version&lt;/code>; &lt;code>toolUseResult&lt;/code> (internal system records invisible to the Agent).&lt;/li>
&lt;li>&lt;strong>Keep in full&lt;/strong>: the Agent&amp;rsquo;s thinking, code outputs, and tool calls (including code, arguments, and Todo lists).&lt;/li>
&lt;li>&lt;strong>Selectively truncate&lt;/strong>: user messages capped at 200 chars; tool results truncated when they exceed 200 chars.&lt;/li>
&lt;/ul>
&lt;h3 id="compression-results">Compression Results&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Metric&lt;/th>
&lt;th>Before&lt;/th>
&lt;th>After&lt;/th>
&lt;th>Improvement&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Characters&lt;/strong>&lt;/td>
&lt;td>41,659&lt;/td>
&lt;td>17,296&lt;/td>
&lt;td>&lt;strong>-58.5%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Lines&lt;/strong>&lt;/td>
&lt;td>538&lt;/td>
&lt;td>216&lt;/td>
&lt;td>&lt;strong>-59.9%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Estimated tokens&lt;/strong>&lt;/td>
&lt;td>~20,800&lt;/td>
&lt;td>~8,600&lt;/td>
&lt;td>&lt;strong>-58.7%&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Core content&lt;/strong>&lt;/td>
&lt;td>100%&lt;/td>
&lt;td>100%&lt;/td>
&lt;td>&lt;strong>lossless&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="part-3-automatic-scoring">Part 3: Automatic Scoring&lt;/h2>
&lt;h3 id="scoring-system">Scoring System&lt;/h3>
&lt;p>We designed a two-stage scoring pipeline that evaluates trajectories along two dimensions: &lt;strong>task difficulty&lt;/strong> and &lt;strong>improvement potential&lt;/strong>.&lt;/p>
&lt;p>&lt;strong>Stage 1: Task Difficulty Score (0–10)&lt;/strong>&lt;/p>
&lt;p>Inputs include the problem description, number of issues, evaluation results (resolved or not, patch status, test logs), total tokens, and total turns. Dimensions assessed:&lt;/p>
&lt;ul>
&lt;li>Inherent problem complexity (number of files involved, logical depth)&lt;/li>
&lt;li>Fix difficulty (how deep an architectural understanding is required)&lt;/li>
&lt;li>Clarity of the problem description&lt;/li>
&lt;li>Project complexity (issue counts as a proxy for project size)&lt;/li>
&lt;li>Empirical solving difficulty (token consumption, turn count, test outcomes)&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Stage 2: Improvement-Potential Score (0–10)&lt;/strong>&lt;/p>
&lt;p>The input is the compressed full conversation history &lt;code>messages&lt;/code>. Higher scores mean higher-quality trajectories. We defined several stereotypical bad patterns — the more bad patterns observed, the lower the score:&lt;/p>
&lt;ul>
&lt;li>Test-respect — does the Agent take failing tests seriously?&lt;/li>
&lt;li>Validation-loop completeness — is the discover → analyze → fix → verify loop intact?&lt;/li>
&lt;li>Root-cause accuracy — did the Agent locate the actual root cause?&lt;/li>
&lt;li>Behavioral repetition — is it repeating ineffective operations?&lt;/li>
&lt;li>Exploration efficiency — is it exploring code productively?&lt;/li>
&lt;li>Error-handling capability — does it deal well with error messages?&lt;/li>
&lt;li>Reasoning quality — do thinking blocks contain substantive content?&lt;/li>
&lt;li>Trajectory stability — does it frequently drift off the main thread?&lt;/li>
&lt;li>Action effectiveness — are late-stage actions still meaningful?&lt;/li>
&lt;/ul>
&lt;h3 id="application">Application&lt;/h3>
&lt;p>We auto-scored &lt;strong>12,839&lt;/strong> Sonnet 4.5 trajectories on SWE-bench, at a cost of roughly &lt;strong>¥1 per trajectory&lt;/strong>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Score distribution" srcset="
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_a7faf91365c93184e4a6b3f1edcce891.webp 400w,
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_d31556507b117630306c2e3697bc0ff8.webp 760w,
/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/project/long-insight/score_distribution_hu4c787f1bba4462257befff7bc7c4199b_163119_a7faf91365c93184e4a6b3f1edcce891.webp"
width="760"
height="305"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Filtering thresholds derived from the scores:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Threshold&lt;/th>
&lt;th>Retained&lt;/th>
&lt;th>Retention&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Improvement potential ≥ 8&lt;/td>
&lt;td>11,381&lt;/td>
&lt;td>88.6%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Improvement potential ≥ 9&lt;/td>
&lt;td>999&lt;/td>
&lt;td>7.8%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>These scores feed directly into the SWE SFT quality filter — removing bad patterns from low-scoring trajectories to improve training data quality, rather than introducing selection bias by difficulty or domain.&lt;/p>
&lt;/div>
&lt;script>
(function(){
function getInitialLang(){
try{
var url = new URL(window.location.href);
var q = url.searchParams.get('lang');
if(q === 'en' || q === 'zh') return q;
var stored = localStorage.getItem('li_lang');
if(stored === 'en' || stored === 'zh') return stored;
}catch(_){}
var nav = (navigator.language || navigator.userLanguage || 'en').toLowerCase();
return nav.indexOf('zh') === 0 ? 'zh' : 'en';
}
var currentLILang = null;
// Bump LI_DEMO_VERSION when demo HTML files change so browsers bypass cache.
var LI_DEMO_VERSION = '2026-05-27a';
function postLangToIframe(f, lang){
try{
if(f.contentWindow){
f.contentWindow.postMessage({type:'li-demo-set-lang', lang: lang}, '*');
}
}catch(_){}
}
function setLang(lang){
if(lang !== 'en' &amp;&amp; lang !== 'zh') lang = 'en';
currentLILang = lang;
document.body.setAttribute('data-li-lang', lang);
try{ localStorage.setItem('li_lang', lang); }catch(_){}
try{
var url = new URL(window.location.href);
url.searchParams.set('lang', lang);
window.history.replaceState({}, '', url.toString());
}catch(_){}
document.querySelectorAll('.li-lang-bar [data-lilang]').forEach(function(b){
b.classList.toggle('active', b.getAttribute('data-lilang') === lang);
});
document.querySelectorAll('iframe.li-demo-iframe').forEach(function(f){
var base = f.getAttribute('data-src') || (f.src ? f.src.split('?')[0] : '');
if(!base) return;
var desired = base + '?lang=' + lang + '&amp;v=' + LI_DEMO_VERSION;
// attach a one-time load listener so we ALSO send postMessage once the iframe is ready
if(!f.dataset.liLoadHook){
f.addEventListener('load', function(){
postLangToIframe(f, currentLILang || lang);
});
f.dataset.liLoadHook = '1';
}
if(!f.dataset.liInited){
// first time: force the iframe to load with the correct lang
f.setAttribute('src', desired);
f.dataset.liInited = '1';
f.dataset.liLang = lang;
} else if(f.dataset.liLang !== lang){
// language changed: notify via postMessage (no reload). Don't update src to avoid losing user state.
postLangToIframe(f, lang);
f.dataset.liLang = lang;
}
});
}
window.__setLILang = setLang;
setLang(getInitialLang());
})();
&lt;/script></description></item><item><title>Reward and Guidance through Rubrics: Promoting Exploration to Improve Multi-Domain Reasoning</title><link>https://geyuyao.com/publication/bi2025reward/</link><pubDate>Sat, 15 Nov 2025 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/bi2025reward/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Reinforcement learning (RL) has shown great promise in enhancing LLM reasoning, but current approaches mainly focus on single domains with verifiable rewards. We propose RGR-GRPO, a rubric-driven RL framework for multi-domain reasoning that uses rubrics to provide fine-grained reward signals and offline guidance. This approach helps LLMs receive dense and informative rewards while exploring a larger solution space during GRPO training. Experiments across 14 benchmarks show RGR-GRPO outperforms alternatives, achieving average gains of +7.0%, +5.4%, +8.4%, and +6.6% on math, physics, chemistry, and general reasoning tasks respectively. The method also maintains stable entropy fluctuations during off-policy training and demonstrates stronger pass@k performance, indicating sustained exploration capabilities.&lt;/p></description></item><item><title>A Survey of Vibe Coding with Large Language Models</title><link>https://geyuyao.com/publication/ge2025vibe/</link><pubDate>Sat, 25 Oct 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/ge2025vibe/</guid><description/></item><item><title>Focusing by Contrastive Attention: Enhancing VLMs' Visual Reasoning</title><link>https://geyuyao.com/publication/ge2025focusing/</link><pubDate>Wed, 10 Sep 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/ge2025focusing/</guid><description>&lt;h1 id="carve无需训练利用对比注意力让视觉模型更专注">CARVE：无需训练，利用对比注意力让视觉模型更专注&lt;/h1>
&lt;p>你是否曾经在书架前寻找一本书，却因为密密麻麻的书脊而眼花缭乱？或者在超市货架前，面对琳琅满目的商品标签而一时找不到目标？其实，视觉语言模型（VLMs）也面临着同样的困扰。&lt;/p>
&lt;p>本篇发现了一个有趣的现象：&lt;strong>视觉复杂度会让AI模型的注意力&amp;quot;走神&amp;quot;&lt;/strong>，就像人类在复杂场景中会分心一样。我们提出的 &lt;strong>CARVE（Contrastive Attention Refinement for Visual Enhancement）&lt;/strong> 方法，通过对比注意力机制，帮助模型在视觉噪声中聚焦关键信息，在开源模型上实现了大幅的性能提升。&lt;/p>
&lt;!-- ![figure/02_00.png](figure/02_00.png)
**论文标题：** Focusing by Contrastive Attention: Enhancing VLMs' Visual Reasoning
**论文地址：**https://arxiv.org/pdf/2509.06461 -->
&lt;h2 id="一发现视觉模型也会眼花缭乱">一、发现：视觉模型也会&amp;quot;眼花缭乱&amp;quot;？&lt;/h2>
&lt;p>研究团队首先探索了一个基础问题：复杂的视觉信息是否会像影响人类一样，干扰VLMs的注意力机制，使其难以聚焦于任务相关区域？&lt;/p>
&lt;h3 id="11-注意力的演化规律">1.1 注意力的演化规律&lt;/h3>
&lt;p>通过对Qwen2.5-VL-3B-Instruct模型在TextVQA数据集上的深入分析，研究团队发现了注意力分布的层次性演化规律：&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/01_00.png" srcset="
/publication/ge2025focusing/figure/01_00_hu38a2b057085376ca17a2d95a7d8d4439_12100515_74941fd14fe7bdb61781956a10ebc8b7.webp 400w,
/publication/ge2025focusing/figure/01_00_hu38a2b057085376ca17a2d95a7d8d4439_12100515_73ca3c755718d6547c3e9aca98da8f11.webp 760w,
/publication/ge2025focusing/figure/01_00_hu38a2b057085376ca17a2d95a7d8d4439_12100515_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/01_00_hu38a2b057085376ca17a2d95a7d8d4439_12100515_74941fd14fe7bdb61781956a10ebc8b7.webp"
width="760"
height="514"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>如上图所示，注意力呈现出明显的渐进式细化过程：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>浅层（Shallow layers）&lt;/strong>：进行广泛的全局扫描，注意力分布相对均匀&lt;/li>
&lt;li>&lt;strong>中层（Middle layers）&lt;/strong>：开始区域性定位，注意力逐渐收敛&lt;/li>
&lt;li>&lt;strong>深层（Deep layers）&lt;/strong>：实现聚焦收敛，理想情况下应锁定任务相关区域&lt;/li>
&lt;/ul>
&lt;h3 id="12-复杂度带来的注意力困境">1.2 复杂度带来的&amp;quot;注意力困境&amp;quot;&lt;/h3>
&lt;p>然而，视觉复杂度严重影响了这一收敛过程：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>简单场景（第1行）&lt;/strong>：目标清晰、干扰项少，高注意力区域成功收窄并对齐任务相关区域&lt;/li>
&lt;li>&lt;strong>复杂场景（第2-3行）&lt;/strong>：纹理丰富、颜色繁杂，即使到深层，注意力权重仍然分散&lt;/li>
&lt;/ul>
&lt;p>正如图中标注的&amp;quot;Confused where to look&amp;quot;，这种注意力分散类似于人类面对拥挤货架时的犹豫不决，最终导致推理失败。&lt;/p>
&lt;h2 id="二量化视觉复杂度对注意力有怎样的影响">二、量化：视觉复杂度对注意力有怎样的影响？&lt;/h2>
&lt;p>为了定量地研究这一现象，研究团队将视觉复杂度分解为两个纹理和颜色维度，并建立了量化指标。&lt;/p>
&lt;p>&lt;strong>纹理复杂度&lt;/strong>：对于输入图像
$\mathcal{I} \in \mathbb{R}^{H \times W \times 3}$，纹理复杂度通过Canny边缘检测定义：
$$
\mathcal{T}_c(\mathcal{I}) = \frac{1}{HW} \sum_{i=1}^{H} \sum_{j=1}^{W} \mathcal{E}(\mathcal{I})_{ij} = \frac{\|\mathcal{E}(\mathcal{I})\|_1}{HW} \in [0, 1]
$$
&lt;/p>
&lt;p>其中
$\mathcal{E}(\mathcal{I}) \in \{0,1\}^{H \times W}$ 是二值边缘图。值越高表示纹理越复杂。&lt;/p>
&lt;p>&lt;strong>颜色复杂度&lt;/strong>：通过HSV色彩空间中色相分布的Shannon熵来衡量：
$$
\mathcal{C}_c(\mathcal{I}) = -\frac{1}{\ln B} \sum_{b=0}^{B-1} \rho_b \ln \rho_b, \quad \text{其中 } \rho_b = \frac{n_b}{HW}, \quad n_b = |\{(i,j) : \zeta_{ij} = b\}|
$$
&lt;/p>
&lt;p>其中
$\rho_b = \frac{n_b}{HW}$ 是色相值为
$b$ 的像素比例，
$B = 180$ 为色相区间数。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/12_00.png" srcset="
/publication/ge2025focusing/figure/12_00_hua04b28422bbb4c6a12cc5f607adbb1af_124508_a9cd937faec721652a5312961a5d0c10.webp 400w,
/publication/ge2025focusing/figure/12_00_hua04b28422bbb4c6a12cc5f607adbb1af_124508_898696bd78ddaca0c2a6fe7f55143f9b.webp 760w,
/publication/ge2025focusing/figure/12_00_hua04b28422bbb4c6a12cc5f607adbb1af_124508_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/12_00_hua04b28422bbb4c6a12cc5f607adbb1af_124508_a9cd937faec721652a5312961a5d0c10.webp"
width="760"
height="251"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>上图展示了两个样本的可视化复杂度分析：第一行显示高复杂度（密集边缘、多样色彩分布），第二行显示低复杂度（稀疏边缘、集中色相值）。&lt;/p>
&lt;p>&lt;strong>注意力熵&lt;/strong>：为了量化注意力分散程度，本文采用Shannon熵作为度量：
$$
\overline{\mathcal{H}} = \frac{1}{|\mathcal{L}|} \sum_{l \in \mathcal{L}} \mathcal{H}(A_{l,t_{\text{end}}}^{(Q)}) = \frac{1}{|\mathcal{L}|} \sum_{l \in \mathcal{L}} \left(-\sum_{i=1}^{N_v} a_{l,t_{\text{end}},i} \ln a_{l,t_{\text{end}},i}\right)
$$
其中：&lt;/p>
&lt;ul>
&lt;li>
$A_{l,t}^{(Q)} \in \mathbb{R}^{N_v}$ 是层
$l$、时间步
$t$ 的注意力图&lt;/li>
&lt;li>
$N_v$ 是视觉token数量&lt;/li>
&lt;li>
$\mathcal{L} = [L_{\text{start}}, L_{\text{end}}]$ 是考虑的层范围&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/14_00.png" srcset="
/publication/ge2025focusing/figure/14_00_hu08f5d267cbed419771bf2366724d53f9_161267_00495fe323935253d77ef65587b8d5ea.webp 400w,
/publication/ge2025focusing/figure/14_00_hu08f5d267cbed419771bf2366724d53f9_161267_5f76f896752ad32f7d44748e5196fd59.webp 760w,
/publication/ge2025focusing/figure/14_00_hu08f5d267cbed419771bf2366724d53f9_161267_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/14_00_hu08f5d267cbed419771bf2366724d53f9_161267_00495fe323935253d77ef65587b8d5ea.webp"
width="760"
height="201"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>实验结果显示，纹理复杂度和颜色复杂度都与注意力熵呈现强正线性关系。这种单调趋势表明：&lt;strong>复杂的视觉特征导致VLMs产生分散的注意力模式&lt;/strong>。&lt;/p>
&lt;h2 id="三影响分散的注意力如何损害性能">三、影响：分散的注意力如何损害性能？&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/13_00.png" srcset="
/publication/ge2025focusing/figure/13_00_hu6f13b140fb5dfc95ca4dafd816e26ccc_153335_4129ba8a11008c108f3131f135cd1e9a.webp 400w,
/publication/ge2025focusing/figure/13_00_hu6f13b140fb5dfc95ca4dafd816e26ccc_153335_070d540450c7f02c7eb9710287c2423d.webp 760w,
/publication/ge2025focusing/figure/13_00_hu6f13b140fb5dfc95ca4dafd816e26ccc_153335_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/13_00_hu6f13b140fb5dfc95ca4dafd816e26ccc_153335_4129ba8a11008c108f3131f135cd1e9a.webp"
width="760"
height="236"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>图(a)揭示了注意力熵与准确率之间的强负相关关系：当注意力熵从5.1增加到6.8时，性能从约76%下降到65%。这证实了&lt;strong>注意力分散损害视觉推理能力&lt;/strong>。&lt;/p>
&lt;p>图(b)展示了两个重要特征：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>熵单调递减&lt;/strong>：注意力熵随层深度单调下降，与图1的观察一致&lt;/li>
&lt;li>&lt;strong>方差逐渐增大&lt;/strong>：95%置信区间随深度逐渐扩大，表明样本间差异性增强&lt;/li>
&lt;/ol>
&lt;p>这意味着：&lt;/p>
&lt;ul>
&lt;li>对于清晰目标的样本，深层实现高度集中的注意力&lt;/li>
&lt;li>对于噪声样本，即使在深层也保持分散的注意力模式&lt;/li>
&lt;/ul>
&lt;h2 id="四初步实验通过手动渐进式掩盖视觉噪声">四、初步实验：通过手动渐进式掩盖视觉噪声&lt;/h2>
&lt;p>在发现视觉复杂度影响注意力进而损害性能后，一个自然的问题是：如果我们能够移除视觉噪声，是否能提升模型性能？&lt;/p>
&lt;p>基于这一想法，研究团队在TextVQA数据集上进行了初步实验：首先应用渐进式掩码遮挡背景区域，然后裁剪仅保留任务相关区域，最后自适应放大到原始图像尺寸。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/08_00.png" srcset="
/publication/ge2025focusing/figure/08_00_huc20cccc8970eb85b8ebbb2f32a7bc825_3657997_3713cecb774b37597ad3090229067259.webp 400w,
/publication/ge2025focusing/figure/08_00_huc20cccc8970eb85b8ebbb2f32a7bc825_3657997_c8f7ce3557aa42ff6c6c1493fc0ac4e0.webp 760w,
/publication/ge2025focusing/figure/08_00_huc20cccc8970eb85b8ebbb2f32a7bc825_3657997_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/08_00_huc20cccc8970eb85b8ebbb2f32a7bc825_3657997_3713cecb774b37597ad3090229067259.webp"
width="760"
height="248"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>图中展示了两个代表性样本，在这两个案例中，杂乱的视觉环境最初都导致了错误预测。横轴表示掩码比例，纵轴显示候选token的对数概率（
$\log_{10}$Probability）。&lt;/p>
&lt;p>观察结果显示：&lt;/p>
&lt;ul>
&lt;li>在两个样本中，错误token的概率最初都占主导地位&lt;/li>
&lt;li>随着掩码比例的增加，正确token的概率逐渐上升&lt;/li>
&lt;li>在掩码比例分别约为0.02和0.65时，正确token概率超过了错误token概率&lt;/li>
&lt;/ul>
&lt;p>这些结果提供了初步验证：&lt;strong>掩盖视觉噪声能够提高正确token的概率&lt;/strong>。&lt;/p>
&lt;h2 id="五理论基础注意力分解与语义提取">五、理论基础：注意力分解与语义提取&lt;/h2>
&lt;p>在上一章节我们证明了使用掩盖视觉噪声能够提高VLM的性能，于是作者团队考虑如何将视觉噪声掩盖自动化。为此，研究团队提出了基于对比注意力的理论框架。&lt;/p>
&lt;h3 id="51-注意力分解">5.1 注意力分解&lt;/h3>
&lt;p>&lt;strong>定义1（注意力分解）&lt;/strong>：首先，假设VLMs的注意力分布受图像固有视觉噪声和任务相关语义信号的影响，可分解为：
$$
A_{l,t}^{(Q)}(\mathcal{I}) = \mathcal{F}_{\text{vis}}(\mathcal{I}) \otimes \mathcal{F}_{\text{sem}}(Q, \mathcal{I})
$$
其中：&lt;/p>
&lt;ul>
&lt;li>
$\mathcal{F}_{\text{vis}}(\mathcal{I}) \in \mathbb{R}^{N_v}$：图像固有的视觉噪声分量&lt;/li>
&lt;li>
$\mathcal{F}_{\text{sem}}(Q, \mathcal{I}) \in \mathbb{R}^{N_v}$：任务相关的语义信号分量&lt;/li>
&lt;li>
$\otimes$：Hadamard积（逐元素乘积）&lt;/li>
&lt;/ul>
&lt;p>当使用通用指令
$G$（如&amp;quot;描述这张图片&amp;quot;）时，由于缺乏特定任务来引入语义信息，语义信号函数退化为均匀分布：&lt;/p>
$$
A_{l,t}^{(G)}(\mathcal{I}) \approx \mathcal{F}_{\text{vis}}(\mathcal{I}) \otimes \mathbf{1}_{N_v} = \mathcal{F}_{\text{vis}}(\mathcal{I})
$$
&lt;h3 id="52-语义提取优化">5.2 语义提取优化&lt;/h3>
&lt;p>&lt;strong>定义2（基于注意力分解的语义提取）&lt;/strong>：为了从
$A^{(Q)}$ 中提取语义信号函数，定义估计的语义注意力
$\hat{A} \in \mathbb{R}^{N_v}_+$ 为以下优化问题的解：
$$
\hat{A} = \arg\min_{\tilde{A} \in \mathcal{A}} \mathcal{J}(\tilde{A}; A^{(Q)}, A^{(G)})
$$
目标函数基于分解构造：&lt;/p>
$$
\mathcal{J}(\tilde{A}) = \underbrace{\sum_{i=1}^{N_v} \left( \tilde{A}_i \cdot \mathcal{F}_{\text{vis},i}(\mathcal{I}) - [\mathcal{F}_{\text{vis},i}(\mathcal{I}) \cdot \mathcal{F}_{\text{sem},i}(Q,\mathcal{I})] \right)^2}_{\text{语义重建误差}} + \underbrace{\lambda \sum_{i=1}^{N_v} \tilde{A}_i^2 \cdot \mathcal{F}_{\text{vis},i}(\mathcal{I})}_{\text{视觉抑制正则化}}
$$
&lt;h3 id="53-闭式解">5.3 闭式解&lt;/h3>
&lt;p>&lt;strong>定理3（语义提取的闭式解）&lt;/strong>：将关系式
$A^{(Q)}_i \approx \mathcal{F}_{\text{vis},i} \cdot \mathcal{F}_{\text{sem},i}$ 和
$A^{(G)}_i \approx \mathcal{F}_{\text{vis},i}$ 代入，得到：
$$
\mathcal{J}(\tilde{A}) = \sum_{i=1}^{N_v} \left( \tilde{A}_i \cdot A^{(G)}_i - A^{(Q)}_i \right)^2 + \lambda \sum_{i=1}^{N_v} \tilde{A}_i^2 \cdot A^{(G)}_i
$$
求解一阶最优性条件，得到闭式解：&lt;/p>
$$
\hat{A}_i = \frac{A^{(Q)}_i}{A^{(G)}_i + \lambda} = \frac{\mathcal{F}_{\text{vis},i} \cdot \mathcal{F}_{\text{sem},i}}{\mathcal{F}_{\text{vis},i} + \lambda} \approx \mathcal{F}_{\text{sem},i} \quad \text{当 } \mathcal{F}_{\text{vis},i} \gg \lambda
$$
&lt;p>&lt;strong>这个公式表明，当视觉噪声占主导时（
$\mathcal{F}_{\text{vis},i} \gg \lambda$），归一化能有效抑制
$\mathcal{F}_{\text{vis},i}$ 的影响，近似得到语义信号
$\mathcal{F}_{\text{sem},i}$。&lt;/strong>&lt;/p>
&lt;h2 id="六carve通过对比注意力降低视觉噪声">六、CARVE：通过对比注意力降低视觉噪声&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/09_00.png" srcset="
/publication/ge2025focusing/figure/09_00_hu5f9e9ba5c8deace460f7501c6c88cbe9_3322818_19e47f370a687c11bdbe558633c12287.webp 400w,
/publication/ge2025focusing/figure/09_00_hu5f9e9ba5c8deace460f7501c6c88cbe9_3322818_3d9734a9f233077454d05319408b8e19.webp 760w,
/publication/ge2025focusing/figure/09_00_hu5f9e9ba5c8deace460f7501c6c88cbe9_3322818_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/09_00_hu5f9e9ba5c8deace460f7501c6c88cbe9_3322818_19e47f370a687c11bdbe558633c12287.webp"
width="760"
height="378"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>CARVE的核心思想是通过对比注意力机制来实现视觉增强。整体上需要三次推理（inference）过程来完成整个流程。&lt;/p>
&lt;p>对于前两次推理，CARVE分别使用任务特定问题和通用指令来获取注意力图。&lt;/p>
&lt;p>第一次推理使用原始图像
$\mathcal{I}$ 和具体问题
$Q$，通过注意力提取函数
$\Xi$ 获得任务特定注意力集合：&lt;/p>
$$
\mathcal{A}^Q = \{A_{l,t}^{(Q)}\}_{l \in \mathcal{L}, t \in \mathcal{T}} = \Xi(\mathcal{M}, \mathcal{I}, Q)
$$
&lt;p>第二次推理使用相同的图像但配以通用指令
$G$（如&amp;quot;Write a general description of the image&amp;quot;），获得通用注意力集合：&lt;/p>
$$
\mathcal{A}^G = \{A_{l,t}^{(G)}\}_{l \in \mathcal{L}, t \in \mathcal{T}} = \Xi(\mathcal{M}, \mathcal{I}, G)
$$
&lt;p>得到两次推理产生的注意力图之后，CARVE进行注意力对比。对所有层
$l \in \mathcal{L}$ 和时间步
$t \in \mathcal{T}$，应用对比公式：&lt;/p>
$$
\hat{A}_{l,t} = \frac{A_{l,t}^{(Q)}}{A_{l,t}^{(G)} + \lambda}
$$
&lt;p>这一步骤通过归一化操作有效地抑制了视觉噪声的影响，提取出任务相关的语义信号。&lt;/p>
&lt;p>接下来进行注意力图融合。由于不同层和时间步捕获互补信息，CARVE通过加权聚合进行融合：&lt;/p>
$$
S = \sum_{t \in \mathcal{T}} w_t \sum_{l \in \mathcal{L}} \pi_{H \times W}(\hat{A}_{l,t})
$$
&lt;p>其中时间步权重
$w_t = t - t_{\text{start}} + 1$，赋予后期token更大权重，因为它们包含更丰富的上下文信息。
$\pi_{H \times W}$ 函数将token维度的注意力重塑为空间维度。&lt;/p>
&lt;p>融合后的注意力图
$S$ 用于生成掩码。首先计算阈值
$\tau = \mathcal{Q}_p(S)$，保留top-p百分位的像素。然后通过连通区域分析，选择累积注意力分数最高的K个区域：&lt;/p>
$$
M^* = \bigcup_{k=1}^{K} R_k^*, \quad \text{其中} \quad R_k^* = \arg\max_{R \in \mathcal{R}} \sum_{(i,j) \in R} S(i,j)
$$
&lt;p>生成掩码后，通过视觉提取函数
$\Phi$ 对原始图像进行处理：&lt;/p>
$$
\mathcal{I}_{\text{refined}} = \Phi(\mathcal{I}, M^*)
$$
&lt;p>函数
$\Phi$ 执行掩码、裁剪和缩放操作，移除视觉噪声并放大任务相关区域。&lt;/p>
&lt;p>最后进行第三次推理，使用增强后的图像和原始问题生成最终答案：&lt;/p>
&lt;p>
$$
\text{Answer} = \mathcal{M}(\mathcal{I}_{\text{refined}}, Q)
$$
&lt;strong>值得注意的是，虽然CARVE需要三次推理，但前两次推理只需要提取特定层（如20-25层）的注意力图，可以在获得所需注意力后提前终止，无需完成全部层的前向传播。此外，通用注意力图
$A^{(G)}$ 只依赖于图像而与具体问题无关，对于同一图像的多个问题可以缓存重用。这些优化使得CARVE在实际应用中的计算开销保持在可接受范围内。&lt;/strong>&lt;/p>
&lt;h2 id="七结果">七、结果&lt;/h2>
&lt;h3 id="71-整体性能表现">7.1 整体性能表现&lt;/h3>
&lt;p>研究团队在四个数据集上测试了CARVE的效果：&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/15_00.png" srcset="
/publication/ge2025focusing/figure/15_00_huf351e692b406650845ae6b141759a188_205070_a5f65ae887cee26fc99a18e864cd5bcb.webp 400w,
/publication/ge2025focusing/figure/15_00_huf351e692b406650845ae6b141759a188_205070_775b2ceda9c6440ba88aef7727250e01.webp 760w,
/publication/ge2025focusing/figure/15_00_huf351e692b406650845ae6b141759a188_205070_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/15_00_huf351e692b406650845ae6b141759a188_205070_a5f65ae887cee26fc99a18e864cd5bcb.webp"
width="760"
height="371"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>早期模型（如LLaVA系列）展现出更大的提升幅度，这表明能力有限的模型更容易受视觉复杂度干扰，因此从对比注意力引导的聚焦机制中获益更多。&lt;/p>
&lt;h3 id="72-时间步选择的影响">7.2 时间步选择的影响&lt;/h3>
&lt;p>实验比较了三种时间步配置：&lt;/p>
&lt;ul>
&lt;li>
$t_{\text{start}}$：使用初始生成token的注意力&lt;/li>
&lt;li>
$t_{\text{end}}$：使用最终token的注意力&lt;/li>
&lt;li>
$\mathcal{T}_{\text{full}}$：所有token的加权融合&lt;/li>
&lt;/ul>
&lt;p>结果显示性能层次：
$t_{\text{end}} > \mathcal{T}_{\text{full}} > t_{\text{start}}$&lt;/p>
&lt;p>这是因为后期token通过访问完整的前序序列编码了更丰富的上下文信息，其注意力图能更准确地定位目标对象。&lt;/p>
&lt;h3 id="73-层选择策略分析">7.3 层选择策略分析&lt;/h3>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/16_00.png" srcset="
/publication/ge2025focusing/figure/16_00_hu0ab179b35fdd000d99556adb415036e9_332556_2c625fe575326163983ffe3a90919c30.webp 400w,
/publication/ge2025focusing/figure/16_00_hu0ab179b35fdd000d99556adb415036e9_332556_7eff28aae52f2605588df90018d48466.webp 760w,
/publication/ge2025focusing/figure/16_00_hu0ab179b35fdd000d99556adb415036e9_332556_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/16_00_hu0ab179b35fdd000d99556adb415036e9_332556_2c625fe575326163983ffe3a90919c30.webp"
width="760"
height="583"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>层选择实验揭示了清晰的性能排序：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>[20,25]层融合&lt;/strong>：最佳性能&lt;/li>
&lt;li>&lt;strong>[15,20]层融合&lt;/strong>：次优&lt;/li>
&lt;li>&lt;strong>单层25&lt;/strong>：中等&lt;/li>
&lt;li>&lt;strong>单层20&lt;/strong>：较低&lt;/li>
&lt;li>&lt;strong>[10,15]层融合&lt;/strong>：最差&lt;/li>
&lt;/ol>
&lt;p>以LLaVA-1.5-7B在TextVQA上的表现为例：&lt;/p>
&lt;ul>
&lt;li>[20,25]层：21.76%提升&lt;/li>
&lt;li>[15,20]层：17.99%提升&lt;/li>
&lt;li>[10,15]层：仅2.93%提升&lt;/li>
&lt;/ul>
&lt;p>多层融合优于单层的原因在于捕获互补信息从而具有更强的鲁棒性，而选择单层的注意力图则会有较强的随机性。&lt;/p>
&lt;h3 id="74-与其他方法的对比">7.4 与其他方法的对比&lt;/h3>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="figure/17_00.png" srcset="
/publication/ge2025focusing/figure/17_00_hud3dc40c45bfe742e0634e6d4b30515f2_59477_c42362eb4b9ae5ba4f9f5d9c5cced697.webp 400w,
/publication/ge2025focusing/figure/17_00_hud3dc40c45bfe742e0634e6d4b30515f2_59477_f8bc25521bd86ad45021a24dff39fb59.webp 760w,
/publication/ge2025focusing/figure/17_00_hud3dc40c45bfe742e0634e6d4b30515f2_59477_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/publication/ge2025focusing/figure/17_00_hud3dc40c45bfe742e0634e6d4b30515f2_59477_c42362eb4b9ae5ba4f9f5d9c5cced697.webp"
width="760"
height="110"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>CARVE显著优于所有基线方法：&lt;/p>
&lt;ul>
&lt;li>外部工具（SAM、YOLO、CLIP）缺乏问题-图像上下文感知&lt;/li>
&lt;li>ViCrop虽能减少视觉噪声，但缺乏像素级噪声掩码&lt;/li>
&lt;li>CARVE在保持实用计算开销的同时达到最高准确率&lt;/li>
&lt;/ul>
&lt;h2 id="八意义与总结">八、意义与总结&lt;/h2>
&lt;p>此前的研究忽略了视觉语言模型的原生能力，当前方法要么需要额外训练、依赖外部分割工具，要么只能在粗粒度层面操作。而CARVE证明了通过对比通用查询和任务特定查询所生成的注意力图，就能在像素层面将视觉信号分解为语义信号和视觉噪声分量，为提高视觉语言模型的能力提供了新的思路。&lt;/p></description></item><item><title>Are All Prompt Components Value-Neutral? Understanding the Heterogeneous Adversarial Robustness of Dissected Prompt in Large Language Models</title><link>https://geyuyao.com/publication/zheng2025all/</link><pubDate>Sun, 03 Aug 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/zheng2025all/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Prompt-based adversarial attacks have become an effective means to assess the robustness of large language models (LLMs). However, existing approaches often treat prompts as monolithic text, overlooking their structural heterogeneity-different prompt components contribute unequally to adversarial robustness. Prior works like PromptRobust assume prompts are value-neutral, but our analysis reveals that complex, domain-specific prompts with rich structures have components with differing vulnerabilities. To address this gap, we introduce PromptAnatomy, an automated framework that dissects prompts into functional components and generates diverse, interpretable adversarial examples by selectively perturbing each component using our proposed method, ComPerturb. To ensure linguistic plausibility and mitigate distribution shifts, we further incorporate a perplexity (PPL)-based filtering mechanism. As a complementary resource, we annotate four public instruction-tuning datasets using the PromptAnatomy framework, verified through human review. Extensive experiments across these datasets and five advanced LLMs demonstrate that ComPerturb achieves state-of-the-art attack success rates. Ablation studies validate the complementary benefits of prompt dissection and PPL filtering. Our results underscore the importance of prompt structure awareness and controlled perturbation for reliable adversarial robustness evaluation in LLMs.&lt;/p></description></item><item><title>Can Graph Descriptive Order Affect Solving Graph Problems with LLMs?</title><link>https://geyuyao.com/publication/ge2025graphdo/</link><pubDate>Mon, 28 Jul 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/ge2025graphdo/</guid><description/></item><item><title>Kimi K2: Open Agentic Intelligence</title><link>https://geyuyao.com/publication/team2025kimi/</link><pubDate>Mon, 28 Jul 2025 00:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/team2025kimi/</guid><description/></item><item><title>A Survey of Context Engineering for Large Language Models</title><link>https://geyuyao.com/publication/mei2025context/</link><pubDate>Thu, 17 Jul 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/mei2025context/</guid><description/></item><item><title>Who is in the Spotlight: The Hidden Bias Undermining Multimodal Retrieval-Augmented Generation</title><link>https://geyuyao.com/publication/yao2025spotlight/</link><pubDate>Fri, 30 May 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/yao2025spotlight/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Multimodal Retrieval-Augmented Generation (RAG) systems have become essential in knowledge-intensive and open-domain tasks. As retrieval complexity increases, ensuring the robustness of these systems is critical. However, current RAG models are highly sensitive to the order in which evidence is presented, often resulting in unstable performance and biased reasoning, particularly as the number of retrieved items or modality diversity grows. This raises a central question: How does the position of retrieved evidence affect multimodal RAG performance? To answer this, we present the first comprehensive study of position bias in multimodal RAG systems. Through controlled experiments across text-only, image-only, and mixed-modality tasks, we observe a consistent U-shaped accuracy curve with respect to evidence position. To quantify this bias, we introduce the Position Sensitivity Index (PSIp) and develop a visualization framework to trace attention allocation patterns across decoder layers. Our results reveal that multimodal interactions intensify position bias compared to unimodal settings, and that this bias increases logarithmically with retrieval range. These findings offer both theoretical and empirical foundations for position-aware analysis in RAG, highlighting the need for evidence reordering or debiasing strategies to build more reliable and equitable generation systems.&lt;/p></description></item><item><title>MIX-MCP (Eth-Beijing Runner-Up🥈)</title><link>https://geyuyao.com/project/eth-beijing/</link><pubDate>Sat, 17 May 2025 16:00:00 +0000</pubDate><guid>https://geyuyao.com/project/eth-beijing/</guid><description>&lt;h1 id="abstract">Abstract:&lt;/h1>
&lt;p>🔥 MIX-MCP is a Go-based MCP service aggregator designed to construct the foundational layer for interaction between large language models (LLMs) and Web3 technologies. Leveraging this, our fully automated Ethereum trading Agent can fetch real-time candlestick data, analyze market indicators, generate market assessment reports, predict ETH trends, construct trading strategies, and integrate real-time market assessments into strategies to smartly initiate or terminate trades on Bitget.&lt;/p>
&lt;p>🚀 In just 48 hours, our team built the core functionalities of MIX-MCP from scratch! Looking ahead, we aim to maintain MIX-MCP long-term and welcome everyone to join the project.&lt;/p>
&lt;hr>
&lt;p>🔥MIX-MCP是一个由GO开发的MCP服务的聚合器，目标是构建大模型与 Web3 交互的底层基座💡🛠️！基于此，我们构建的全自动以太坊交易Agent可以获取实时 K 线数据📊，解析市场指标，生成市场评估报告📈，预测 ETH 走势，构建交易策略💡，将实时市场评估融入策略并智能地在Bitget上开启或终止策略💼。&lt;/p>
&lt;p>🚀在过去的48小时内，我们团队完成了从0到1构建MIX-MCP的主要功能！在未来，我们希望长期维护MIX-MCP，欢迎大家参与到项目中来🤗！&lt;/p></description></item><item><title>PIS:Linking Importance Sampling and Attention Mechanisms for Efficient Prompt Compression</title><link>https://geyuyao.com/publication/chen2025pis/</link><pubDate>Wed, 23 Apr 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/chen2025pis/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Large language models (LLMs) have achieved remarkable progress, demonstrating unprecedented capabilities across various natural language processing tasks. However, the high costs associated with such exceptional performance limit the widespread adoption of LLMs, highlighting the need for prompt compression. Existing prompt compression methods primarily rely on heuristic truncation or abstractive summarization techniques, which fundamentally overlook the intrinsic mechanisms of LLMs and lack a systematic evaluation of token importance for generation. In this work, we introduce Prompt Importance Sampling (PIS), a novel compression framework that dynamically compresses prompts by sampling important tokens based on the analysis of attention scores of hidden states. PIS employs a dual-level compression mechanism:1) at the token level, we quantify saliency using LLM-native attention scores and implement adaptive compression through a lightweight 9-layer reinforcement learning (RL) network; 2) at the semantic level, we propose a Russian roulette sampling strategy for sentence-level importance sampling. Comprehensive evaluations across multiple domain benchmarks demonstrate that our method achieves state-of-the-art compression performance. Notably, our framework serendipitously enhances reasoning efficiency through optimized context structuring. This work advances prompt engineering by offering both theoretical grounding and practical efficiency in context management for LLMs.&lt;/p></description></item><item><title>a1: Steep Test-time Scaling Law via Environment Augmented Generation</title><link>https://geyuyao.com/publication/mei2025a1/</link><pubDate>Sun, 20 Apr 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/mei2025a1/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Large Language Models (LLMs) have made remarkable breakthroughs in reasoning, yet continue to struggle with hallucinations, logical errors, and inability to self-correct during complex multi-step tasks. Current approaches like chain-of-thought prompting offer limited reasoning capabilities that fail when precise step validation is required. We propose Environment Augmented Generation (EAG), a framework that enhances LLM reasoning through: (1) real-time environmental feedback validating each reasoning step, (2) dynamic branch exploration for investigating alternative solution paths when faced with errors, and (3) experience-based learning from successful reasoning trajectories. Unlike existing methods, EAG enables deliberate backtracking and strategic replanning through tight integration of execution feedback with branching exploration. Our a1-32B model achieves state-of-the-art performance among similar-sized models across all benchmarks, matching larger models like o1 on competition mathematics while outperforming comparable models by up to 24.4 percentage points. Analysis reveals EAG&amp;rsquo;s distinctive scaling pattern: initial token investment in environment interaction yields substantial long-term performance dividends, with advantages amplifying proportionally to task complexity. EAG&amp;rsquo;s theoretical framework demonstrates how environment interactivity and systematic branch exploration together establish a new paradigm for reliable machine reasoning, particularly for problems requiring precise multi-step calculation and logical verification.&lt;/p></description></item><item><title>Innate Reasoning is Not Enough : In-Context Learning Enhances Reasoning Large Language Models with Less Overthinking</title><link>https://geyuyao.com/publication/ge2025icl/</link><pubDate>Tue, 25 Mar 2025 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/ge2025icl/</guid><description/></item><item><title>EMNLP2024论文分享 | Fewer is More：CoT示例要少而精</title><link>https://geyuyao.com/post/few-is-more/</link><pubDate>Thu, 24 Oct 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/few-is-more/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Fewer is More: Boosting LLM Reasoning with Reinforced Context Pruning&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Hong Kong University of Science and Technology, Microsoft Research&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Xijie Huang Li, Lyna Zhang, Kwang-Ting Cheng, Fan Yang, Mao Yang&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2312.08901" target="_blank" rel="noopener">https://arxiv.org/abs/2312.08901&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2024.2.15&lt;/p>
&lt;h1 id="一摘要">一、摘要&lt;/h1>
&lt;p>即使使用了CoT，LLMs在解决数学推理问题的表现依旧不尽人意。作者提出CoT-Influx方法，一种对CoT的示例和内容进行优化从而提高LLMs推理能力的方法，其核心思想是通过剪枝最大化有效信息的输入。&lt;/p>
&lt;h1 id="二动机">二、动机&lt;/h1>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>链式推理示例（Chain-of-Thought, CoT）的潜力未被充分利用&lt;/strong>：&lt;br>
之前的研究表明，提供分步的链式推理示例可以帮助模型更好地进行复杂推理。然而，由于模型的上下文窗口长度（context window size）有限，&lt;strong>能够输入的CoT示例数量受到限制&lt;/strong>，因此无法完全发挥CoT的潜力。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>现有解决方案的局限性&lt;/strong>：&lt;br>
扩展上下文窗口虽然可以容纳更多的CoT示例，&lt;strong>但会增加推理成本和复杂度，代价高昂&lt;/strong>。而现有的基于压缩或检索的技术在数学推理任务上表现不佳，尤其是无法有效地选择对特定任务最有帮助的CoT示例和token。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>基于这些动机，本文提出了&lt;strong>CoT-Influx&lt;/strong>方法，旨在解决上述问题。其目标是通过剪枝策略，在不增加计算成本的前提下，增加输入文本的质量。&lt;/p>
&lt;h1 id="三观察">三、观察&lt;/h1>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>更多的CoT示例可以提升LLMs推理性能&lt;/strong>：
增加CoT示例的数量能够提升LLMs在数学推理任务中的表现，但受限于上下文窗口长度，LLMs无法输入足够多的示例。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>CoT示例选择至关重要&lt;/strong>：
并非所有的CoT示例都有助于推理，随意添加错误、冗余、误导的示例甚至可能导致性能下降。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>CoT示例中存在冗余token&lt;/strong>：
CoT示例中往往包含不必要的冗余token，这些token可以被剪枝以腾出更多空间容纳更有用的内容，从而提高推理效果。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="四方法cot-influx">四、方法：CoT-Influx&lt;/h1>
&lt;h2 id="简要不看细节版">简要不看细节版&lt;/h2>
&lt;p>CoT-Influx将LLM视为黑盒，关键模块是一个粗糙到精细的剪枝器，目的在于生成高质量、低长度的CoT示例，包括两个步骤：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>样本剪枝（Shot Pruner）&lt;/strong>：首先，从一大批CoT示例中筛选出对目标问题最有帮助的k个示例。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>标记剪枝（Token Pruner）&lt;/strong>：接着，从这些被保留下来的CoT示例中进一步剪枝，移除不重要的token，生成精简版本。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>最后，将精简后的CoT示例拼接在问题前面，完成！&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1729793114717.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;h2 id="细节版">细节版&lt;/h2>
&lt;h3 id="1-问题定义">1. &lt;strong>问题定义&lt;/strong>&lt;/h3>
&lt;p>给定一个链式推理示例集合
$\mathcal{D} = \{x_{\text{cot}}^i\}_{i=1}^{n}$，每个示例
$x_{\text{cot}}^i$ 由问题、推理步骤和答案组成，且其token数量超出LLM的上下文窗口长度
$T$。我们希望通过两阶段的剪枝过程，对
$\mathcal{D}$ 进行优化，生成有效输入，使其token总数
$t(x_{\text{input}})$ 满足：&lt;/p>
$$
t(x_{\text{input}}) \leq T
$$
&lt;p>同时保证LLM能够基于此输入生成正确的推理结果。&lt;/p>
&lt;h3 id="2-两阶段剪枝过程">2. &lt;strong>两阶段剪枝过程&lt;/strong>&lt;/h3>
&lt;p>CoT-Influx的两阶段剪枝过程通过策略网络选择有用的链式推理示例和相关token，具体描述如下：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>第一阶段：样本剪枝（Shot Pruner）&lt;/strong>&lt;br>
该阶段使用一个包含两层隐藏层的多层感知机（MLP）从一批链式推理示例中选择出最有用的
$k'$个示例。MLP的输入是每个示例的文本嵌入向量，表示为
$H_{\text{shot}} \in \mathbb{R}^{k \times N \times D_{\text{BERT}}}$，其中
$k$是批量大小，
$N=512$是每个示例的token数，
$D_{\text{BERT}}$是BERT嵌入的维度。MLP经过计算后输出一个概率分布：&lt;/li>
&lt;/ul>
$$
\pi_{\theta_1}(a_{\text{shot}} | s_{\text{shot}}) = \sigma(\text{MLP}(H_{\text{shot}}))
$$
&lt;p>其中，
$\sigma$为Sigmoid激活函数，动作
$a_{\text{shot}}$表示是否保留该CoT示例。选择后的示例集为：&lt;/p>
$$
\mathcal{D'} = \{x_{\text{cot}}^j \in \mathcal{D} : a_{\text{shot}}^j = 1\}
$$
&lt;ul>
&lt;li>&lt;strong>第二阶段：token剪枝（Token Pruner）&lt;/strong>&lt;br>
对保留下来的示例集
$\mathcal{D'}$，使用另一层包含两层隐藏层的MLP进一步剪枝每个示例中的token。类似地，MLP的输入是保留示例的嵌入向量
$H_{\text{token}} \in \mathbb{R}^{k' \times N \times D_{\text{BERT}}}$，输出概率分布决定每个token是否保留：&lt;/li>
&lt;/ul>
$$
\pi_{\theta_2}(a_{\text{token}} | s_{\text{token}}) = \sigma(\text{MLP}(H_{\text{token}}))
$$
&lt;p>剪枝后的token集为：&lt;/p>
$$
\hat{x}_{\text{cot}}^j = \{ \text{token} \in x_{\text{cot}}^j : a_{\text{token}} = 1 \}
$$
&lt;h3 id="3-优化目标多目标奖励函数">3. &lt;strong>优化目标：多目标奖励函数&lt;/strong>&lt;/h3>
&lt;p>CoT-Influx的优化目标就是通过一个&lt;strong>多目标奖励函数&lt;/strong>，在保持推理准确性的同时，尽量减少冗余的示例和token。这个奖励函数综合了LLM的推理损失、推理的准确性和输入的token数量。具体定义为：&lt;/p>
$$
R(x_{\text{input}}) = \left( \frac{1}{1 + L_{\text{LLM}}(x_{\text{input}})} + R_{\text{Acc}} \right) \times \left( \frac{t(x_{\text{input}})}{T} \right)^w
$$
&lt;p>其中：&lt;/p>
&lt;ul>
&lt;li>
$L_{\text{LLM}}(x_{\text{input}})$ 表示LLM的推理损失；&lt;/li>
&lt;li>
$R_{\text{Acc}}$ 是推理的准确性（正确时为1，错误时为0）；&lt;/li>
&lt;li>
$t(x_{\text{input}})$ 是输入的token数量；&lt;/li>
&lt;li>
$T$ 是上下文窗口的最大token长度；&lt;/li>
&lt;li>
$w$ 是用于调整token数量影响的超参数。&lt;/li>
&lt;/ul>
&lt;p>通过这个多目标奖励函数，CoT-Influx引导剪枝器最大化推理准确性，并尽量压缩输入token的总量，确保输入不超出上下文窗口长度。&lt;/p>
&lt;h3 id="4-强化学习优化">4. &lt;strong>强化学习优化&lt;/strong>&lt;/h3>
&lt;p>为了优化剪枝策略网络，CoT-Influx使用了&lt;strong>REINFORCE&lt;/strong>进行优化，通过最大化奖励函数来调整两阶段剪枝器的参数。&lt;/p>
$$
\nabla_\theta J(\theta) = R(x_{\text{input}}) \cdot \left( \nabla_\theta \log \pi_{\theta_1}(a_{\text{shot}} | s_{\text{shot}}) + \nabla_\theta \log \pi_{\theta_2}(a_{\text{token}} | s_{\text{token}}) \right)
$$
&lt;h2 id="五结果">五、结果&lt;/h2>
&lt;p>下图展示了CoT-Influx在GSM8K数据集上的表现&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1729791928636.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>值得注意的是，如下图所示，LLaMA2-70B搭配CoT-Influx在没有任何微调的情况下超过了更大的LLMs。比如LLaMA2-70B相比GPT-3.5提高了2.5%。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1729791914198.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;h1 id="六发现">六、发现&lt;/h1>
&lt;ol>
&lt;li>更具能力的LLM偏爱更难的CoT示例，而较小的LLM则选择更简单的示例。&lt;/li>
&lt;li>数字和格式标记对于数学推理至关重要。像with、the、then这样的功能词，以及与推理能力无关的背景环境，如theater,可以被剪掉而不影响推理能力。&lt;/li>
&lt;/ol>
&lt;h1 id="七评价">七、评价&lt;/h1>
&lt;ol>
&lt;li>
&lt;p>虽然思路很自然，这篇文章还是具有一定的启发性的，尤其是对架构的设计和优化部分。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这篇文章讲故事的水平是很高超的，可以把来龙去脉讲的非常吸引人，比如Pilot Study部分。能把简单的东西讲的很高深但却易于理解。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在实验上有很多可以学习的地方，比如消融实验和许多小的实验，逻辑很严谨。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在实用性上有待讨论，首先使用强化学习的方法就意味着这种方法对成本是有一定需求的。其次，我认为这个方法是一个端到端的设计，如果换数据集就需要重新训练。最后，也许这个网络训练出来删除掉的就是with、the、then这样的词，如果真是如此死板，那不如使用词表的方法。当然此条只是推测。&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>编码实践 | 一文读懂Tokenizer | 以Word-based 和 Byte Pair Encoding为例</title><link>https://geyuyao.com/post/tokenizer/</link><pubDate>Wed, 03 Jul 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/tokenizer/</guid><description>&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>&lt;strong>分词器 (Tokenizer)&lt;/strong> 是自然语言处理领域中一种关键的工具，其作用在于将文本字符串划分为词元也就是token。分词器在文本预处理阶段起着至关重要的作用，为后续的文本分析、信息检索、机器翻译等任务提供基础。&lt;/p>
&lt;h2 id="渊源与发展">渊源与发展&lt;/h2>
&lt;p>分词器的历史可以追溯到计算语言学和信息检索的发展早期。随着计算机科学的发展，研究人员认识到在处理自然语言文本时，需要将连续的文本序列划分为具有语义意义的基本单位 (在语言学中称语素)。早期的分词方法主要基于规则和词典，依靠预定义的规则和词库来识别词语边界。随着统计自然语言处理和机器学习的兴起，统计模型和数据驱动的方法逐渐取代了基于规则的方法。&lt;/p>
&lt;p>近年来，深度学习技术的发展进一步推动了分词技术的进步。特别是BERT (Bidirectional Encoder Representations from Transformers) 等预训练语言模型的引入，采用了子词级别的分词方法，如Byte Pair Encoding (BPE) 、WordPiece和SentencePiece等，这些方法能够更好地处理未登录词和语言多样性的问题。&lt;/p>
&lt;h2 id="motivation">Motivation&lt;/h2>
&lt;p>要理解Tokenizer，我们首先要理解使用Tokenizer的动机是什么。&lt;/p>
&lt;p>在 NLP 任务中，通常处理的数据是原始文本。&lt;/p>
&lt;p>以下文为例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Jim Henson was a puppeteer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>但是，模型只能处理数字，因此我们需要找到一种将原始文本转换为数字的方法。这正是Tokenizer所做的事。&lt;/p>
&lt;p>概括来讲，Tokenizer的目标就是将人类能理解的文本转为机器所能理解的数字。&lt;/p>
&lt;p>接下来，我们将介绍一种最简单和直观的分词方法——&lt;strong>基于单词的分词器 (Word-based Tokenizer)&lt;/strong>&lt;/p>
&lt;h1 id="最简单和直观的分词方法word-based-tokenizer">最简单和直观的分词方法——Word-based Tokenizer&lt;/h1>
&lt;p>&lt;em>本章部分内容参考自 huggingface NLP Course&lt;/em> &lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/p>
&lt;p>书接上文，那如何把文本&lt;code>Jim Henson was a puppeteer&lt;/code>转为数字呢？&lt;/p>
&lt;p>一个直观的方法就是以空格分割这段字符串，为每一个单词赋予一个唯一的数字作为索引。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">tokenized_text = &amp;#34;Jim Henson was a puppeteer&amp;#34;.split()
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">print(tokenized_text)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">[&amp;#39;Jim&amp;#39;, &amp;#39;Henson&amp;#39;, &amp;#39;was&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;puppeteer&amp;#39;]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这样，每个单词都分配了一个 ID，从 0 开始一直到词汇表的大小。该模型使用这些 ID 来识别每个单词。&lt;/p>
&lt;p>如果我们想用 Word-based Tokenizer 完全覆盖一种语言，就需要为语言中的每个单词都赋予一个唯一整数索引，这将生成大量的索引。例如，英语中有超过 500,000 个单词，因此要构建从每个单词到索引的映射，我们需要创建包含500,000个元素的字典。但这还不只是 Word-based Tokenizer 唯一的缺点。&lt;/p>
&lt;p>此外，像 &amp;ldquo;dog&amp;rdquo; 这样的词与 &amp;ldquo;dogs&amp;rdquo; 这样的词的表示方式不同，模型无法知道&amp;quot;dog&amp;quot;和&amp;quot;dogs&amp;quot;是相似的：它会将这两个词识别为不相关。这同样适用于其他相似的词，例如&amp;quot;run&amp;quot;和&amp;quot;running&amp;quot;，模型不会认为它们是相似的。&lt;/p>
&lt;p>此外，我们需要一个自定义token来表示不在我们词汇表中的单词，这被称为&amp;quot;未知&amp;quot;标记(token)，通常表示为&amp;quot;[UNK]&amp;ldquo;或&amp;rdquo;&amp;lt;unk&amp;gt;&amp;quot;。如果你看到Tokenizer产生了很多这样的Token，这通常是一个不好的迹象，因为它无法检索到一个词的索引，这就意味着在分词的过程中会产生信息缺失，这一缺点是极其致命的。&lt;/p>
&lt;p>综上，我们总结了Word-based Tokenizer的几大缺点：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>词汇表规模大&lt;/strong>: 由于不同语言和应用场景中的词汇量非常庞大，Word-based Tokenizer需要一个非常大的词汇表。这不仅增加了存储和计算的开销，还会导致训练和推理效率下降。此外，在实际应用中，许多单词是低频词。如果词汇表中包含大量低频词，会导致稀疏数据问题。&lt;/li>
&lt;li>&lt;strong>难以处理形态变化灵活的单词&lt;/strong>: 许多语言具有丰富的形态变化 (如英语的复数形式、时态变化，法语的性别变化等) 。Word-based Tokenizer需要包含所有这些形态变化形式，导致词汇表进一步膨胀。此外，不同形式的同一词语被视为不同的词元，导致模型无法有效共享这些词语的语义信息。&lt;/li>
&lt;li>&lt;strong>词汇表覆盖范围有限，无法处理未登录词 (Out-of-Vocabulary Words)&lt;/strong>: Word-based Tokenizer需要一个固定的词汇表。如果遇到词汇表中没有的新词或拼写错误的词，它们将无法处理。这导致Tokenizer无法处理这些未登录词，影响其泛化能力。&lt;/li>
&lt;/ol>
&lt;h1 id="更精细的分词方法byte-pair-encoding-bpe">更精细的分词方法——Byte Pair Encoding (BPE)&lt;/h1>
&lt;p>在上文提到，Word-based Tokenizer存在词表大、难以处理灵活的单词形态、词表覆盖范围有限的问题。那么，是否有一种分词方法可以解决上述问题呢？&lt;/p>
&lt;p>我们注意到，在英文单词中，存在大量复用的字母组合。以 &amp;ldquo;happy&amp;rdquo; 为例，以 &amp;ldquo;happy&amp;rdquo; 为词根的单词有很多，如 &amp;ldquo;happily&amp;rdquo;、&amp;ldquo;happiness&amp;rdquo;、&amp;ldquo;unhappy&amp;quot;等。我们注意到，这些衍生词可以拆分成字母组合并复用，如&amp;quot;happ&amp;quot;这一字母组合在三个单词中都有出现。此外， &amp;ldquo;ily&amp;rdquo;、&amp;ldquo;un&amp;rdquo; 字母组合在其他英语单词中高频出现，它们和其他单词的组合也可以用于表示新的单词。&lt;/p>
&lt;p>自然而然的，我们想到，是否可以基于这种 &amp;ldquo;找高频出现的字母组合&amp;rdquo; 的方法设计出一种分词器，从而通过复用各种字母组合来覆盖所有英文单词呢？&lt;/p>
&lt;p>如果可以，这种分词器会解决Word-based Tokenizer存在的三种缺点，这是因为：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>复用性高导致词表规模小&lt;/strong>：由于各种单词是由各种字母组合构成的，复用性高，因此只需要少量的字母组合就可以覆盖大多数的英语单词。&lt;/li>
&lt;li>&lt;strong>易于处理灵活多变的单词形态&lt;/strong>：在本节的样例中，我们的词表中存在 &amp;ldquo;ily&amp;rdquo;、&amp;ldquo;un&amp;rdquo; 等token，这些token在其他经过形态变化的单词中也高频出现，因此适用于处理灵活多变的单词形态。&lt;/li>
&lt;li>&lt;strong>单词覆盖范围广&lt;/strong>：该方法从单个字母开始，寻找各种字母组合，可以覆盖所有的英文单词。&lt;/li>
&lt;/ol>
&lt;p>事实上，这种方法就是&lt;strong>字节对编码(Byte Pair Encoding, BPE)&lt;/strong>。&lt;/p>
&lt;p>&lt;strong>Byte Pair Encoding (BPE)&lt;/strong> 是一种源于数据压缩领域的子词分割技术，现已广泛应用于自然语言处理任务。&lt;strong>BPE的核心思想是通过迭代地合并出现频率最高的字节对，逐步构建子词单元，从而实现文本的分段&lt;/strong>。该方法最早由Philip Gage在1994年提出&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>，用于文件压缩，随后被Sennrich等人在2015年引入到机器翻译中&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>，以应对词汇表过大和稀疏性问题。&lt;/p>
&lt;p>在大模型时代，许多著名的大模型的分词器使用的正是BPE，如GPT系列、BERT、RoEBRTa、T5等。可以说，BPE已经是自然语言处理领域最经典的算法之一。&lt;/p>
&lt;p>在下一章节，我们将根据&lt;a href="https://github.com/karpathy" target="_blank" rel="noopener">Andrej&lt;/a>的项目&lt;a href="https://github.com/karpathy/minbpe" target="_blank" rel="noopener">minbpe&lt;/a>逐步构建一个BPE。&lt;/p>
&lt;blockquote>
&lt;p>值得一提的是，Andrej有许多知名的大模型项目，如 &lt;a href="https://github.com/karpathy/llm.c" target="_blank" rel="noopener">llm.c &lt;/a>和 &lt;a href="https://github.com/karpathy/llama2.c" target="_blank" rel="noopener">llama2.c&lt;/a>等。&lt;/p>
&lt;/blockquote>
&lt;h1 id="代码实践手撕bpe">代码实践：手撕BPE&lt;/h1>
&lt;p>在本章节，我们将根据&lt;a href="https://github.com/karpathy" target="_blank" rel="noopener">Andrej&lt;/a>的项目&lt;a href="https://github.com/karpathy/minbpe" target="_blank" rel="noopener">minbpe&lt;/a>逐步构建一个BPE&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>。&lt;/p>
&lt;h2 id="基类tokenizer">基类Tokenizer&lt;/h2>
&lt;p>首先，我们给出BPE的基类形态，即&lt;code>Tokenizer&lt;/code> 类的定义：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Tokenizer&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Base class for Tokenizers&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># default: vocab size of 256 (all bytes), no merges, no patterns&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merges&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="c1"># (int, int) -&amp;gt; int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_build_vocab&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># int -&amp;gt; bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">train&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vocab_size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">verbose&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Tokenizer can train a vocabulary of size vocab_size from text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Tokenizer can encode a string into a list of integers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Tokenizer can decode a list of integers into a string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">_build_vocab&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># vocab is simply and deterministically derived from merges&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">bytes&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">idx&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">256&lt;/span>&lt;span class="p">)}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">vocab&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在类&lt;code>Tokenizer&lt;/code>中，存在四个基本函数分别是&lt;code>init&lt;/code>、&lt;code>train&lt;/code>、&lt;code>encode&lt;/code>、&lt;code>decode&lt;/code> 分别对应了分词器的初始化、训练、编码、解码过程，其中&lt;code>train&lt;/code>、&lt;code>encode&lt;/code>、&lt;code>decode&lt;/code> 作为虚函数将被子类的同名函数覆盖。&lt;/p>
&lt;p>此外，在项目&lt;a href="https://github.com/karpathy/minbpe" target="_blank" rel="noopener">minbpe&lt;/a>中还有保存、加载分词器模型的功能，因与主题关系有限和篇幅限制在此不做赘述，有兴趣的读者可自行查阅&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup>。&lt;/p>
&lt;p>在&lt;code>init&lt;/code>函数中，我们定义两个变量，分别是&lt;code>self.merges = {}&lt;/code>和&lt;code>self.vocab&lt;/code>。前者用于记录在分词器过程中，两个相邻原始token的索引可被合并为的新的token的索引的映射关系，即&lt;code>(int, int) -&amp;gt; int&lt;/code>；后者用于表示词表，词表记录了索引到token的映射关系，即&lt;code>int -&amp;gt; bytes&lt;/code>。&lt;/p>
&lt;p>其中， &lt;code>self.vocab&lt;/code> 在&lt;code>init&lt;/code>函数中被初始化，在这里，我们使用256个整数作为索引 (&lt;code>idx&lt;/code>) 映射到十六进制表示的256个token (&lt;code>bytes([idx])&lt;/code>)。&lt;/p>
&lt;p>如果我们在&lt;code>_build_vocab&lt;/code>函数中打印 &lt;code>vocab&lt;/code> 会得到：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">{0: b&amp;#39;\x00&amp;#39;, 1: b&amp;#39;\x01&amp;#39;, 2: b&amp;#39;\x02&amp;#39;, 3: b&amp;#39;\x03&amp;#39;, ..., 254: b&amp;#39;\xfe&amp;#39;, 255: b&amp;#39;\xff&amp;#39;}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="bpe">BPE&lt;/h2>
&lt;p>接下来，我们给出BPE类的定义：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">BPE&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tokenizer&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">train&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vocab_size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">verbose&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_stats&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">counts&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Given a list of integers, return a dictionary of counts of consecutive pairs
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Example: [1, 2, 3, 1, 2] -&amp;gt; {(1, 2): 2, (2, 3): 1, (3, 1): 1}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Optionally allows to update an existing dictionary of counts
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">counts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">counts&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="n">counts&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">pair&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">zip&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">:]):&lt;/span> &lt;span class="c1"># iterate consecutive elements&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">counts&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">counts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">counts&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">merge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pair&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">idx&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> In the list of integers (ids), replace all consecutive occurrences
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> of pair with the new integer token idx
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Example: ids=[1, 2, 3, 1, 2], pair=(1, 2), idx=4 -&amp;gt; [4, 3, 4]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">newids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if not at the very last position AND the pair matches, replace it&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">pair&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">pair&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">newids&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">newids&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">newids&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="n">vocab_size&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">num_merges&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vocab_size&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># input text preprocessing&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_bytes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># raw bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text_bytes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># list of integers in range 0..255&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># iteratively merge the most common pairs to create new tokens&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">merges&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span> &lt;span class="c1"># (int, int) -&amp;gt; int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">bytes&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">idx&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">256&lt;/span>&lt;span class="p">)}&lt;/span> &lt;span class="c1"># int -&amp;gt; bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num_merges&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># count up the number of times every consecutive pair appears&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stats&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_stats&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># find the pair with the highest count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pair&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stats&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">stats&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># mint a new token: assign it the next available id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">idx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># replace all occurrences of pair in ids with idx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">merge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pair&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">idx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># save the merge&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">merges&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">idx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vocab&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vocab&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">vocab&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">verbose&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;merge &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">num_merges&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">vocab&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">) had &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">stats&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> occurrences&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># save class variables&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merges&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">merges&lt;/span> &lt;span class="c1"># used in encode()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vocab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vocab&lt;/span> &lt;span class="c1"># used in decode()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># given ids (list of integers), return Python string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_bytes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">vocab&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">idx&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ids&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text_bytes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">errors&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;replace&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># given a string text, return the token ids&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text_bytes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># raw bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text_bytes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># list of integers in range 0..255&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># find the pair with the lowest merge index&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stats&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_stats&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pair&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stats&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merges&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">float&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inf&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># subtle: if there are no more merges available, the key will&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># result in an inf for every single pair, and the min will be&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># just the first pair in the list, arbitrarily&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># we can detect this terminating case by a membership check&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">pair&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merges&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span> &lt;span class="c1"># nothing else can be merged anymore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># otherwise let&amp;#39;s merge the best pair (lowest merge index)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">idx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">merges&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">pair&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">merge&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pair&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">idx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ids&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在BPE类中，对 &lt;code>train&lt;/code>、&lt;code>encode&lt;/code>、&lt;code>decode&lt;/code> 函数进行了复写，而 &lt;code>init&lt;/code> 函数继承自&lt;code>Tokenizer&lt;/code>类。&lt;/p>
&lt;p>我们按照 &lt;code>train&lt;/code>、&lt;code>encode&lt;/code>、&lt;code>decode&lt;/code> 的顺序对函数逐个介绍：&lt;/p>
&lt;h3 id="bpetrain">BPE.train&lt;/h3>
&lt;p>在&lt;code>train&lt;/code>函数中，存在两个函数，分别是 &lt;code>get_stats&lt;/code> 和 &lt;code>merge&lt;/code> 。&lt;/p>
&lt;p>&lt;code>def get_stats(ids)&lt;/code> : 该函数用于统计每两个相邻token出现的频率。举例来讲，当 &lt;code>ids = [1, 2, 3, 1, 2]&lt;/code> 那么其返回值为 &lt;code>{(1, 2): 2, (2, 3): 1, (3, 1): 1}&lt;/code> &lt;sup id="fnref:6">&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref">6&lt;/a>&lt;/sup>。&lt;/p>
&lt;p>&lt;code>def merge(ids, pair, idx)&lt;/code> : 该函数用于将ids中存在的pair合并为idx，返回新的ids列表。举例来讲，当 &lt;code>ids=[1, 2, 3, 1, 2], pair=(1, 2), idx=4 -&amp;gt; [4, 3, 4]&lt;/code> ，我们会将&lt;code>ids&lt;/code>中相邻的&lt;code>1, 2&lt;/code>用 &lt;code>4&lt;/code>替换，获得新的ids &lt;code>[4, 3, 4]&lt;/code>。&lt;/p>
&lt;p>在 &lt;code>train&lt;/code> 函数中，我们首先需要将字符串中的字符转为索引，通过 &lt;code>text_bytes = text.encode(&amp;quot;utf-8&amp;quot;) &lt;/code> 和 &lt;code>ids = list(text_bytes) &lt;/code>我们可以达到这个目的。例如，当 &lt;code>text = 'aaabbc'&lt;/code> 时，&lt;code>ids = [97, 97, 97, 98, 98, 99]&lt;/code>。&lt;/p>
&lt;p>接下来，在循环中，首先在 &lt;code>get_stats&lt;/code> 中&lt;strong>统计&lt;/strong> &lt;code>ids&lt;/code> &lt;strong>中各个相邻token的出现频率&lt;/strong>。聪明的读者读到这里已经猜到这样做的目的是什么了，这样做的目的正是为了&lt;strong>将这些出现频率高的token合并为新的token&lt;/strong>，而这个过程正是 &lt;code>merge&lt;/code>。此时，&lt;code>ids&lt;/code>的长度已经缩短了。最后，在merge和词表&lt;code>vocab&lt;/code>中分别记录token对与索引的映射关系和索引和新token的映射关系。&lt;/p>
&lt;p>重复上述过程，直至循环结束。&lt;/p>
&lt;p>那么，我们来思考一下，&lt;code>train&lt;/code> 的过程是在做一件什么事呢？&lt;/p>
&lt;p>事实上，&lt;code>train&lt;/code> 的过程就是将高频出现的两个相邻token对合并为一个新的token。这样，只需要在词表中增加少量的映射关系，就可以大幅减少训练文本的长度。需要注意的是，一开始，词表中只有单个字母。随着训练的进行，词表中会逐渐增加高频出现的字母对，从两个字母构成的字母对到多个字母构成的字母序列，以此类推。&lt;/p>
&lt;p>以训练文本&lt;code>text = &amp;quot;happily happiness unhappy&amp;quot;&lt;/code>为例，三轮循环中，每轮输出的日志如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">merge 1/3: (104, 97) -&amp;gt; 256 (b&amp;#39;ha&amp;#39;) had 3 occurrences
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">merge 2/3: (256, 112) -&amp;gt; 257 (b&amp;#39;hap&amp;#39;) had 3 occurrences
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">merge 3/3: (257, 112) -&amp;gt; 258 (b&amp;#39;happ&amp;#39;) had 3 occurrences
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我们注意到，在三次循环结束后，&lt;code>happ&lt;/code> 出现在了词表中。这就表示 &lt;code>happ&lt;/code> 这一高频出现的字母组合可被应用于后续的解码和编码过程中。&lt;/p>
&lt;h3 id="bpeencode">BPE.encode&lt;/h3>
&lt;p>在 &lt;code>encode&lt;/code> 函数中，我们还是先检索文本中高频出现的token对。接着，我们查找在merge函数中索引数最小的token对。这是因为，在训练过程中，索引数越小，在训练集中出现的频率越高，从统计学的角度来讲是合理的&lt;sup id="fnref:7">&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref">7&lt;/a>&lt;/sup>。接着，将token对按照 &lt;code>merge&lt;/code> 中的映射关系，映射为新的token，从而获得新的token序列。重复此过程，直至没有token对可被合并 (化简) 。&lt;/p>
&lt;h3 id="bpedecode">BPE.decode&lt;/h3>
&lt;p>&lt;code>decode&lt;/code> 函数接受一个整数的索引列表 &lt;code>ids&lt;/code>，将其转换为对应的字节序列，并将该字节序列解码为 UTF-8 编码的字符串。最终返回原始字符串的解码版本。该函数是 &lt;code>encoder&lt;/code> 的逆过程。&lt;/p>
&lt;h1 id="总结">总结&lt;/h1>
&lt;p>总结来讲，BPE的训练是在寻找训练集中高频出现的token组合；解码过程是将文本中出现的可合并的token用新的token替换从而生成新的token序列；解码过程则是解码的逆过程。&lt;/p>
&lt;p>此时，我们给出我们在文章中提到的BPE的三个优点的原因。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>复用性高导致词表规模小&lt;/strong>：相比于Word-based Tokenizer，BPE无需为每一个单词都建立一个映射关系，而只需要对高频出现的token序列建立映射关系即可。&lt;/li>
&lt;li>&lt;strong>易于处理灵活多变的单词形态&lt;/strong>：无论单词如何变化，那些高频出现的token序列如过去式&lt;code>ed&lt;/code>、副词 &lt;code>ly&lt;/code>已被包含在词表中，在编码过程中可被高效利用。&lt;/li>
&lt;li>&lt;strong>单词覆盖范围广&lt;/strong>：即使当前单词中存在词表中不存在的token序列，我们也可以可以用词表中存在的单个字母来表示。因此，BPE可以覆盖所有的英文单词。&lt;/li>
&lt;/ol>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://huggingface.co/learn/nlp-course/zh-CN/chapter2/4" target="_blank" rel="noopener">https://huggingface.co/learn/nlp-course/zh-CN/chapter2/4&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>Gage P. A new algorithm for data compression[J]. The C Users Journal, 1994, 12(2): 23-38.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>Sennrich R, Haddow B, Birch A. Neural machine translation of rare words with subword units[J]. arXiv preprint arXiv:1508.07909, 2015.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;a href="https://github.com/karpathy/minbpe" target="_blank" rel="noopener">https://github.com/karpathy/minbpe&lt;/a>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>&lt;a href="https://github.com/karpathy/minbpe/blob/master/minbpe/base.py" target="_blank" rel="noopener">https://github.com/karpathy/minbpe/blob/master/minbpe/base.py&lt;/a>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:6">
&lt;p>当然，在实际的字符串中，字母 &lt;code>a&lt;/code> 对应的索引是 &lt;code>97&lt;/code> 以此类推，使用 &lt;code>[1, 2, 3, 1, 2]&lt;/code> 是起到方便理解的作用。&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:7">
&lt;p>需要注意的是，BPE是一种启发式的分词方法，并不是追求最优解，因此编码获得的token序列并不是最短的，而是相对较短的。&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Translating Words to Worlds: Zero-Shot Synthesis of 3D Terrain from Textual Descriptions Using Large Language Models</title><link>https://geyuyao.com/publication/zhang2024terrain/</link><pubDate>Mon, 01 Jul 2024 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/zhang2024terrain/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>The current research on text-guided 3D synthesis predominantly utilizes complex diffusion models, posing significant challenges in tasks like terrain generation. This study ventures into the direct synthesis of text-to-3D terrain in a zero-shot fashion, circumventing the need for diffusion models. By exploiting the large language model’s inherent spatial awareness, we innovatively formulate a method to update existing 3D models through text, thereby enhancing their accuracy. Specifically, we introduce a Gaussian–Voronoi map data structure that converts simplistic map summaries into detailed terrain heightmaps. Employing a chain-of-thought behavior tree approach, which combines action chains and thought trees, the model is guided to analyze a variety of textual inputs and extract relevant terrain data, effectively bridging the gap between textual descriptions and 3D models. Furthermore, we develop a text–terrain re-editing technique utilizing multiagent reasoning, allowing for the dynamic update of the terrain’s representational structure. Our experimental results indicate that this method proficiently interprets the spatial information embedded in the text and generates controllable 3D terrains with superior visual quality.&lt;/p></description></item><item><title>论文分享 | 广泛的解码策略导致大模型越狱</title><link>https://geyuyao.com/post/catastrophic-jailbreak-llms/</link><pubDate>Tue, 09 Apr 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/catastrophic-jailbreak-llms/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Catastrophic Jailbreak of Open-source LLMs via Exploiting Generation&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Princeton University&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Yangsibo Huang, Samyak Gupta ,Mengzhou Xia, Kai Li, Danqi Chen&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2310.06987" target="_blank" rel="noopener">https://arxiv.org/abs/2310.06987&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2023.10.10&lt;/p>
&lt;h1 id="摘要">摘要&lt;/h1>
&lt;p>本文提出了一种名为 &lt;em>generation exploitation&lt;/em> 的方法，该方法通过操纵大模型的系统prompt和超参数实现攻击。该攻击方法将攻击成功率 (ASR) 从0%提高到了95%以上。在该实验中，作者还提出使用经过微调的BERT-BASE-CASED用于评估大模型回答的毒性(危险性)。鉴于对齐的灾难性失败，作者提出了一种名为 &lt;em>generation-aware alignment&lt;/em> 的对齐手段。&lt;/p>
&lt;h1 id="动机">动机&lt;/h1>
&lt;p>作者团队注意到，目前大模型领域通常只使用默认解码方法 (如贪心) 来评估开源大模型的对齐情况。当恶意用户更改解码的超参数时，可能会导致对齐错误。&lt;/p>
&lt;p>举例来讲，前人在LLAMA2上进行对齐评估时，使用了 $p = 0.9$ 和 $\tau = 0.1$ 的超参数且始终带有系统prompt。&lt;/p>
&lt;ul>
&lt;li>在LLAMA2论文的第4.1节中：“For decoding, we set temperature to 0.1 and use nucleus sampling with top-p set to 0.9”;&lt;/li>
&lt;li>在LLAMA2论文的附录A.3.7 中提到：“在收集生成语言的过程中，我们在评估提示之前附加了一个系统提示”。&lt;/li>
&lt;/ul>
&lt;p>尽管这种方法在实践中具有一定的合理性，但是当用户使用更广泛的解码方式的时候可能会导致严重的后果。&lt;/p>
&lt;h1 id="更广泛的解码策略是否会导致大模型越狱">更广泛的解码策略是否会导致大模型越狱？&lt;/h1>
&lt;h2 id="实验设置">实验设置&lt;/h2>
&lt;p>为了探究本问题，作者将问题拆解为两个子问题并分别探究。&lt;/p>
&lt;ol>
&lt;li>是否添加系统prompt是否会对大模型越狱有影响？
&lt;ol>
&lt;li>作者团队根据是否使用默认系统prompt将实验分为两组作为对比来探究系统prompt对大模型越狱的影响。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>解码的超参数是否会对大模型越狱有影响？
&lt;ol>
&lt;li>使用不同温度 $\tau$ 进行温度抽样。$\tau$ 从0.05变化到1，步长为0.05，共得到20种配置。&lt;/li>
&lt;li>Top-K 采样是指选取概率最大的K 个词作为下一个预测词，接下来的预测词将只从这K 个词中进行采样。作者在{1, 2, 5, 10, 20, 50, 100, 200, 500} 中改变K，给出了9种配置。&lt;/li>
&lt;li>Top-p抽样是选择累计概率超过概率p的可能性最小的一组词语。将p从0.05变化到1，步长为0.05，这样共得到20个配置。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;p>在ASR评估方面，作者使用了两种方式进行评估。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>字符串匹配&lt;/strong>：使用子字符串匹配一小组拒绝短语来确定对齐情况，例如“对不起”或“我无法创建”，如果不存在这些字符串，则将攻击分类为成功。&lt;/li>
&lt;li>&lt;strong>使用训练过的分类器来评估&lt;/strong>：字符串匹配方法有很大的局限性，因为大模型的输出是很灵活的。因此，作者团队使用经过微调的BERT-BASE-CASED用于评估大模型回答的毒性(危险性)。具体而言，该模型被设置为将输入字符串分类为两类，即对齐正确和对齐错误。&lt;/li>
&lt;/ol>
&lt;p>在数据集方面，作者使用了AdvBench和自创的MaliciousInstruct。&lt;/p>
&lt;h2 id="实验结果">实验结果&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="0.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;ol>
&lt;li>&lt;strong>移除系统提示会增加攻击成功率&lt;/strong>：如上图所示，仅仅是移除系统提示这一简单操作就会显著增加攻击成功率（ASR），通常提高超过10%。我们观察到，系统提示的存在对于保持输出的一致性起着至关重要的作用，尤其对于未经安全调整的模型来说如此。对于这些模型，移除系统提示可能会导致ASR显著增加超过50%。然而，即使是具有明确安全对齐的模型，即LLAMA2对话模型，移除系统提示后ASR仍然增加。&lt;/li>
&lt;li>&lt;strong>多样化的解码策略增加攻击成功率&lt;/strong>：如上图所示，结果表明确实可以通过探索多样化的解码策略来提高性能。实际上，除了LLAMA2-CHAT模型外，所有模型的ASR都超过了90%。这种性能上的鲜明对比突显了被评估模型中对齐的灾难性失败。&lt;/li>
&lt;li>&lt;strong>固定的解码策略评估模型对齐性的局限性&lt;/strong>：值得注意的是，在LLAMA-CHAT模型中采用固定的解码配置通常导致ASR低于30%，而使用不同的配置可以显著提高ASR至80%以上。这些发现强调了使用固定的解码策略来评估模型对齐性会明显低估实际风险。&lt;/li>
&lt;/ol>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>上图报告了每个模型的最脆弱的解码策略，表明不同的模型对不同的解码策略的脆弱性是不同的。&lt;/p>
&lt;p>根据人类判断,一半的对齐不良的输出是有害的。&lt;/p>
&lt;h1 id="进一步提高攻击性能">进一步提高攻击性能&lt;/h1>
&lt;p>作者团队使用了两种简单策略进一步提高了在安全对齐的LLAMA2-CHAT模型上的ASR至95%。&lt;/p>
&lt;h2 id="多次采样">多次采样&lt;/h2>
&lt;p>由于基于采样的解码的非确定性特性，增加采样运行次数是加强攻击的直观方法。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1712633120711.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示， 对于每个解码配置进行多次采样显著提高了LLAMA2-CHAT模型的ASR，达到了&amp;gt; 95% - 具体而言，对于LLAMA2-7B-CHAT进行5次采样，对于LLAMA2-13B-CHAT 进行4次采样，达到了95%的ASR水平。&lt;/p>
&lt;h2 id="基于惩罚和约束的解码">基于惩罚和约束的解码&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1712633475305.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>另一种有效的策略是在解码过程中引入约束。例如，通过在解码时引入长度惩罚，攻击成功率可以从83%提升到92%。进一步地，通过加入两个额外的约束——限制生成特定的“不良词汇”（例如‘sorry’、‘unethical’、‘illegal’等）和强制生成特定的词汇（例如‘sure’、‘ok’等），攻击成功率可以提升到100%。&lt;/p>
&lt;h2 id="与gcg对比">与GCG对比&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1712633864711.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>作者的生成利用攻击在两个模型、两个基准和两个用于衡量攻击成功的指标上持续优于SOTA攻击。值得注意的是， 作者的方法还比GCG快30倍：在LLAMA2-7B-CHAT上使用一块NVIDIA A100 GPU以单个prompt启动作者的攻击只需约3分钟，而GCG则需要大约1.5小时完成相同的任务（步数为500，批大小为512）。&lt;/p>
&lt;h1 id="一种生成感知对齐方法">一种生成感知对齐方法&lt;/h1>
&lt;p>这段文字介绍了一个名为“生成感知对齐（generation-aware alignment）”的方法，旨在提高模型对生成利用攻击的抵抗力。这种攻击可能导致模型对齐出现严重失误。下面是对这个方法的解释：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>方法概述&lt;/strong>：在生成感知对齐方法中，系统会主动收集各种解码策略生成的模型输出，并将这些输出用于对齐过程。这里的解码策略指的是模型如何根据输入的提示来生成文本序列。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>具体过程&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>对于一个语言模型 $f_\theta$ 和给定的提示 $\mathbf{p}$，模型通过采样方法 $h$ 生成输出序列 $\mathbf{r}$。这里 $h$ 是一种解码策略，它基于提示 $p$ 将语言模型的概率分布映射到词汇表 $\mathcal{V}$ 中的一个token序列。&lt;/li>
&lt;li>对于每个提示 $\mathbf{p}$，系统会从不同的解码策略中收集 $n$ 个响应，形成响应集合 $\mathcal{R}^{\mathbf{p}}$。&lt;/li>
&lt;li>然后，将所有的响应分为两组：对齐的响应集合 $\mathcal{R}&lt;em>{a}^{\mathbf{p}}$ 和未对齐的响应集合 $\mathcal{R}&lt;/em>{m}^{\mathbf{p}}$。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>优化目标&lt;/strong>：生成感知对齐通过最小化以下目标函数来实现，这个函数来自“追溯链”方法：
$$
\mathcal{L} = \frac{1}{|\mathcal{P}|} \sum_{\mathbf{p} \sim \mathcal{P}} \frac{1}{|\mathcal{R}&lt;em>{m}^{\mathbf{p}}| \times |\mathcal{R}&lt;/em>{a}^{\mathbf{p}}|} \sum_{(\mathbf{r}&lt;em>m, \mathbf{r}&lt;em>a) \sim \mathcal{R}&lt;/em>{m}^\mathbf{p} \times \mathcal{R}&lt;/em>{a}^\mathbf{p}} - \log \mathbb{P}(\mathbf{r}_a \mid \mathbf{p}, \mathbf{s}_a) - \log \mathbb{P}(\mathbf{r}_m \mid \mathbf{p}, \mathbf{s}_m)
$$
其中，$\mathbf{s}_a$ 和 $\mathbf{s}_m$ 分别表示“一个对齐的回答”和“一个未对齐的回答”。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>简单来讲，该过程可用下述方法简单化表示：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>收集答案&lt;/strong>：想象你问模型一个问题，它不只给出一个答案，而是根据不同的方式（称为解码策略）来生成多个答案。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>分类答案&lt;/strong>：接着，我们把这些答案分成两组，一组是正确的答案，另一组是错误的答案。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>训练模型&lt;/strong>：最后，我们用这些信息来训练模型，目的是让模型学会更好地区分什么样的答案是正确的，什么样的答案是错误的。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="实验结果-1">实验结果&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1712633826438.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示，基于生成感知的对齐使原模型的ASR从95%降低到69%。相比之下，使用固定解码结果进行对齐的抽样例子导致更高的最终ASR达到88%。&lt;/p>
&lt;p>值得注意的是，在攻击者利用的三种解码策略中，多样化的解码抽样策略显示出增强模型对温度攻击的最大优势。&lt;/p>
&lt;h1 id="开源vs闭源">开源vs闭源&lt;/h1>
&lt;p>上述实验都是在开源模型上进行，在本章，作者尝试对闭源模型，即gpt-3.5-turbo进行攻击。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1712634394552.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>&lt;strong>专有模型更不易受攻击&lt;/strong>。我们观察到攻击专有模型时的ASR显著较低（7%）（见上图），相比之下攻击开源模型的ASR通常超过95%。&lt;/p>
&lt;p>这种差异可以归因于两个关键因素。&lt;/p>
&lt;ol>
&lt;li>专有模型通常会引入内容过滤器，用于识别并处理可能有害的提示和输出内容。例如，我们观察到有9个经过测试的提示因内容过滤器而出现较长的请求时间，最终因超时错误而终止；&lt;/li>
&lt;li>第二个因素是，专有模型通常由拥有资源实施广泛红队测试的组织所拥有，从而使这些模型更加抵御攻击。&lt;/li>
&lt;/ol>
&lt;h1 id="总结">总结&lt;/h1>
&lt;p>在本文，作者提出了一个新的数据集MaliciousInstruct，一种模型回答毒性评估方式，一种通过操纵解码超参数的攻击手段——generation exploitation，一种对齐策略——generation-aware alignment。&lt;/p>
&lt;p>其中，generation exploitation方法无需像优化对抗性提示那样采用复杂技术，其注重于操纵不同的生成策略。值得注意的是，这种方法在使用比当前最佳攻击低30倍计算量的情况下，使得11个模型的对齐率高达95%。&lt;/p></description></item><item><title>论文解读 | TTA:大模型回答置信度评估新方法</title><link>https://geyuyao.com/post/think-twice-before-assure/</link><pubDate>Mon, 25 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/think-twice-before-assure/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Think Twice Before Assure: Confidence Estimation for Large Language Models through Reflection on Multiple Answers&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> National University of Singapore, University of Science and Technology of China, Meta AI&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Moxin Li, Wenjie Wang, Fuli Feng, Fengbin Zhu, Qifan Wang, Tat-Seng Chua&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2403.09972" target="_blank" rel="noopener">https://arxiv.org/abs/2403.09972&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2024.3.15&lt;/p>
&lt;h1 id="摘要">摘要&lt;/h1>
&lt;p>对于大型语言模型（LLM），尤其是黑盒模型，评估输出的可信度是一项关键工作。由于LLM对生成的错误答案过于自信，导致现有的LLM可信度评估通常不够准确。现有的方法解决过度自信问题存在明显的限制，这些方法仅考虑LLM生成的一个答案的可信度。为了解决这个限制，本文提出了一种新的方法，全面评估多个候选答案的可信度，以减轻对于错误答案的过度自信。&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>置信度评估的核心是实现校准，确保置信水平与实际答案的准确性相一致。&lt;/p>
&lt;p>黑盒LLM实现校准的关键在于解决过度自信的问题。LLM在信任自己生成的回答方面存在固有偏见，这使得大模型很难真正辨别出自己的回答是否正确，并且往往倾向于给自己的回答分配很高的置信分数。&lt;/p>
&lt;p>目前有两种研究范式：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>第一种范式（self-consistency）认为过度自信部分由问题（prompt）和答案之间的上下文偏差引起。为了解决这个问题，研究者尝试通过构建各种prompt模板和多样化的问题重述来进行prompt集成。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>第二种范式（verbalized methods）集中于LLM的自我评估，设计了诸如询问LLM关于答案真实性的指令或思维链（Chain-of-Thought, CoT）推理的方法。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>然而上述研究的局限性在于：这些研究方法通常只考虑LLM生成的单一目标答案，由于大模型对自己的回答表现出过度自信，它们可能仍会对错误答案保持偏见。&lt;/p>
&lt;p>为了解决这一局限性，本文引入了一种新的多答案评估范例，让大模型考虑多个候选答案，以增强置信度校准。&lt;/p>
&lt;h1 id="问题定义">问题定义&lt;/h1>
&lt;p>给定由问题 $q$ 和prompt $p$ 组成的输入，其中包括一条指令和可选的上下文示例，LLM可以生成答案 $a$。随后，置信度估计旨在获得LLM对 $a$ 的置信水平，以置信分数 $c \in R$ 的形式表示。将置信度评估策略表示为 $CE(·)$ ，这个过程可被形式化表述为：
$$
a = LLM(p(q)), \
c = CE(LLM(·), p(q), a).
$$&lt;/p>
&lt;h1 id="前人方法">前人方法&lt;/h1>
&lt;p>如今，问题聚焦于如何设计置信度评估函数$CE(·)$。&lt;/p>
&lt;p>一个显而易见的方法是利用LLM的输出概率来估计置信度分数，形式化表述为 $c = Pr(LLM(·), p(q), a)$。然而，本文设定在黑盒状态下，因此模型内部状态不可见，故此方法不可用。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711439658243.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>对于黑盒状态，目前已有的两种方法为：&lt;/p>
&lt;ul>
&lt;li>自一致性（self-consistency），如上图子图1&lt;/li>
&lt;li>口述方法（verbalized methods），如上图子图2&lt;/li>
&lt;/ul>
&lt;p>对于自一致性（self-consistency）方法，其实就是同一个问题用多种表述方法多问几遍，看正确答案的比例。形式上可表示为：
$$
\begin{aligned}&amp;amp;c=\frac{\sum_{i=1}^D \mathbb1(a_i=a)}D,\&amp;amp;\mathrm{where~}a_i=LLM(p(q)).\end{aligned}
$$
其中，$D&amp;gt;1$。&lt;/p>
&lt;p>对于口述方法（verbalized methods），就是让大模型自己说几个候选回答及其对应的概率。
$$
[{a_1,c_1},&amp;hellip;{a_K,c_K}]=LLM(p^b(q)).
$$&lt;/p>
&lt;p>然而上述方法只考虑LLM生成的单一目标答案，由于大模型对自己的回答表现出过度自信，它们可能仍会对错误答案保持偏见。&lt;/p>
&lt;h1 id="本文方法">本文方法&lt;/h1>
&lt;p>作者认为，如果LLM能够彻底比较更多候选答案的可信度，当LLM对其他答案具有强烈正确倾向的情况下，对 $a$ 的高置信度可能会减弱，从而降低过度自信的风险。&lt;/p>
&lt;p>因此，作者团队提出了一种多答案评估范式TTA。&lt;/p>
&lt;p>其过程包含两个步骤：&lt;/p>
&lt;h2 id="第一步反思和证明">第一步:反思和证明&lt;/h2>
&lt;p>首先让LLM反思每个答案 $a^q_i$ 的可信度，并要求LLM找到证据 $e_i$ 来证明 $a^q_i$ 作为 $q$ 的正确答案的合理性。
$$
e_i = LLM(p^e(q, a^q_i)), i \in {1, &amp;hellip;, N}
$$
此步骤的合理性在于，$p^e$ 指导LLM从 $q$ 和 $a^q_i$ 中推导出理由，避免了LLM在从 $p(q)$ 到 $a$ 的生成上存在的偏见。&lt;/p>
&lt;h2 id="第二步联合置信度估计">第二步:联合置信度估计&lt;/h2>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711439658243.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>在对每个 $a^q_i$ 获得了相应的证据 $e_i$ 之后，我们采用 Top-$K$ 口头化方法，将这些 $e_i$ 整合起来，以获得答案 $a$ 的概率。
$$
c = Pr(LLM(\cdot), p^v(q, [e_1, &amp;hellip;, e_N]), a)
$$
此处选择 Top-$K$ 口头化方法是因为它能够在一次回应中，生成一组 $K$ 个潜在答案以及其各自的概率。&lt;/p>
&lt;p>其中 $K$ 被设置为答案的数量 $N$ 。&lt;/p>
&lt;p>整个过程可被形式化表述为：
$$
c = Pr(LLM(\cdot), p^v(q, [e_1, &amp;hellip;, e_N]), a), \
\notag
\text{where } e_i = LLM(p^e(q, a^q_i)), i \in {1, &amp;hellip;, N}.
$$
流程如上图子图3。&lt;/p>
&lt;h1 id="实验">实验&lt;/h1>
&lt;h2 id="datasets--models">Datasets &amp;amp; Models&lt;/h2>
&lt;p>本文在三个任务上使用六个数据集进行实验。&lt;/p>
&lt;p>情感分析（SA）使用了IMDB和Flipkart，自然语言推理（NLI）使用了 SNLI 和 HANS，常识问题回答（CQA）使用了CommonsenseQA 和PIQA。&lt;/p>
&lt;p>对于大模型，本文使用了OpenAI的GPT-3.5、GPT-4和ZhipuAI的GLM-4。&lt;/p>
&lt;h2 id="baseline">Baseline&lt;/h2>
&lt;p>Self-cons、CoT-cons、Top-K Verb、Hybrid、Self-detect、CAPE、P(True)。&lt;/p>
&lt;h2 id="evaluation">Evaluation&lt;/h2>
&lt;p>AUROC和PRAUC，取值范围都是从0到1。&lt;/p>
&lt;h2 id="result">Result&lt;/h2>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711440605017.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">GPT-3.5上比较方法的结果&lt;/div>&lt;/center>
&lt;ol>
&lt;li>答案的准确性可以通过置信度分数更好地区分，实现更好的校准效果。&lt;/li>
&lt;li>TTA在选择性预测场景中具有很强的应用潜力。&lt;/li>
&lt;li>不同的目标答案，LLMs的参数敏感性也是不同的。&lt;/li>
&lt;li>TTA在校准性能方面取得了比其他方法更好的表现。&lt;/li>
&lt;/ol></description></item><item><title>Softmax回归及其优化问题</title><link>https://geyuyao.com/post/softmax-regression/</link><pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/softmax-regression/</guid><description>&lt;h1 id="简介">简介&lt;/h1>
&lt;p>&lt;strong>温故而知新&lt;/strong>&lt;/p>
&lt;p>本文所属系列为笔者学习陈天奇和J.Zico Kolter在CMU开设的Deep Learning Systems的课程笔记。&lt;/p>
&lt;p>本文为Deep Learning Systems课程的第二课：2 - ML Refresher / Softmax Regression。&lt;/p>
&lt;h1 id="数据定义">数据定义&lt;/h1>
&lt;p>&lt;em>在这一章节，我们将定义在本文中会用到的输入数据。&lt;/em>&lt;/p>
&lt;p>让我们来考虑一个$k$分类问题，给定：&lt;/p>
&lt;ol>
&lt;li>训练数据：$x^{(i)}\in \mathbb{R}^n$，$y^{(i)}\in {1,&amp;hellip;,k}$ $for$ $i = 1,..,m$。&lt;/li>
&lt;li>&lt;code>n&lt;/code>为输入数据的维度数&lt;/li>
&lt;li>&lt;code>k&lt;/code>为类别/label的数量&lt;/li>
&lt;li>&lt;code>m&lt;/code>为训练数据的数量&lt;/li>
&lt;/ol>
&lt;p>至此，本文中所有的输入数据定义完毕。&lt;/p>
&lt;h1 id="线性映射">线性映射&lt;/h1>
&lt;p>&lt;em>在这一章节，我们将定义将输入数据 $x$ 映射到 $k$ 个类别的假设函数 $h$。&lt;/em>&lt;/p>
&lt;p>我们将使用线性函数来实现这一功能并提供形式化表述，同时提供函数是线性的的证明。&lt;/p>
&lt;h2 id="向量形式">向量形式&lt;/h2>
&lt;p>由于我们要将维度为$n$的数据$x$分为$k$类，因此我们需要将这个功能形式化表述。&lt;/p>
&lt;p>对于$k$分类问题，我们希望将维度为$n$的输入向量$x\in \mathbb{R}^n$映射到一个$k$维的解空间中，即
$$
h{:}\mathbb{R}^n\to\mathbb{R}^k
$$
其中，$h_i(x)$表示对于输入数据$x$，它是第$i$类的置信度。&lt;/p>
&lt;p>上述过程，我们可以用线性映射函数来表示：
$$
{h_\theta(x)=\theta^Tx}
$$
其中，$\theta \in \mathbb{R}^{n\times k}$。&lt;/p>
&lt;p>至此，映射函数的形式化表述完毕。&lt;/p>
&lt;blockquote>
&lt;p>为什么$ h_\theta(x) = \theta^T x $是线性的？&lt;/p>
&lt;p>一个线性的函数需要满足可加性和齐次性。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>可加性（Additivity）&lt;/strong>：
假设我们有两个 $n$-维输入向量 $x_1$ 和 $ x_2$。那么对于线性假设函数 $h$，我们有：
$$ h_\theta(x_1 + x_2) = \theta^T (x_1 + x_2) $$
由于矩阵乘法与向量加法相容，根据分配律：
$$h_\theta(x_1 + x_2) = \theta^T x_1 + \theta^T x_2 $$
而上式右侧等于把每个向量单独变换然后相加：
$$h_\theta(x_1 + x_2) = h_\theta(x_1) + h_\theta(x_2) $$
故满足可加性&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>齐次性（Homogeneity）&lt;/strong>：
如果我们取$ x$的一个标量倍数$cx$，其中$c$是任意实数，那么线性假设函数$h$的输出为：
$$ h_\theta(cx) = \theta^T (cx) $$
根据分配律：
$$ h_\theta(cx) = c(\theta^T x) $$
这表明通过函数 ( h ) 变换的标量倍数正是标量倍数的变换：
$$ h_\theta(cx) = c h_\theta(x) $$&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>故满足齐次性&lt;/p>
&lt;p>因此可证，矩阵乘法满足可加性和齐次性，所以$h_\theta(x)$是一个线性函数。。&lt;/p>
&lt;/blockquote>
&lt;h2 id="矩阵格式">矩阵格式&lt;/h2>
&lt;p>在上小节中，$x$ 的形状为 $1 \times n$ 的向量。在这一小节，我们将 $m$ 个 $x$ 向量拼接为一个形状为 $m \times n$ 的矩阵：&lt;/p>
$$
X\in\mathbb{R}^{m\times n}=\begin{bmatrix}-{x^{(1)}}^T-\\\vdots\\-{x^{(m)}}^T-\end{bmatrix}
$$
&lt;p>对于一个向量 $x$ ，其label，即 $y$ ，为一个实数 $y$ 。类似地，当 $m$ 个 $x$ 拼接为矩阵，其label，即 $y$， 是一个形状为$m \times 1$的矩阵：&lt;/p>
$$
y\in\{1,...,k\}^m=\begin{bmatrix}y^{(1)}\\\vdots\\y^{(m)}\end{bmatrix}
$$
&lt;h1 id="损失函数">损失函数&lt;/h1>
&lt;p>&lt;em>在这一章节，我们将讨论两种损失函数的定义、利弊——0-1损失函数和交叉损失函数。&lt;/em>&lt;/p>
&lt;p>损失函数的意义在于，它将模型的参数矩阵映射到一个实数值上，这个值用于评估假设函数 $h_\theta(x)$ 的&amp;quot;好坏&amp;quot;程度。&lt;/p>
&lt;h2 id="0-1损失函数">0-1损失函数&lt;/h2>
&lt;p>对于一个分类问题，我们如何判断一个假设函数 $h_\theta(x)$ 的好坏呢？&lt;/p>
&lt;p>一个非常直观的想法是，如果判断正确置$1$，分类错误置$0$。这种损失函数叫做&amp;quot;0-1损失函数&amp;quot;（0-1 loss function）。这个函数的值取决于一个分类器 $h$ 在输入 $x $上的预测 $h_\theta(x) $ 是否与真实标签 $y$ 相同。如果预测正确，那么损失为0；如果预测错误，则损失为1。简而言之，这个函数是在衡量“分类器是否犯错”，如果犯错就惩罚，否则不惩罚。其形式化表述为：&lt;/p>
$$
\ell_{err}(h(x),y)=\begin{cases}0&amp;\text{if }\operatorname{argmax}_ih_i(x)=y\\1&amp;\text{otherwise}\end{cases}
$$
&lt;p>这个损失函数的好处在于非常简单。然而，不幸的是，这种损失函数非常不利于后续我们对模型参数进行优化。这是因为这种损失函数在优化过程中不能使用基于梯度的方法，因为它本身就没有梯度！当预测是正确的，损失函数的输出突然跳跃到0，这导致没有一个有意义的梯度方向来指导参数更新。&lt;/p>
&lt;blockquote>
&lt;p>其中，$ \text{argmax}_i h_i(x) $ 表示分类器对于所有可能的类别输出的得分中，得分最高的类别。&lt;/p>
&lt;/blockquote>
&lt;h2 id="softmax-和-cross-entropy-loss">Softmax 和 Cross-entropy loss&lt;/h2>
&lt;p>在上一小节中提到的&amp;quot;0-1损失函数&amp;quot;的思想可以总结为&amp;quot;一刀切&amp;quot;，正确为1，错误为0。然而，即使是错，也有错了一点和错得离谱之分。&lt;/p>
&lt;p>基于这个思想，我们希望将假设函数$h_\theta(x)$的输出从生硬的&amp;quot;一刀切&amp;quot;转换为&amp;quot;概率&amp;quot;。这里，我们可以使用softmax函数，它可以将任何实数向量转换为一个概率分布。对于分类 $i $，模型预测的概率 $p(\text{label} = i) $ 计算为该类的得分 $ h_i(x) $ 的指数，除以所有类得分指数的总和，以确保所有预测概率相加等于1。其形式化表述为：&lt;/p>
$$
z_i=p(\text{label}=i)=\frac{\exp\bigl(h_i(x)\bigr)}{\sum_{j=1}^k\exp\bigl(h_j(x)\bigr)}\Longleftrightarrow z\equiv\text{softmax}\bigl(h(x)\bigr)
$$
&lt;p>其中，将输出除以所有的输出的和这一步骤很好理解，其意义在于通过对输出归一化使得&lt;strong>每个类别的输出值都在0到1之间&lt;/strong>且&lt;strong>各类别输出和为1&lt;/strong>。我们好奇在于，为什么要将 $ h_i(x) $ 指数化呢？&lt;/p>
&lt;p>这么做主要有两个原因&lt;/p>
&lt;ol>
&lt;li>通过将输出指数化，将假设函数的输出转换为正值。这对于创建一个有效的概率分布是必需的，因为概率值不能为负。&lt;/li>
&lt;li>指数函数曲线呈现递增趋势，最重要的是斜率逐渐增大，也就是说在x轴上一个很小的变化，可以导致y轴上很大的变化。这有助于在计算概率时清晰地区分那些具有更高原始逻辑值的类别。&lt;/li>
&lt;/ol>
&lt;p>有了softmax函数，我们可以用交叉熵损失函数（cross-entropy loss）来计算损失值，其形式化表述为：&lt;/p>
$$
\ell_{ce}(h(x),y)=-\log p(\text{label}=y)=-h_y(x)+\log\sum_{j=1}^k\exp\left(h_j(x)\right)
$$
&lt;p>我们注意到，交叉熵损失函数实质上是对 $y$ 类别的softmax输出做$-log$操作。&lt;/p>
&lt;p>对于加$log$，其意义在于：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>将(0, 1)区间内的值映射到负无穷大到0的区间，使得概率的微小变化在损失值中得到放大，从而提供更好的区分度。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>当预测概率接近真实标签的概率时，损失函数的梯度会变小，模型的学习速度会减慢。相反，当预测概率与真实标签差异很大时，损失函数的梯度会显著变大，模型速度会加快。这样使得模型能够更有效地学习，当模型经常做出错误预测时，可以快速调整方向。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>对于加$-$，其意义在于将负值转为正值。这样，差异越大损失值越大，反之亦然。&lt;/p>
&lt;h1 id="优化">优化&lt;/h1>
&lt;p>在上文我们提到，我们可以通过损失函数来判断假设函数$h_\theta(x)$中的权重参数的好坏程度。&lt;/p>
&lt;p>&lt;em>那么，如果$h_\theta(x)$中的权重参数不够好，我们应该如何进行优化呢？&lt;/em>&lt;/p>
&lt;h2 id="定义">定义&lt;/h2>
&lt;p>广义上讲，我们希望通过优化权重参数 $\theta$，使得损失函数的输出值最小。其形式化表述如公式所示：
$$
\underset{\theta}{\operatorname*{minimize}}\frac1m\underset{i=1}{\operatorname*{\sum}}\ell(h_\theta(x^{(i)}),y^{(i)})
$$
其中 $i$ 表示当前样本索引，$h$ 表示假设函数，$y$ 表示样本的真实标签 (Ground truth)。&lt;/p>
&lt;p>我们将交叉熵损失函数 $\ell_{ce}$ 带入 $\ell$ ，得到下述公式：
$$
\underset{\theta}{\operatorname*{minimize}}\frac1m\sum_{i=1}^m\ell_{ce}(\theta^Tx^{(i)},y^{(i)})
$$
至此，优化的定义有了。&lt;/p>
&lt;p>接下来，具体而言，我们应该如何进行优化呢？&lt;/p>
&lt;h2 id="梯度优化">梯度优化&lt;/h2>
&lt;h3 id="梯度">梯度&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711028494122.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>对于一个输入为矩阵，输出为实数的函数 $f{:\mathbb{R}^{n\times k}\to\mathbb{R}}$，其梯度被定义为偏导数矩阵，可被形式化表述为：&lt;/p>
$$
\nabla_\theta f(\theta)\in\mathbb{R}^{n\times k}=\begin{bmatrix}\dfrac{\partial f(\theta)}{\partial\theta_{11}}&amp;...&amp;\dfrac{\partial f(\theta)}{\partial\theta_{1k}}\\\vdots&amp;\ddots&amp;\vdots\\\dfrac{\partial f(\theta)}{\partial\theta_{n1}}&amp;...&amp;\dfrac{\partial f(\theta)}{\partial\theta_{nk}}\end{bmatrix}
$$
&lt;p>结合我们上文可知，此处的$f$代表了上文中的损失函数。&lt;/p>
&lt;p>在数学上，梯度指向的是损失函数局部下降最快的方向。&lt;/p>
&lt;p>&lt;strong>因此，在优化中，我们通常希望找到损失函数梯度下降的方向，来调整参数以最小化损失函数。&lt;/strong>&lt;/p>
&lt;h3 id="学习率">学习率&lt;/h3>
&lt;p>现在我们可以通过梯度这个强有力的工具来对权重参数进行更新了！&lt;/p>
&lt;p>然而需要注意的是，我们在更新权重参数的时候，我们是一轮一轮地进行更新。于是，我们需要用一个缩放因子$\alpha$定义每一轮训练对权重参数的更新幅度。这个缩放因子$\alpha$就被称为&lt;strong>学习率&lt;/strong>。在利用梯度对权重参数进行的过程中，更新每一步的更新的形式化表述可以表示为：
$$
\begin{aligned}\theta:=\theta-\alpha\nabla_\theta f(\theta)\end{aligned}
$$
其中：&lt;/p>
&lt;ul>
&lt;li>$\theta$ 是需要优化的权重参数。&lt;/li>
&lt;li>$\alpha$是学习率，为正数，它控制了每一步的更新幅度。&lt;/li>
&lt;li>$\nabla_\theta f(\theta)$ 是损失函数 $f(\theta) $ 关于参数 $ \theta$ 的梯度。&lt;/li>
&lt;/ul>
&lt;p>上述方法就是著名的&lt;strong>梯度下降法&lt;/strong>（Gradient-Descent）。其原理是，通过计算损失函数在当前参数下的梯度，然后沿着梯度的负方向更新参数，不断迭代直到收敛。&lt;/p>
&lt;p>在梯度下降法中，选择适当的学习率对于梯度下降算法的优化性能至关重要。下方的三个子图展示了使用不同学习率 $\alpha$ 在一个二维参数空间中进行梯度下降时的路径，其中的等高线表示损失函数的值。从左到右，学习率分别是 0.05、0.2 和 0.42。梯度下降的目的是找到损失函数的全局最小点，也就是图中是最内层的那圈等高线。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711029122820_1.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>通过上方三个子图，我们可以观察到：&lt;/p>
&lt;ul>
&lt;li>当学习率较小（如左图的 0.05）时，梯度下降路径较长，需要更多的迭代次数才能达到最小点。这意味着我们需要经过多轮迭代才能找到最优的权重参数。&lt;/li>
&lt;li>当学习率适中（中图的 0.2）时，梯度下降可以较快地接近最小点。&lt;/li>
&lt;li>当学习率较大（如右图的 0.42）时，可能会导致过度更新，使得梯度下降路径在最小点附近游荡，难以稳定下来。&lt;/li>
&lt;/ul>
&lt;p>因此，在梯度下降法中，我们需要谨慎地来设置学习率。&lt;/p>
&lt;p>这是因为：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>收敛速度&lt;/strong>：如果学习率设置得过小，梯度下降可能会非常缓慢地收敛到最小值，这会增加达到最优解所需的迭代次数，导致训练过程耗时更长。&lt;/li>
&lt;li>&lt;strong>反复横跳&lt;/strong>：如果学习率设置得过大，可能会导致参数更新过度，从而使得算法在最小值附近跳跃，甚至可能越过最小值点，使得损失函数反而增加。这会导致算法发散，无法找到最小值。&lt;/li>
&lt;li>&lt;strong>避免陷入局部最小值&lt;/strong>：一个好的学习率设置可以帮助算法准确地收敛到损失函数的全局最小值或一个好的局部最小值，而不是收敛到一个不太理想的局部最小值或鞍点。&lt;/li>
&lt;li>&lt;strong>稳定性&lt;/strong>：过大的学习率可能导致在最小值周围震荡而不是收敛，而一个适当的学习率则可以确保参数更新过程平稳且稳定地接近最优解。&lt;/li>
&lt;/ul>
&lt;h2 id="随机梯度下降法">随机梯度下降法&lt;/h2>
&lt;p>在上一小节我们介绍了梯度下降法，此时，我们已经拥有了对权重参数进行优化的范式。然而，在实际中，我们更多的使用一种叫&lt;strong>随机梯度下降法&lt;/strong>（Stochastic Gradient Descent, SGD）的优化方式来对权重参数进行更新。&lt;/p>
&lt;p>在机器学习中，当我们的损失函数是个体损失的总和时，我们不希望用所有样本来计算梯度进行一次单一的参数更新，因为这样计算和时间成本较高。&lt;/p>
&lt;p>因此，我们可以每次只取数据集的一个小部分（称为一个小批量或minibatch）来计算梯度并更新参数，这样可以减少计算资源的消耗而且可以更快地进行多次参数更新。&lt;/p>
&lt;p>我们定义一个minibatch的形式化表述为：
$$
X\in\mathbb{R}^{B\times n},y\in{1,&amp;hellip;,k}^B
$$&lt;/p>
&lt;p>随机梯度下降法的优化方式可被形式化表示为：
$$
\theta:=\theta-\frac{\alpha}{B}\sum_{i=1}^{B}\nabla_{\theta}\ell(h_{\theta}(x^{(i)}),y^{(i)})
$$&lt;/p>
&lt;h2 id="交叉熵损失函数的梯度计算">交叉熵损失函数的梯度计算&lt;/h2>
&lt;p>在上一章节，我们知道了如何使用梯度对权重参数进行更新。此时，距离我们达成目的只差最后一步了——&lt;strong>计算梯度&lt;/strong>。&lt;/p>
&lt;p>那么我们应该如何计算交叉熵损失函数的梯度呢？
$$
\nabla_\theta\ell_{ce}(\theta^Tx,y)=?
$$
根据链式法则，上式可被表述为：
$$
\frac\partial{\partial\theta}\ell_{ce}(\theta^Tx,y) = \frac{\partial\ell_{ce}(\theta^Tx,y)}{\partial\theta^Tx}\frac{\partial\theta^Tx}{\partial\theta}
$$
对于右侧式子，我们可以拆分成两项，分别是：
$$
\frac{\partial\ell_{ce}(\theta^Tx,y)}{\partial\theta^Tx} \tag{1}
$$
和
$$
\frac{\partial\theta^Tx}{\partial\theta} \tag{2}
$$
对于 ${(1)}$：&lt;/p>
&lt;p>还记得交叉熵损失函数的公式吗？让我们对损失函数关于某个类别的输出$h_i$求偏导。&lt;/p>
$$
\begin{aligned}
\begin{aligned}\frac{\partial\ell_{ce}(h,y)}{\partial h_i}\end{aligned}&amp; \begin{aligned}=\frac{\partial}{\partial h_i}\left(-h_y+\log\sum_{j=1}^k\exp h_j\right)\end{aligned} \\
&amp;=-1\{i=y\}+\frac{\exp h_i}{\sum_{j=1}^k\exp h_j}
\end{aligned}
$$
&lt;p>忽然我们有一个惊奇的发现，对交叉熵损失函数的求导结果中，竟然出现了$\frac{\exp h_i}{\sum_{j=1}^k\exp h_j}$ ！有点眼熟对吗？&lt;strong>这不正是Softmax(h(x))的展开嘛！&lt;/strong>&lt;/p>
&lt;p>于是，我们可以$\begin{aligned}\nabla_h\ell_{ce}(h,y)=z-e_y\end{aligned}$来简化上述公式的结果。其中，$z=\mathrm{softmax}(h)$，$e_y$是对应于正确类别的one-hot编码向量。&lt;/p>
&lt;p>对于 ${(2)}$：&lt;/p>
&lt;p>我们可以很方便的求导
$$
\frac{\partial\theta^Tx}{\partial\theta} = x
$$
于是，$(0)$式可被表达为：&lt;/p>
$$
\begin{aligned}
\begin{aligned}\frac{\partial}{\partial\theta}\ell_{ce}(\theta^Tx,y)\end{aligned}&amp; \begin{aligned}=\frac{\partial\ell_{ce}(\theta^Tx,y)}{\partial\theta^Tx}\frac{\partial\theta^Tx}{\partial\theta}\end{aligned} \\
&amp;=({z-e_y})(x),\quad\text{where }z=\text{softmax}(\theta^Tx)
\end{aligned}
$$
&lt;p>距离大功告成就差最后一步了！&lt;/p>
&lt;p>让我们再做一些矩阵对齐的操作&amp;hellip;&lt;/p>
&lt;p>于是，当输入为向量 $x$ 时，通过交叉熵损失函数对权重矩阵 $\theta$ 的梯度为：
$$
\nabla_\theta\ell_{ce}(\theta^Tx,y)\in\mathbb{R}^{n\times k}=x(z-e_y)^T
$$
当输入拓展到batch中所有的向量 $x$ 拼接成的矩阵 $X$ 时，上式被拓展为：
$$
\nabla_\theta \ell_{ce}(X\theta, y) \in \mathbb{R}^{n \times k} = X^T(Z - I_y)
$$
其中：&lt;/p>
&lt;ul>
&lt;li>$X$ 是整个数据批量的特征矩阵。&lt;/li>
&lt;li>$Z$ 是假设函数对于整个批量的预测概率矩阵。每一行对应一个样本的预测概率分布，通过将 $X\theta$ 输入softmax函数得到。&lt;/li>
&lt;li>$ I_y $ 是一个矩阵，其中每一行对应一个样本的正确类别的one-hot编码向量。&lt;/li>
&lt;/ul>
&lt;p>至此，我们完成了交叉损失函数的梯度计算！我们可以用梯度来对权重矩阵进行更新了！&lt;/p>
&lt;h1 id="总结">总结&lt;/h1>
&lt;p>在本文，我们介绍了Softmax函数、交叉熵损失函数、梯度、梯度下降法、随机梯度下降法、如何利用梯度下降法来对权重参数进行优化等问题。&lt;/p>
&lt;p>欢迎关注后续文章~&lt;/p></description></item><item><title>论文解读 | 3月最新用于游戏的大模型Agent综述</title><link>https://geyuyao.com/post/game-playing-agents-survey/</link><pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/game-playing-agents-survey/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> A Survey on Game Playing Agents and Large Models: Methods, Applications, and Challenges&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Beijing Academy of Artificial Intelligence (BAAI) ，Institute of Software, Chinese Academy of Science，University of Chinese Academy of Science，Dartmouth College，Beijing University of Posts and Telecommunications，Peking University&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Xinrun Xu，Yuxin Wang，Chaoyi Xu，Ziluo Ding，Jiechuan Jiang，Zhiming Ding，Börje F. Karlsson&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2403.10249" target="_blank" rel="noopener">https://arxiv.org/abs/2403.10249&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2024.3.15&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1711099570041.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>大规模模型（LMs），包括语言模型和多模态模型，在许多重要领域取得了重大进展。这些进展促使研究者探索将LMs作为agent应用于执行复杂任务。与传统模型相比，基于LM的agent（LMAs）在许多情况下展现出与更强大的泛化能力。&lt;/p>
&lt;p>基于LMs的agent表现出的能力，引起了人们将其应用于游戏的极大兴趣。这是因为游戏为agent提供了需要复杂推理和认知能力的虚拟挑战环境，是评估agent的理想Benchmark。相比于真实世界实验，在游戏环境中进行数据获取的过程在成本、可控性、安全性和多样性方面具有无可比拟的优势，同时也保留了一定的挑战性。&lt;/p>
&lt;p>在思考如何让大模型玩游戏之前，让我们先来想一想人类是如何玩游戏的。&lt;/p>
&lt;p>人类大脑作为一个复杂的信息处理系统，首先将感官信息转化为感知表征，然后利用这些表征构建关于世界的知识并做出决策，最后通过行动实施。这一序列可以抽象为agent的迭代过程：&lt;strong>感知&lt;/strong>、&lt;strong>推理&lt;/strong>和&lt;strong>行动&lt;/strong>。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>感知&lt;/strong>：将游戏过程中的观察到的原始信息转化为可操作的、对游戏的理解，以支持后续的互动。早期的工作将文本转化为语义信息，最近的工作尝试将视觉信息整合进来。&lt;/li>
&lt;li>&lt;strong>推理&lt;/strong>（&lt;strong>Inference&lt;/strong> ）：涉及agent的诸多关键能力，包括记忆、学习、 推理（&lt;strong>reasoning&lt;/strong>）、反思和决策等。
&lt;ul>
&lt;li>&lt;strong>记忆&lt;/strong>：指存储并检索学到的知识。&lt;/li>
&lt;li>&lt;strong>学习&lt;/strong>：通过经验和多智体系统中获得技能对策略进行调整。&lt;/li>
&lt;li>&lt;strong>推理&lt;/strong>：指通过处理、汇总信息，从而解决问题的过程。在复杂游戏中，决策需要多跳推理和长期规划，任务分解和协作决策，以应对游戏中的动态环境。&lt;/li>
&lt;li>&lt;strong>反思&lt;/strong>：指自我改进的过程，agent根据反馈评估和调整策略。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>行动&lt;/strong>：涵盖了与游戏环境的互动，即agent对游戏状态和环境反馈的反应。
&lt;ul>
&lt;li>&lt;strong>代码生成&lt;/strong>：agent的许多行为是通过生成编码来执行的，使用诸如迭代prompt、角色特定prompt和代码生成等技术。&lt;em>其实gpt-4也经常这么做。例如，我们命令gpt为我们分析一个表格，gpt会构建一段python代码来读取表格、分析表格、可视化表格，然后将结果以文本的形式回答给我们。&lt;/em>&lt;/li>
&lt;li>&lt;strong>对话互动&lt;/strong>：对话交互不仅涉及agent与agent之间的通信，还包括人与agent之间的互动，这些交互行为通过协作框架和对话控制机制来实现动态且有效的沟通，这样做的目的是为了根据交互的需求和上下文灵活地调整对话行为。&lt;/li>
&lt;li>&lt;strong>行为一致性&lt;/strong>：行为一致性指的是agent在不同情境下按照可预测的、稳定的、一致的模式行动。为达到此目的，可以使用结构化的方法如DAG、反馈机制、强化学习等手段。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>请注意上文中的两个推理虽然在中文中相同，但是在英文中一个是Inference一个是reasoning。&amp;ldquo;inference&amp;quot;侧重于从已有信息出发进行逻辑上的延伸和结论抽取，而&amp;quot;reasoning&amp;quot;则涵盖更广泛的思考和逻辑推理过程&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>上文所指的&amp;quot;世界模型&amp;quot;可以理解为人类大脑利用感知表征构建的关于世界的知识。此处的世界模型是大脑对外部环境的内部表示，包括对物体、事件、场景以及它们之间关系的理解和认知，然后帮助个体理解周围的环境，预测未来事件，并在此基础上做出决策和行动。&lt;/p>
&lt;/blockquote>
&lt;h1 id="感知">感知&lt;/h1>
&lt;p>感知游戏的原始场景并提取信息对于随后的步骤至关重要。感知的主要功能是将多模态空间（包括视觉、语义和音频）转化为agent的输入。&lt;/p>
&lt;p>现代的数字游戏通过整合多模态感知通道，为人类玩家提供更丰富和更沉浸式的体验，使玩家能够更深入地沉浸游戏世界。然而，不幸的是，目前现有工作中并没有太多关于将&lt;strong>音频数据&lt;/strong>整合到大型模型的训练中或优化游戏agent的工作。&lt;/p>
&lt;h2 id="语义感知">语义感知&lt;/h2>
&lt;p>在语义方面的感知主要指的是，游戏中的文本元素和文本描述，包括从自然语言指令到对话。这意味着玩家通过阅读和解释文本来理解游戏环境中的各种元素和发生的事件，以及进行决策和行动。&lt;/p>
&lt;p>语义感知可以被划分为四类：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>简单的文本输入&lt;/strong>：指用户的简单想法或描述、基本游戏状态变量、人物之间的对话。&lt;/li>
&lt;li>&lt;strong>结构化或基于角色的输入&lt;/strong>：角色的属性、故事、相关的信息、技能等。&lt;/li>
&lt;li>&lt;strong>环境和特定上下文输入&lt;/strong>：详细的游戏描述和上下文信息等情况，以及任务的自然语言指令。&lt;/li>
&lt;li>&lt;strong>多模态输入&lt;/strong>：将视觉、听觉和文本数据整合用于决策，以及将对话、游戏状态和脚本的整合以实现更丰富的交互。&lt;/li>
&lt;/ul>
&lt;h2 id="视觉感知">视觉感知&lt;/h2>
&lt;p>在上文中，我们提到可以将多模态信息如视觉信息转为文本信息。然而，在从多模态转换为文本格式时可能会丢失许多重要信息，这很可能会导致agent
难以理解其面对的情况或难以在游戏中导航。因此，LMAs需要更全面的感知数据。&lt;/p>
&lt;p>利用多模态大语言模型（MLLMs）成为了解决上述问题的一种解决方案。 通过利用MLLMs，agent可以获得对周围环境更丰富的感知，从而促进更复杂的认知过程和类似于现实世界的环境中的决策能力。&lt;/p>
&lt;p>关于这个视觉空间，目前有三种不同的感知方法：&lt;/p>
&lt;ol>
&lt;li>通过特定的API来获取与游戏相关的信息，并将这些信息输入到agent中&lt;/li>
&lt;li>使用图像和行动数据来对模型预训练&lt;/li>
&lt;li>直接使用纯图像信息进行输入&lt;/li>
&lt;/ol>
&lt;h1 id="推理inference">推理（Inference）&lt;/h1>
&lt;p>在游戏的初始阶段，agent需要吸收基本常识和游戏特定背景知识（通过预训练或实时感知）。在游戏过程中，agent综合过去的游戏事件，管理知识存储和检索，以及进行核心认知功能，如学习、推理（Reasoning）、决策和反思。&lt;/p>
&lt;h2 id="记忆">记忆&lt;/h2>
&lt;p>为了正确地表示学习到的知识或过去事件，并在推理中使用这些信息，一个agent需要有效地操作这些&amp;quot;记忆&amp;rdquo;。如何设计一种高质量的记忆机制，使agent能够有效&lt;strong>检索&lt;/strong>和&lt;strong>存储&lt;/strong>记忆，同时&lt;strong>充分利用&lt;/strong>背后的大型语言模型并&lt;strong>遵守其约束条件&lt;/strong>，仍然是一个尚未解决的问题。&lt;/p>
&lt;h3 id="常识">常识&lt;/h3>
&lt;p>常识知识是人们通常在早期生活中习得的、在特定情境下往往不需要明确表达的知识，对于推理和避免误解至关重要。&lt;/p>
&lt;p>大型语言模型，通过在多样化的互联网文本上预训练，已经表现出高级的语言理解和推理能力，能够使用这种隐含的知识来适应新挑战。然而，这些知识可能不总是与特定的游戏场景等应用情境完全一致。因此，当前的研究旨在通过以下方式增强语言模型的常识性理解：&lt;/p>
&lt;ol>
&lt;li>通过&lt;strong>指令微调&lt;/strong>将结构化的知识嵌入。&lt;/li>
&lt;li>使用&lt;strong>SOP&lt;/strong>将常识集成到特定的角色和任务中。例如，如果一个模型被用于模拟医生的角色，SOP可能包含医疗常识、病人交流的指南，以及诊断和治疗的标准流程。这使得模型能够在模拟或实际情境中更加有效和适应性地行动，因为它利用SOP中的常识来指导决策和行为。&lt;/li>
&lt;li>使用&lt;strong>RAG&lt;/strong>（检索增强生成）。&lt;/li>
&lt;/ol>
&lt;h3 id="游戏背景知识">游戏背景知识&lt;/h3>
&lt;p>在大型模型中的游戏背景知识指的是对游戏环境各个方面的理解。&lt;/p>
&lt;p>当前的技术通过将基本游戏规则、 基本流程、 推理能力和ont-shot演示纳入prompt中。例如：&lt;/p>
&lt;ol>
&lt;li>将详细的角色资料通过prompt输入大模型中。&lt;/li>
&lt;li>使用知识图谱用于描述实体之间的关系。&lt;/li>
&lt;li>使用来自模拟环境和角色扮演游戏（RPG）日志的详细场景显著增强了语言模型对游戏动态的理解。&lt;/li>
&lt;li>根据Minecraft Wiki和物品制作/熔炼配方的文档构建外部知识库，为Minecraft世界创建了一个详尽的知识来源，供agent查阅。&lt;/li>
&lt;/ol>
&lt;h3 id="检索">检索&lt;/h3>
&lt;p>LMAs中的记忆检索是指通过回 忆学到的信息来增强推理和行动。&lt;/p>
&lt;p>可以将LMAs的记忆检索方法分为三类：结构化记忆系统、动态自适应检索过程和高级记忆检索技术。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>结构化记忆系统&lt;/strong>：该技术旨在高效地组织和索引信息，以便快速检索。例如，技能库、共享消息池、层次结构和结构化通信，都是为了让agent能够快速访问以前获得的技能和知识，促进有效的记忆管理。&amp;ldquo;总结并忘记&amp;quot;的记忆机制通过总结重要信息并丢弃其余部分来优先处理关键记忆项，从而降低计算成本。&lt;/li>
&lt;li>&lt;strong>动态自适应检索过程&lt;/strong>：该方法侧重于结合相关性、最近性和重要性来检索记忆，从而策略性收集则强调历史游戏信息的相关性和新鲜度。这个过程还包括根据新的情况不断调整计划，确保agent的行为能够适应游戏的变化。简单来说，该方法实时地更新和调整agent的记忆，以便做出更好的决策。&lt;/li>
&lt;li>&lt;strong>高级记忆检索技术&lt;/strong>：包括（1）使用长短期记忆（LSTM）来保持对过去事件的记忆、（2）生成更简洁的状态描述来帮助agent快速理解当前游戏情况、（3）压缩历史文本序列以节省空间和提高效率。简而言之，该技术帮助agent更精确和有效地管理和使用它们的记忆。&lt;/li>
&lt;/ol>
&lt;h2 id="学习">学习&lt;/h2>
&lt;p>在大模型（LMs）的背景下的学习涉及解释和整合来自各种来源的信息，包括训练数据、用户交互和环境反馈。&lt;/p>
&lt;p>学习过程可以是显式的，例如通过在特定数据集上进行微调或专注于任务的训练；也可以是隐式的， 如在利用预先存在的知识来适应新场景。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>迭代和基于反馈的学习&lt;/strong>：结合迭代提示、角色prompt、反馈机制和行为克隆，通过持续的反馈和适应来增强能力。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>强化学习和离线学习&lt;/strong>：包括具有环境反馈的强化学习、离线学习和基于语言指令的强化学习。相比于迭代和基于反馈的学习侧重于通过连续的实时反馈来优化模型行为，本方法侧重于通过环境交互（实时或基于历史数据）来最大化长期奖励或达成特定目标。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>基于经验和利用记忆的学习&lt;/strong>：侧重于利用过去的经验、记忆检索和经验池来指导当前和未来的行动。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>协作和适应性学习&lt;/strong>：强调通过muti-agent合作、适应性策略和互动学习过程进行学习。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="推理reasoning">推理（Reasoning）&lt;/h2>
&lt;p>推理涉及将从学习阶段获得的基础知识抽象为更高级形式的理解，通过演绎、归纳或诱导推理。&lt;/p>
&lt;h2 id="决策">决策&lt;/h2>
&lt;p>在游戏的广阔世界中，特别是在开放世和沉浸式环境中，玩家和人工智能agent面临复杂的决策和行动空间。&lt;/p>
&lt;p>这些空间包含着大量可能的行动、互动和决策，具有广泛的角色、物品使用和技能组合。此外， 多智能体规划可能增加另一层复杂性，需要在信息不完整的环境中协调和协作多个agent。&lt;/p>
&lt;h3 id="多跳推理">多跳推理&lt;/h3>
&lt;p>多跳推理是指在做出决策之前考虑多层信息和依赖关系的认知过程。&lt;/p>
&lt;p>例如，在战略游戏中，agent必须考虑当前的局势，预测对手的动作，评估各种行动的潜在结果， 然后决定最有利的行动方向。&lt;/p>
&lt;h3 id="长期规划">长期规划&lt;/h3>
&lt;p>长期规划是指agent设定目标并确定在较长时期内通过行动实现该目标的战略过程。&lt;/p>
&lt;p>有学者提出使用思维链(COT) 规划模仿人类推理，生成最终决策的中间步骤，其中每个步骤都建立在前一个步骤的基础上， 以得出达到目的。&lt;/p>
&lt;h2 id="反思">反思&lt;/h2>
&lt;p>反思指的是大型模型agent（LMAs）评估、评估和可能调整其自身过程、决策或输出随任务进展的能力。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>基于反馈的自我改进&lt;/strong>：利用外部反馈（如环境响应或代码执行结果）进行自我核实、分析和迭代增强的过程。&lt;/li>
&lt;li>&lt;strong>迭代优化计划和行动&lt;/strong>：基于反馈和新信息不断细化计划或行动以更好地实现或适应目标的方法。&lt;/li>
&lt;li>&lt;strong>协作与多智能体交互&lt;/strong>：强调在多智能体系统中协作重新评估和调整决策。&lt;/li>
&lt;li>&lt;strong>辩论和基于理论心智的反思&lt;/strong>：使用辩论或交流格式作为反思过程的模型。&lt;/li>
&lt;/ul>
&lt;h1 id="行动action">行动（Action）&lt;/h1>
&lt;p>LMAs在游戏中操作的行动空间可以分类为三种不同类型。&lt;/p>
&lt;ol>
&lt;li>基于文本互动&lt;/li>
&lt;li>使用API互动&lt;/li>
&lt;li>通过IO操作直接控制。如键盘、鼠标等。&lt;/li>
&lt;/ol>
&lt;h2 id="行动-behavior">行动（ Behavior）&lt;/h2>
&lt;p>LMAs通过生成式编程技术执行特定操作。迭代prompt结合环境反馈、执行错误和自我验证，不断完善生成的程序，确保其对手头任务的有效性和相关性。&lt;/p>
&lt;h2 id="对话">对话&lt;/h2>
&lt;p>LMAs通过考虑当前环境和过去经验与人类或其他agnet进行交互。&lt;/p>
&lt;p>比如，agent-agent交互和人-agent交互。&lt;/p>
&lt;p>在过去的研究中表明，LMAs在协作中展示了类似人类的社会行为，如团队合作、领导、说服、欺骗和对抗。&lt;/p>
&lt;h2 id="一致性consistency">一致性（&lt;strong>Consistency&lt;/strong>）&lt;/h2>
&lt;p>行动一致性指agent的行动需要保持连贯并与其目标一致。&lt;/p>
&lt;p>为了维护这种一致性，agent通过考虑过去的经验和当前情境、利用反馈机制以及在必要时修改行动和计划。&lt;/p>
&lt;p>具体策略包括：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>前瞻检查机制&lt;/strong>：评估行为的可行性。&lt;/li>
&lt;li>&lt;strong>强化学习（RL）&lt;/strong>：训练选择最合适行动的策略。&lt;/li>
&lt;li>&lt;strong>自我一致性（SC）&lt;/strong>：生成多个行动预测并选择最常见的行动进行一致的决策，如PokéLLMon案例。&lt;/li>
&lt;/ul>
&lt;p>结构性方法包括：&lt;/p>
&lt;ul>
&lt;li>使用有向无环图来控制行动进展。&lt;/li>
&lt;li>利用技能库&lt;/li>
&lt;li>以及定义具有清晰语义的结构化行动&lt;/li>
&lt;li>为代理分配特定角色并遵循结构化工作流程&lt;/li>
&lt;li>神经符号方法&lt;/li>
&lt;/ul>
&lt;h1 id="挑战">挑战&lt;/h1>
&lt;h2 id="幻觉">幻觉&lt;/h2>
&lt;p>LM可以产生与原始或准确信息不符的输出， 这种情况通常被描述为幻觉，想解决起来非常困难。&lt;/p>
&lt;p>通过引入critic agents（用于评价的agent）、SOP、角色特定prompt可以减少逻辑性的幻觉。&lt;/p>
&lt;p>此外，还有学者尝试引入上下文强化学习（ICRL）、知识增强生成（RAG）、多智体辩论等方法解决幻觉问题。&lt;/p>
&lt;h2 id="错误校正">错误校正&lt;/h2>
&lt;p>在此方面，许多研究采用迭代提示机制、反馈机制或agent之间的聊天链来识别和纠正错误。&lt;/p>
&lt;p>使用critic agents进行选择和反馈、带环境反馈的迭代prompt等方法被用于错误校正。&lt;/p>
&lt;h2 id="泛化">泛化&lt;/h2>
&lt;p>泛化能力指agent将在过去环境中获得的知识、技能和能力，应用于新的、以前未遇到的环境中，以实现目标并执行任务。&lt;/p>
&lt;p>解决的方法包括：上下文引导的COT推理方法 （Context-Oriented Thinking，COT）、Minecraft中利用长期规划和外部知识的GITM方法（Generalized Inverse Task Mapping，GITM），在多智体环境下的信息提取和协作规划等。&lt;/p>
&lt;h2 id="可解释性">可解释性&lt;/h2>
&lt;p>一些研究利用COT过程（COT processes）、模块化决策过程、清晰的对话式编程范式等方法增强agent行为的可解释性。&lt;/p>
&lt;h1 id="发展">发展&lt;/h1>
&lt;h2 id="多模态感知">多模态感知&lt;/h2>
&lt;p>通过增强多模态能力，包括视觉和听觉感知，也许可以增加agent对更复杂的任务处理。&lt;/p>
&lt;p>值得注意的是，游戏中的声音效果对于感知上下文、理解任务和接收反馈至关重要，但很少有文献探讨如何利用&lt;strong>听觉信息&lt;/strong>来提升游戏agent的表现。&lt;/p>
&lt;h2 id="游戏体验的真实性">游戏体验的真实性&lt;/h2>
&lt;p>相比于由大型语言模型生成的对话和想法，人们更偏爱人类编写的内容。这表明未来的研究需要更好地将LLM生成的内容与游戏的叙事和状态联系起来。&lt;/p>
&lt;h2 id="外部工具">外部工具&lt;/h2>
&lt;p>大模型agent无法掌握利用外部工具，来提升自己在游戏中的表现。&lt;/p>
&lt;h2 id="实时性">实时性&lt;/h2>
&lt;p>考虑到大模型固有的推理过程和计算需求， 掌握实时、高速游戏提出了一项艰巨的挑战。&lt;/p></description></item><item><title>论文解读 | 2月最新大模型综述——来自Word2Vec作者Tomas Mikolov</title><link>https://geyuyao.com/post/large-language-models-survey/</link><pubDate>Sat, 16 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/large-language-models-survey/</guid><description>&lt;h1 id="介绍">介绍&lt;/h1>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710679207909.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>大型语言模型（LLMs）主要指基于Transformer的神经语言模型，这些模型包含数百亿到数千亿个参数，在大规模文本数据上进行预训练，例如PaLM、LLaMA和GPT-4。与PLMs相比，LLMs不仅在模型规模上更大，而且在语言理解和生成能力上表现更强，更重要的是，具有在小规模语言模型中不存在的新兴能力。如上图所示，这些新兴能力包括（1）上下文学习，即LLMs在推理时从提示中呈现的少量示例中学习新任务，（2）遵循指令，即经过指令调整后，LLMs可以遵循新类型任务的指令而无需使用显式示例，以及（3）多步推理，即LLMs可以通过将任务分解为中间推理步骤来解决复杂任务，如链式思维提中所示。LLMs还可以通过使用外部知识和工具进行增强，以便它们可以有效地与用户和环境进行交互，并通过与人类互动收集的反馈数据（例如通过强化学习与人类反馈（RLHF））持续改进自身。&lt;/p>
&lt;h1 id="大语言模型">大语言模型&lt;/h1>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 80%;" src="1710686762203.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;h2 id="早期预训练神经网络">早期预训练神经网络&lt;/h2>
&lt;p>1999年，Bengio等人开发了最早的神经语言模型（neural language models - NLMs），可与n-gram模型相媲美。此后，基于循环神经网络（recurrent neural networks - RNNs）及其变种，如长短期记忆（long short-term memory - LSTM）和门控循环单元（gated recurrent unit - GRU）的NLMs被广泛用于许多自然语言应用，包括机器翻译、文本生成和文本分类。随后，Transformer架构的发明标志着自然语言模型(NLMs)发展中的又一个里程碑。Transformers比RNNs具有并行的能力，这使得在GPU上可以高效地预训练非常大的语言模型。这些预训练语言模型（pre-trained language models - PLMs）可以针对许多下游任务进行微调。&lt;/p>
&lt;p>我们将早期流行的、基于Transformer的PLMs，根据它们的神经架构，分为三个主要类别：encoder-only、decoder-only和encoder-decoder在下文分别介绍。&lt;/p>
&lt;h3 id="encoder-only-plms">&lt;em>Encoder-only PLMs:&lt;/em>&lt;/h3>
&lt;p>正如其名，encoder-only models仅包含编码器网络。这些模型最初是为了语言理解任务而开发的，例如文本分类，其中模型需要预测输入文本的类别标签。代表性的为BERT及其变种，例如RoBERTa、ALBERT、DeBERTa、XLM、XLNet、UNILM等。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710680176745.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">BERT的整体预训练和微调流程&lt;/div>&lt;/center>
&lt;p>BERT（Bidirectional Encoder Representations from Transformers）是最广泛使用的encoder-only架构的模型之一。BERT由三个模块组成：（1）一个嵌入模块，将输入文本转换为一系列embedding向量，（2）一堆Transformer编码器，将embedding向量转换为上下文表示向量，以及（3）一个全连接层，将表示向量（在最终层）转换为one-hot向量。BERT经过预训练，使用了两个目标：masked language modeling（MLM）和 next sentence prediction。预训练的BERT模型可以通过添加一个分类器层进行微调，用于许多语言理解任务，从文本分类、问答到语言推理。BERT的整体预训练和微调流程如上图所示。&lt;/p>
&lt;h3 id="decoder-only-plms">&lt;em>Decoder-only PLMs&lt;/em>&lt;/h3>
&lt;p>Decoder-only架构的PLMs中，最具代表性的莫过于由OpenAI开发的GPT-1和GPT-2，其出现为GPT-3.5和GPT-4铺平道路。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710680578957.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">GPT预训练和微调步骤概述&lt;/div>&lt;/center>
&lt;p>GPT-1首次证明了通过在未标记文本语料库上，采用自监督学习方式，对Decoder-only架构的生成式预训练（Generative Pre-Training - GPT）模型进行训练，然后通过在每个特定下游任务上进行区分性微调，可以获得在各种自然语言任务上的良好性能。&lt;/p>
&lt;p>GPT-2表明，当在由数百万个网页组成的大型WebText 数据集上训练时，语言模型能够学习执行特定的自然语言任务，而无需任何明确的监督。&lt;/p>
&lt;blockquote>
&lt;p>自监督学习：属于无监督学习的一个子集。在自监督学习中，模型使用未标记的数据集自身作为训练数据。例如，在GPT模型的训练过程中，模型预测下一个Token，而这个预测任务并不需要外部标注的数据，因为下一个Token直接来自于输入数据本身。&lt;/p>
&lt;/blockquote>
&lt;h3 id="encoder-decoder-plms">&lt;em>Encoder-Decoder PLMs&lt;/em>&lt;/h3>
&lt;p>过去的研究表明，几乎所有自然语言处理任务都可以被视为一个sequence-to-sequence生成任务。因此，Encoder-Decoder语言模型从设计上来说是一个统一的模型，因为它可以执行所有自然语言理解和生成任务。此类别中，最具代表性的莫过于T5、mT5、MASS和BART等。&lt;/p>
&lt;h2 id="大模型家族">大模型家族&lt;/h2>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710682371551.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>大型语言模型（Large Language Model - LLMs）主要指包含数十亿到数百亿参数的基于Transformer架构的PLMs。与上述PLMs相比，LLMs不仅在模型大小上更大，而且在语言理解、生成和新兴能力方面表现更强，这些能力在规模较小的模型中不存在。接下来，我们将回顾三个LLM系列：GPT、LLaMA和PaLM：&lt;/p>
&lt;h3 id="the-gpt-family">&lt;em>The GPT Family&lt;/em>&lt;/h3>
&lt;p>生成式预训练（Generative Pre-Training - GPT）是一类基于Decoder-only架构的模型家族，由OpenAI开发。该家族包括GPT-1、GPT-2、GPT-3、InstrucGPT、ChatGPT、GPT-4、CODEX和WebGPT。尽管早期的GPT模型，如GPT-1和GPT-2，是开源的，但最近的模型，如GPT-3和GPT-4，是闭源的，只能通过API访问。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>GPT-3&lt;/strong>：一个具有1750亿参数的预训练自回归语言模型。GPT-3被广泛认为是第一个LLM，因为它不仅比以前的PLM大得多，而且首次展示了以前较小的PLM中没有观察到的新兴能力。GPT-3展示了上下文学习的新兴能力，这意味着GPT-3可以应用于任何下游任务，而无需任何梯度更新或微调。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>CODEX&lt;/strong>：一种通用编程模型，能够解析自然语言并生成代码作为回答。CODEX是GPT-3的后代，经过在从GitHub收集的代码语料库上进行编程应用的微调。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>WebGPT&lt;/strong>：GPT-3的另一个后代，经过微调以使用基于文本的网络浏览器回答开放性问题，帮助用户搜索和浏览网络。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>InstructGPT&lt;/strong>：为了使LLMs能够遵循人类指令，InstructGPT被提出，通过使用人类反馈（RLHF）进行微调，使其与用户意图在各种任务上保持一致。&lt;/p>
&lt;blockquote>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="图片.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">RLHF的概述&lt;/div>&lt;/center>
&lt;p>RLHF：从一组由标注者编写的提示和通过OpenAI API提交的提示开始，收集了一组标注者演示所需模型行为的数据集。然后在这个数据集上对GPT-3进行微调。接着，收集了一组人类排名的模型输出数据集，通过强化学习进一步微调模型。该方法被称为从人类反馈中学习强化学习（RLHF）。&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>ChatGPT（GPT-3.5）&lt;/strong>：LLM发展中最重要的里程碑是于2022年11月30日推出的ChatGPT。ChatGPT是一款聊天机器人，使用户能够引导对话以完成各种任务，如回答问题、寻找信息、文本摘要等。ChatGPT由GPT-3.5驱动，是InstructGPT的姊妹模型。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710681340133.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">相比与GPT3.5，GPT-4在学术和专业考试中的表现&lt;/div>&lt;/center>
&lt;ul>
&lt;li>&lt;strong>GPT4&lt;/strong>：GPT系列中最新、最强大的LLM。于2023年3月推出，GPT-4是一种多模态LLM，可以接受图像和文本作为输入，并生成文本输出。虽然在一些最具挑战性的现实场景中仍不及人类，但GPT-4在各种专业和学术基准测试中表现出人类水平的性能，包括通过模拟的律师资格考试，得分约为前10%的考生，如上图所示。与早期的GPT模型一样，GPT-4首先经过预训练，以预测大型文本语料库中的下一个标记，然后通过RLHF进行微调，以使模型行为与人类期望的行为一致。&lt;/li>
&lt;/ul>
&lt;h3 id="the-llama-family">&lt;em>The LLaMA Family&lt;/em>&lt;/h3>
&lt;p>LLaMA是由Meta发布的一系列大语言模型。与GPT模型不同，LLaMA模型是开源的。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>LLaMA-1&lt;/strong>：第一批LLaMA模型于2023年2月发布，参数范围从7B到65B。这些模型在从公开可用数据集中收集的数万亿个Token上进行了预训练。LLaMA使用了GPT-3的Transformer架构，进行了一些轻微的架构修改。&lt;/li>
&lt;li>&lt;strong>LLaMA-2&lt;/strong>：2023年7月，Meta与微软合作发布了LLaMA-2系列，其中包括基础语言模型和针对对话进行微调的Chat模型，称为LLaMA-2 Chat。&lt;/li>
&lt;/ul>
&lt;h3 id="the-palm-family">&lt;em>The PaLM Family&lt;/em>&lt;/h3>
&lt;p>PaLM（Pathways Language Model）系列由Google开发。&lt;/p>
&lt;ul>
&lt;li>首个PaLM模型于2022年4月宣布，其在6144个TPUv4芯片上使用Pathways系统进行预训练，包含5400亿参数，于2023年3月开源。&lt;/li>
&lt;li>PaLM-2与其前身PaLM相比，使用混合目标进行训练。通过对英语、多语言和推理任务的广泛评估，PaLM-2在不同模型大小下显著提高了在下游任务上的模型性能，同时展现出比PaLM更快速和更高效的推理能力。&lt;/li>
&lt;/ul>
&lt;h3 id="其他">&lt;em>其他&lt;/em>&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Mistral-7B&lt;/strong>：一个专为卓越性能和效率而设计的7B参数语言模型。Mistral-7B在所有评估基准中均优于LLaMA-2-13B，并在推理、数学和代码生成方面优于LLaMA-34B。该模型利用&lt;strong>分组查询注意力&lt;/strong>以实现更快的推理，结合&lt;strong>滑动窗口注意力&lt;/strong>有效处理任意长度的序列，并降低推理成本。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710682078104.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">BLOOM架构&lt;/div>&lt;/center>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>BLOOM&lt;/strong>：Scao等人提出了BLOOM，这是一个拥有176B参数的开放获取语言模型，是由数百名研究人员合作设计和构建的。BLOOM是一个仅解码器的Transformer语言模型，是在ROOTS语料库上训练的，该语料库包含46种自然语言和13种编程语言的数百个来源（共59种）。其架构如上图所示。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>GLM&lt;/strong>：一个大型双语（英语和中文）预训练语言模型，具有1300亿个参数。它旨在公开一个与GPT-3（davinci）至少同等水平的1000亿级别的模型。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Gemini&lt;/strong>：Gemini团队介绍了一系列新的多模态模型，支持32k上下文长度。Gemini系列包括三个版本：Ultra用于高度复杂的任务，Pro用于增强性能和规模部署能力，Nano用于设备应用。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="如何构建一个大模型">如何构建一个大模型&lt;/h1>
&lt;h2 id="架构选择">架构选择&lt;/h2>
&lt;p>如上文所述，目前最广泛使用的LLM架构包括encoder-only、decoder-only和encoder-decoder架构。&lt;/p>
&lt;p>在此，我们首先回顾Transformer架构。其最初在论文《Attention is all you need》中被提出，最初是为了利用GPU进行有效的并行计算而设计的。其核心是注意力机制，相比于循环和卷积机制，注意力机制可以（1）更有效地利用GPU和（2）捕捉长期上下文信息。其中，注意力函数可以描述为将query和一组key-value对映射到输出，其中query、key、value和输出都是向量。输出是value的加权和，其中分配给每个值的权重由query与相应key的兼容性函数计算。&lt;/p>
&lt;h3 id="encoder-only">&lt;em>Encoder-Only&lt;/em>&lt;/h3>
&lt;p>对于Encoder-Only架构，在每个阶段，注意力层可以访问初始句子中的所有单词。这些模型的预训练通常包括&lt;strong>以某种方式破坏给定句子（如mask）并要求重构句子&lt;/strong>。&lt;strong>Encoder-Only架构非常适用于需要理解完整序列的任务，如句子分类、命名实体识别和抽取式问答&lt;/strong>。&lt;/p>
&lt;h3 id="decoder-only">&lt;em>Decoder-Only&lt;/em>&lt;/h3>
&lt;p>对于Decoder-Only架构，在每个阶段，对于任何Token，注意其前面的Token。这些模型有时也被称为自回归模型。这些模型的预训练通常被制定为预测序列中的下一个Token（Next token prediction）。Decoder-Only架构适合涉及文本生成的任务。GPT模型是这一模型类别的杰出示例。&lt;/p>
&lt;h3 id="encoder-decoder">&lt;em>Encoder-Decoder&lt;/em>&lt;/h3>
&lt;p>Encoder-Decoder架构同时使用编码器和解码器，有时被称为sequence-to-sequence模型。在每个阶段，Encoder的注意力层可以访问初始句子中的所有单词，而Decoder的注意力层只能访问输入中给定Token之前的Token。Encoder-Decoder模型适合，给定的输入比如摘要、翻译或生成式问答，生成新句子的任务。&lt;/p>
&lt;h2 id="数据清洗">数据清洗&lt;/h2>
&lt;p>数据质量对于在其上训练的语言模型的性能至关重要。诸如过滤、去重等数据清洗技术已被证明对模型性能有重大影响。&lt;/p>
&lt;h3 id="数据过滤">数据过滤&lt;/h3>
&lt;p>数据过滤旨在提高训练数据的质量和训练后LLM的效果。常见的数据过滤技术包括：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>数据去噪&lt;/strong>：如删除虚假信息&lt;/li>
&lt;li>&lt;strong>处理异常值&lt;/strong>&lt;/li>
&lt;li>&lt;strong>类别不平衡&lt;/strong>：平衡数据集中类别的分布&lt;/li>
&lt;li>&lt;strong>文本预处理&lt;/strong>：去除停用词、标点符号等&lt;/li>
&lt;li>&lt;strong>处理歧义&lt;/strong>：处理模糊或矛盾数据&lt;/li>
&lt;/ol>
&lt;h3 id="数据去重">数据去重&lt;/h3>
&lt;p>去重指删除重复实例或重复出现的相同数据。重复数据点可能会在模型训练过程中引入偏见并降低多样性。一些研究表明，去重可以提高模型对新的、未见数据的泛化能力。&lt;/p>
&lt;h2 id="分词">分词&lt;/h2>
&lt;p>Tokenization是将文本序列转换为较小部分即Token的过程。&lt;/p>
&lt;h2 id="模型预训练">模型预训练&lt;/h2>
&lt;p>预训练是大型语言模型训练流程中的第一步。在预训练期间，LLM通常以自监督的方式在大量（通常是）未标记的文本上进行训练。 用于预训练的不同方法最常见的两种是next token prediction 和 masked language modeling，MLM。&lt;/p>
&lt;ul>
&lt;li>next token prediction：从左到右（或从右到左）逐Token预测句子中的下一个Token，建立Token与Token之间的依赖关系。适合于文本生成任务，如机器翻译、文本生成等。&lt;/li>
&lt;li>masked language modeling：在MLM中，模型通过预测句子中随机掩盖的单词来学习Token之间的关系，训练模型理解单词的上下文含义。MLM更适合于理解任务，如文本分类、命名实体识别等。&lt;/li>
&lt;/ul>
&lt;h2 id="微调fine-tuning和指令微调instruction-tuning">微调(Fine-tuning)和指令微调(Instruction Tuning)&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>微调通常有两个目的：（1）使基座模型应对不同的任务，（2）增加新的知识&lt;/p>
&lt;/li>
&lt;li>
&lt;p>除了微调，我们还希望大模型理解和遵循人类的自然语言指令。此时就需要指令微调。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="对齐">对齐&lt;/h2>
&lt;p>AI对齐（AI Alignment）是将AI系统引导朝向人类目标、偏好和原则的过程。有时，大型语言模型为了进行Token预测会表现出危险行为。比如，它们可能生成不良、有害、误导性和偏见的内容。&lt;/p>
&lt;p>在此阶段，两种流行的方法是&lt;strong>RLHF&lt;/strong>（来自人类反馈的强化学习）和&lt;strong>RLAIF&lt;/strong>（来自AI反馈的强化学习）。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>RLHF&lt;/strong>：RLHF使用奖励模型从人类反馈中学习对齐。调整后的奖励模型能够评估不同的输出，根据人类给定的对齐偏好对要训练的模型的输出进行评分。&lt;/li>
&lt;li>&lt;strong>RLAIF&lt;/strong>：另一方面，&lt;strong>RLAIF&lt;/strong>直接将一个预训练且对齐良好的模型连接到要训练的LLM，并帮助其从这个更大、更对齐的模型中学习。这种方式类似于一种广义的知识蒸馏。&lt;/li>
&lt;/ul>
&lt;h2 id="解码策略">解码策略&lt;/h2>
&lt;p>解码是指使用预训练的大型语言模型生成文本的过程。给定一个输入Prompt，分词器将输入文本中的每个Token转换为相应的Token的数值表示。然后，语言模型使用这些Token的数值表示作为输入，并预测下一个最有可能的Token。最后，模型生成logits，通过softmax函数将其转换为概率。已经提出了不同的解码策略。其中一些最流行的策略包括贪心搜索,束搜索,top-K,top-P等。&lt;/p>
&lt;h3 id="greedy-search">Greedy Search&lt;/h3>
&lt;p>贪婪搜索在每一步中选择最有可能的标记作为序列中的下一个标记，丢弃所有其他潜在选项。正如许多贪心算法的缺陷一样，这种方法可能会丧失文本的一致性和连贯性。它只考虑每一步中最有可能的Token，而不考虑生成的序列整体效果。&lt;/p>
&lt;h3 id="beam-search">Beam Search&lt;/h3>
&lt;p>与贪婪搜索只考虑下一个最可能的标记不同，束搜索考虑了N个最可能的Token，其中N表示束的数量。该过程重复进行，直到达到预定义的最大序列长度或出现序列结束标记。此时，具有最高总体分数的Tokne序列（也称为“束”）被选择为输出。例如，对于束大小为2且最大长度为5，束搜索需要递归生成并评估$2^5 = 32$个可能的序列。因此，它比贪婪搜索需要更大的计算量。&lt;/p>
&lt;h3 id="top-k">Top-k&lt;/h3>
&lt;p>Top-k抽样利用语言模型生成的概率分布从k个最有可能的选项中随机选择一个Token。&lt;/p>
&lt;p>假设我们有6个Token（A，B，C，D，E，F），设k=2，P(A)=30%，P(B)=20%，P(C)=P(D)=P(E)=P(F)=12.5%。在top-k抽样中，Token C、D、E、F被忽略，模型输出A的概率为60%，输出B的概率为40%。这种方法确保我们优先考虑最有可能的Token，同时引入一定的随机性。&lt;/p>
&lt;p>在该方法中，我们通常通过温度的概念引入随机性。温度T是一个从0到1的参数，影响softmax函数生成的概率，其作用如公式所示：
$$
softmax(x_i)=\frac{e^{x_i/T}}{\sum_je^{x_j/T}}
$$
如公式所示，当温度较低时，概率分布会变得更加尖锐，这意味着概率较高的tokens会变得更加显著，从而使生成的文本更加确定，减少创造性；而高温度会使得概率分布更加平坦，赋予低概率tokens更多的机会，从而增加文本的多样性和创造性。&lt;/p>
&lt;h3 id="top-p">&lt;strong>Top-p&lt;/strong>&lt;/h3>
&lt;p>Top-p抽样，也被称为核抽样（Nucleus sampling），与top-k抽样有略微不同的方法。与选择前k个最可能的Token不同，核抽样选择一个阈值p，使得所选Token的概率之和超过p。换言之，在top-p抽样中，模型按降序检查最可能的Token，并将它们逐个添加到列表中，直到概率之和超过阈值p。&lt;/p>
&lt;h1 id="利用大模型">利用大模型&lt;/h1>
&lt;h2 id="大模型的限制">大模型的限制&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>没有状态/记忆&lt;/strong>：它们本身甚至无法记住之前提示中发送给它们的内容&lt;/li>
&lt;li>&lt;strong>回答是随机的/概率性的&lt;/strong>：如果多次向大模型发送相同输入，很可能会得到不同的回复&lt;/li>
&lt;li>&lt;strong>过时的信息&lt;/strong>&lt;/li>
&lt;li>&lt;strong>训练成本高&lt;/strong>&lt;/li>
&lt;li>&lt;strong>幻觉&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>这里只对即大模型幻觉（Hallucinations）进行探讨。&lt;/p>
&lt;p>LLM中的幻觉被描述为&amp;quot;生成的内容是荒谬的或不忠实于提供的来源&amp;quot;，其可被分为两种类别：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>内在幻觉（Intrinsic Hallucinations）&lt;/strong>：幻觉与原始材料直接冲突，事实不准确或逻辑不一致。&lt;/li>
&lt;li>&lt;strong>外在幻觉（Extrinsic Hallucinations）&lt;/strong>：无法从来源进行验证，包含了推测性或不可证实的元素。&lt;/li>
&lt;/ol>
&lt;p>幻觉的影响高度依赖于上下文和任务。例如，在像写诗这样的创造性努力中，幻觉可能被认为是可以接受甚至有益的。&lt;/p>
&lt;p>最近对于大模型幻觉的工作，如指导微调和来自人类反馈的强化学习（RLHF），试图引导LLM生成更加基于事实的输出，但其固有的概率性质和局限性仍然存在。&lt;/p>
&lt;h2 id="prompt工程">Prompt工程&lt;/h2>
&lt;p>在于LLM打交道的过程中，Prompt是用户提供的文本输入，用于引导模型的输出。Prompt通常包括指令、问题、输入数据和示例。&lt;/p>
&lt;p>典型的Prompt有：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Chain of Thought (CoT)&lt;/strong>：大名顶顶的CoT，让大模型Think step by step从而获得更好的输出。其包含两种主要形式：
&lt;ol>
&lt;li>&lt;strong>Zero-shot CoT&lt;/strong>：在问题后面加上&amp;quot;Let’s think step by step&amp;quot;。&lt;/li>
&lt;li>&lt;strong>Manual CoT&lt;/strong>：需要人为模型提供逐步推理示例作为模板。&lt;/li>
&lt;li>上述两种方法中，Manual CoT比Zero-shot CoT更有效。然而，通过手动构建CoT是困难且容易出错的。而Auto CoT就不具备这个问题，详情见&lt;a href="https://geyuyao.com/post/auto-cot/" target="_blank" rel="noopener">Auto CoT——利用聚类自动生成CoT&lt;/a>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;strong>Tree of Thought(ToT)&lt;/strong>：基于CoT的思想，ToT可以展开形成多个&amp;quot;思维树&amp;quot;，其中每个分支代表不同的推理线路即CoT。&lt;/li>
&lt;li>&lt;strong>Self-Consistency&lt;/strong>：在给定Prompt的下，LLM不只生成一个回答，而是生成多个回答。之后对这些候选回答进行评估，以确定它们之间的一致性。最后，选择在所有回答上保持一致性最好的回答作为最终输出。&lt;/li>
&lt;li>&lt;strong>Reflection&lt;/strong>：促使大模型根据对其回答的正确性和连贯性的推理来评估并可能修改其输出。&lt;/li>
&lt;li>&lt;strong>Expert Prompting&lt;/strong>：提示LLMs扮演专家角色并相应地回答问题，提供高质量、知情的答案。&lt;/li>
&lt;/ol>
&lt;h2 id="rag">RAG&lt;/h2>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 70%;" src="1710686853330.png "> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>如上图所示所示，RAG从Prompt中提取查询的问题，并使用该查询的问题从外部知识源（例如搜索引擎或知识图谱）检索相关信息。然后将相关信息添加到Prompt中，并将其馈送给大模型，使得大模型生成最终回答。&lt;/p>
&lt;h2 id="大模型agents">大模型Agents&lt;/h2>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 70%;" src="1710686912432.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>AI Agents的概念有着深远的历史。AI Agents通常是一个自主实体，可以利用其传感器感知环境，根据当前状态做出判断，并行动。&lt;/p>
&lt;p>在大模型的背景下，Agents指的是基于大模型能够自主执行特定任务的系统。这些Agents被设计用于与用户或环境进行交互，根据输入和交互的预期目标做出决策。Agents的核心特点是：&lt;/p>
&lt;ol>
&lt;li>能够访问和使用工具&lt;/li>
&lt;li>能够自主决策&lt;/li>
&lt;/ol>
&lt;p>在此领域比较有代表性的工作是ReAct，LATS等，感兴趣的读者可以阅读笔者之前的文章&lt;a href="https://geyuyao.com/post/react/" target="_blank" rel="noopener">ReAct——LLM推理范式 推理+动作&lt;/a>。&lt;/p>
&lt;h1 id="数据集">数据集&lt;/h1>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="101.png
"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;h1 id="挑战">挑战&lt;/h1>
&lt;h2 id="更小更高效的模型">更小更高效的模型&lt;/h2>
&lt;p>当前的研究趋势是提出小型语言模型（SLMs）作为对LLMs的更经济的替代选项，特别是在不需要如此大模型的任务时。&lt;/p>
&lt;h2 id="注意力机制之后引入的新的架构范式">注意力机制之后引入的新的架构范式&lt;/h2>
&lt;p>这类在注意力模型后被提出的模型中的一个重要类别是状态空间模型（SSMs）。虽然状态空间模型的概念在机器学习中有着悠久的历史，但在语言模型的背景下，SSM通常是指较新的结构状态空间模型架构，简称S4。这一类别中的一些最近模型包括Mamba、Hyena和Striped Hyena。&lt;/p>
&lt;p>另一方面，最近一些与注意力兼容的架构机制正在逐渐崭露头角，如专家混合（MoE）。值得注意的是，MoEs可以作为任何架构的组成部分，无论其是否基于注意力机制。&lt;/p>
&lt;h2 id="多模态">多模态&lt;/h2>
&lt;p>目前已经有几个知名的多模态LLMs存在，包括：LLAVA（视觉语言模型）、LLAVA-Plus（LLAVA的扩展版）、GPT-4、Qwen-vl、 Next-GPT等。&lt;/p>
&lt;h2 id="大模型的使用和增强技术">大模型的使用和增强技术&lt;/h2>
&lt;p>如Prompt和RAG等&lt;/p>
&lt;h2 id="大模型安全">大模型安全&lt;/h2>
&lt;p>如隐私、偏见等。&lt;/p></description></item><item><title>图数据挖掘笔记——NIPS2020 Workshop</title><link>https://geyuyao.com/post/graph-mining-and-learning/</link><pubDate>Thu, 14 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/graph-mining-and-learning/</guid><description>&lt;h1 id="前言">前言&lt;/h1>
&lt;p>本文内容为笔者学习Google data Mining Team在NIPS2020上的Workshop的笔记。&lt;/p>
&lt;p>该项目主页为&lt;a href="https://gm-neurips-2020.github.io/" target="_blank" rel="noopener">Graph Mining &amp;amp; Learning&lt;/a>，pdf版的链接为&lt;a href="https://gm-neurips-2020.github.io/master-deck.pdf" target="_blank" rel="noopener">Mining and Learning with Graphs at Scale&lt;/a>。&lt;/p>
&lt;h1 id="introduction">Introduction&lt;/h1>
&lt;h2 id="什么是图">什么是图&lt;/h2>
&lt;p>图是一种表示实体之间的关系的数据。&lt;/p>
&lt;p>其中，实体(entity)指的是节点(node)。关系(relationship)指的是边(edge)。&lt;/p>
&lt;p>一般而言，图有如下特点：&lt;/p>
&lt;ol>
&lt;li>大量的边&lt;/li>
&lt;li>多种类型的边和多种类型的节点&lt;/li>
&lt;li>有高度复杂的结构&lt;/li>
&lt;/ol>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1710465853354.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>于是，图可以被用来表示社交网络、交通网络等。&lt;/p>
&lt;h2 id="图的种类">图的种类&lt;/h2>
&lt;p>一般而言，图可以被划分为两种类别——自然图(Natural graphs)和相似性图(Similarity graphs)。&lt;/p>
&lt;h3 id="自然图">自然图&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1710466664451.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>自然图中，其边的关系来源于外部的实际情况或数据。换言之，自然图所表示的实体及关系是现实世界中存在的。例如，支付网络中的每一笔交易可以看作是一个边，连接着支付方和接收方；社交网络中，两个人之间的友谊关系也可以表示为一个边；道路网中，道路连接着不同的地点；还有共同点击或共同观看的情况，如果两个项目被同一个人点击或观看，它们之间就可以用一个边来表示。这种图的特点是其边的存在和性质是由现实世界中的关系或交互确定的。&lt;/p>
&lt;h3 id="相似性图">相似性图&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="1710466676612.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>与自然图相反，相似性图中的边的关系来自于节点之间的相似度。在这种图中，我们首先有一大堆元数据或数据，然后通过度量数据之间的相似性或距离来为这些数据构建图的结构。例如，如果我们有一组文章，可以基于文章内容的相似度（比如使用关键词的相似性或文章的主题相似性）来连接文章，构成一个图。在这种情况下，边的创建是基于对数据本身特性的分析和计算，而不是基于外部已存在的关系。&lt;/p>
&lt;p>&lt;strong>注意：&lt;/strong> 在我们处理相似性图的时候，每个节点原本的元数据(meta-data)我们依然可以使用。对于高维元数据，使用预处理/预计算的方式可以避免许多重复计算，从而节省很多时间。&lt;/p>
&lt;h2 id="为什么要用图">为什么要用图？&lt;/h2>
&lt;h3 id="计算抽象概念">计算抽象概念&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710467684928.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>所谓&amp;quot;计算抽象概念&amp;quot;，原文&amp;quot;Computation on abstract concepts&amp;quot;，指的是我们可以利用图来处理复杂的事务。举例来讲，社交网络中的人际联系、交通系统中的路线连接、科学研究中的因果关系往往都是很复杂的，而其中的许多数据都可以归纳为实体间的相互作用和联系，也就是图。图是理解和操作这些关系的有力工具。图不仅能帮助我们理解和分析局部（即直接连接的实体间的）信息，而且还能帮助我们抽象这些信息。这意味着我们可以从特定的实例或局部情况中提取出通用模式或原则，通过对局部信息的抽象，图使我们能够从整体数据中提取出有用的全局信息，这可能涉及识别整个网络中的关键节点（比如社交网络中的意见领袖），发现群体结构（比如社区检测），或者理解整体结构如何影响个体行为和系统性能。&lt;/p>
&lt;p>###计算多模态数据&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710467672364.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>许多场景下，我们不得不同时处理多种模态的数据，如视觉的、文本的、语义的信息，这些数据相互关联。通过图，我们可以将多种模态的数据相关联，并进行计算。&lt;/p>
&lt;h3 id="全局视角">全局视角&lt;/h3>
&lt;p>图的结构可以帮助我们发现数据中的模式、群组或关系，甚至可以量化一些本质上难以直接度量的概念。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710468154909.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>以上图为例，对于一张模棱两可的苹果图片，我们可以分别计算其与苹果公司图片簇的相似度和自然苹果图片簇的相似度，从而得出这张苹果图片到底属于哪一个簇。&lt;/p>
&lt;h3 id="局部视角">局部视角&lt;/h3>
&lt;p>通过对图结构的计算，图可以提供超越单个节点属性描述的信息。具体来讲，对于节点，我们能获得的信息有限。但是通过计算该节点周围的节点和边的信息，我们可以获得更多的信息。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710468286544.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>以上图为例，对于单个像素，我们并不知道该像素的意义。但是通过观察该像素周围的像素，我们可以知道该像素来自猫的眼睛。&lt;/p>
&lt;h2 id="数据挖掘工具箱the-graph-mining-toolbox">数据挖掘工具箱(The Graph Mining Toolbox)&lt;/h2>
&lt;p>此段介绍了Google 数据挖掘团队(Graph Mining Team)开发并使用的工具箱。后文会提及，故略去。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710469413448.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;h2 id="应用案例">应用案例&lt;/h2>
&lt;h3 id="垃圾邮件诈骗和滥用行为检测">垃圾邮件、诈骗和滥用行为检测&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710470155439.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>对于检测垃圾信息、欺诈和滥用行为中的应用，特别是在信任与安全问题的处理上，Google团队介绍了两种核心思想和方法——基于密度聚类的异常检测和标签传播：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>异常检测通过密度聚类&lt;/strong>：&lt;/p>
&lt;p>统计学上不太可能的密集群集与恶意行为高度相关。这意味着，如果我们在数据的图表示中发现异常密集的节点群集，这些群集很可能表示垃圾信息发送者、欺诈行为或其他类型的滥用行为。通过使用图挖掘工具，可以识别这些不寻常的密集群集，从而检测和防止恶意行为。这对于保持产品如YouTube和广告平台的安全和信任至关重要。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>标签传播&lt;/strong>：&lt;/p>
&lt;p>从已知的恶意行为者（bad actors）开始，利用图的结构识别可能同样存在问题的邻近节点。这种方法的思路是，恶意用户或实体往往在图中彼此靠近或以某种方式相互连接，例如，他们可能共同参与欺诈活动或垃圾信息传播。通过将标签（如“恶意”）从已知的恶意行为者传播到他们的连接节点，可以识别出更多的可疑行为者。这种方法有助于有效地扩大检测范围，发现其他可能未直接被识别为恶意的实体。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="提升机器学习模型">提升机器学习模型&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>关系发现&lt;/strong>：&lt;/p>
&lt;p>社交网络如何找到“可能认识的人”是通过分析社交图谱实现的。利用图信息可以发现那些不明显的连接，即使这些连接在直接的社交互动中可能不明显，通过图分析，我们可以揭示潜在的联系，比如共同的朋友、兴趣相投或相似的社交路径等。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>特征提取&lt;/strong>：&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710470096212.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>图产生的信号，如群集、个人化页面排名（PPR）向量和图嵌入，对于训练上游的机器学习模型非常有用。这些从图数据中提取的特征可以显著改善机器学习模型的性能，通过提供有关实体间关系的深入信息。在多模态模型中，图数据可以作为另一种模态，与其他数据类型（如文本、图像和声音）一起构成一个更大的整体。这种方法可以使机器学习模型利用更丰富的数据集，从而获得更全面的理解和更准确的预测。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>案例应用&lt;/strong>：&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710469945259.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>以Google Images的“视觉相似图像”功能为例，通过分析图像间的相似性，可以创建一个图，在这个图中，节点代表图像，边代表图像之间的视觉相似度。即使用户没有明确指定搜索条件，也能找到与给定图像视觉上相似的其他图像。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="高效计算">高效计算&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>资源效率：通信开销&lt;/strong>&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710470415837_1.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>在分布式计算系统中，大型数据集需要分割并分布到不同的计算节点上处理，这个过程中产生的通信开销可以通过图分割算法来减少。如在Google Driving Directions（谷歌驾车导航）中应用图分割，可以优化后端处理效率，使道路网络数据处理更加高效。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>数据效率和主动学习&lt;/strong>&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 100%;" src="1710470494310.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>我们可以利用图来回答像“我的数据集中哪些点最具多样性”这样的查询，这可以驱动主动学习循环。主动学习是一种策略，允许模型请求特定数据点的标注，以最有效地学习和提高性能，尤其适用于标注数据稀缺的情况。基于图的半监督学习适用于数据量少的模型，可以利用少量标注数据和大量未标注数据，通过图的结构来提升学习效果。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="application--stories">Application Stories&lt;/h1>
&lt;h2 id="利用时空图神经网络为新冠传播建模">利用时空图神经网络为新冠传播建模&lt;/h2>
&lt;h3 id="基础">基础&lt;/h3>
&lt;p>深度机器学习模型被描述为学习一个函数$f(x)$，其中$x$是一组精心挑选的特征。模型中的中间状态，也就是嵌入（embeddings），捕捉了在高维空间中特征之间的复杂相互作用。模型通过调整嵌入来最小化损失函数，以此来学习数据中的复杂模式和关系。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710498743617.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>深度学习模型能够自动学习和抽象输入数据与输出目标之间的复杂关系，即使这些关系在开始时并不明显或直接。&lt;strong>深度机器学习模型之所以强大，是因为它们能够接受任意的输入并学习到所需输出的映射。&lt;/strong>&lt;/p>
&lt;h3 id="深度学习在流行病学中的应用">深度学习在流行病学中的应用&lt;/h3>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710498806397.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>SIR模型将人群分为三个类别：易感者（Susceptible）、感染者（Infected）和康复者（Recovered），并尝试定义这些类别之间的转换关系。在过去，类别的识别和转换的准确识别是非常困难的任务。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710498814048.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>深度学习技术在处理这种复杂的疾病动态和多维数据方面显示出其能力，这些数据是传统的隔间模型（compartmental models）和统计模型难以捕捉的。深度学习能够分析和理解疾病传播的复杂模式，提供比传统方法更精细和动态的疾病传播分析。&lt;/p>
&lt;h3 id="covid建模">COVID建模&lt;/h3>
&lt;p>流行病学建模依赖于时间和空间，明天的病例数量取决于昨天的病例数量和今天邻居的病例数量，因此这是一个多模态问题。而且，这还是一个图问题。&lt;/p>
&lt;p>该团队使用分层图进行建模。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710499261934.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>在上面这张图中，每个节点代表一个特定的时间和地点，节点自身的特征为病例数量和内部移动数据。&lt;/p>
&lt;p>图被建模为150个层，每层代表一个时间点。在每个层内部的边表示空间属性，这些边的权重表示的是移动距离；而层之间的边表示时间属性，其权重是基于边所连接的节点之间经过的时间（时间越长，权重越低，即反比例关系）。&lt;/p>
&lt;p>这样的设计允许模型捕捉到时间上的动态变化（通过时间边）和空间上的联系（通过空间边），从而更好地理解和预测COVID-19的传播模式。&lt;/p>
&lt;p>从这个样例中，我们可以看到：&lt;strong>图数据的一个主要优势是能够将上下文信息纳入分析中，当分析一个节点时，可以考虑其周围邻接节点作为信息源。&lt;/strong>&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710499333705.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>GCNs正是利用了这一点，它通过学习节点及其邻域间的复杂关系，提高了分析和预测的精度和效率。这种方法使得模型不仅仅考虑单个节点的属性，还考虑了节点在图中的位置和周围节点的影响。&lt;/p>
&lt;h2 id="隐私计算">隐私计算&lt;/h2>
&lt;p>在分析用户数据时，隐私是一个基本的关切点，而图数据（如社交网络图、交易图等）也不例外。它提出了两个与图数据隐私相关的应用场景：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>利用图挖掘（图聚类）来提升用户隐私：&lt;/strong> 是否可以通过图挖掘技术，特别是图聚类，来增强用户隐私。其重点是，我们能否利用这些技术来识别和保护用户数据的敏感部分，从而提高隐私保护水平。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>保护社交网络应用中的用户隐私：&lt;/strong> 在社交网络应用中如何保护用户隐私。社交网络图通常包含大量关于个人关系和交互的敏感信息。其重点是，我们如何设计和实施机制来保护这些数据，避免未经授权的访问或滥用，同时允许合法和有益的数据分析和社交互动。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>这两个场景反映了图数据隐私保护的双重挑战：一方面需要利用图数据的结构和特性来增强用户隐私保护，另一方面需要确保这些数据不被滥用，保护用户免受隐私侵犯。&lt;/p>
&lt;p>隐私计算方面，Google的一项努力是FLoC——群组联合学习（Federated Learning of Cohorts）。&lt;/p>
&lt;h3 id="floc">FLoC&lt;/h3>
&lt;p>FLoC——群组联合学习（Federated Learning of Cohorts）是一种隐私保护的网络广告技术，是Chrome隐私沙盒（Privacy Sandbox）计划的一部分，旨在逐步淘汰第三方cookie的使用。&lt;/p>
&lt;p>其基本原理是以用户的浏览历史数据作为输入，通过由许多用户共享的、匿名的cookie替换可识别的第三方cookie，创建了包含至少k个具有相似浏览兴趣用户的FLoC（群组）。通过这种方式，广告商可以针对具有类似兴趣的群组，而不是基于个人用户的具体行为数据进行广告投放。这减少了对个人隐私的侵犯，同时仍然允许广告的个性化定向。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710573095332.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>在此项目中，一个重要的问题是如何确认聚类的大小。换言之，在聚类过程中需要确保每个群集达到一个最小的规模，因为在较大的群集中个体更难被单独识别。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 30%;" src="1710573108436.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>经过实验，作者团队表明，Affinity在保持较高的余弦相似度同时，也能确保较高的匿名性。&lt;/p>
&lt;h3 id="on-device-public-private-graph-model">On-Device Public-Private Graph Model&lt;/h3>
&lt;p>On-Device Public-Private Graph Model是一种用于推荐系统数据处理和分析模型。其设计意图旨在不泄露用户私人信息的前提下，在用户的个人设备上进行复杂的计算。其关注点在于结合公共数据和私有数据进行运算。&lt;/p>
&lt;p>要实现该模型，一个需要回答的问题是&amp;quot;我们能否在不丧失任何隐私的情况下，将所有私人数据和联系人信息保留在用户的设备上，并解决重要的机器学习问题？&amp;quot;。&lt;/p>
&lt;p>Google团队给出的方法如下图所示。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710573124881.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>用户可以自愿选择哪部分作为私有数据保存在本地，非私有数据则会被上传到云端，构成公有数据供服务器使用。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710573134675.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>如上图所示，其工作流程由两个步骤构成：&lt;/p>
&lt;ol>
&lt;li>云端的公有数据发送摘要至个人用户。&lt;/li>
&lt;li>个人用户之间可以交换公有数据。&lt;/li>
&lt;/ol>
&lt;h2 id="聚类与因果推理">聚类与因果推理&lt;/h2>
&lt;p>因果推断是统计学的一个分支，试图建立因果之间的联系，其理论在临床试验中有大量应用，如随机试验——临床试验、A/B测试等。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 30%;" src="1710573179758.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>然而，随机试验可能会遇到干扰问题，即一个对象的处理可能影响另一个对象。例如，在教育研究中，如果对一组学生实施了某种教学方法，这种方法不仅可能影响这些学生，还可能影响到他们的老师、同学以及学校的整体教学环境，从而对研究结果造成干扰。&lt;/p>
&lt;p>为了尽可能接近“全治疗”和“全对照”的情况，随机试验将对象按簇分配给治疗组或对照组。这是因为，仍以上例为例：如果一个研究想要评估某种教育干预措施的效果，而这种干预措施可能会影响整个班级的学习氛围，那么研究者可能会选择整个班级而不是单个学生作为随机化的单位。这样，一个班级中的所有学生要么都接受干预措施，要么都不接受，这有助于确保干预措施的影响是在班级层面上被评估，从而减少了个体间干扰的问题。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.2125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);width: 50%;" src="1710573196802.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>正如上图所示，如果我们将个体作为实验对象，那么实验对象之间会互相影响，其相互影响的数量达10+之多。为了解决此问题，我们以簇作为实验对象。如右图所示，在该样例中，其相互影响的数量仅为4。&lt;/p></description></item><item><title>编码实践 | 一文读懂Self-Attention机制</title><link>https://geyuyao.com/post/transformer/</link><pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/transformer/</guid><description>&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>在当代自然语言处理（NLP）和深度学习领域，Transformer模型及其核心组成部分——自注意力（Self-Attention）机制——已经成为一种革命性的架构，对序列建模任务产生了深远的影响。自从Vaswani等人在2017年的论文&lt;a href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener">《Attention is All You Need》&lt;/a>中首次提出以来，Transformer模型已经成为了多种复杂任务的基石，包括机器翻译、文本生成、语音识别以及图像处理等。&lt;/p>
&lt;p>在Transformer中，自注意力（Self-Attention）因其卓越的性能，引发了学界和工业界的广泛关注。注意力机制让模型在每个时间步骤都能访问所有序列元素。其中的关键在于选择性，也就是确定在特定上下文中哪些词最重要。它通过纳入与输入上下文有关的信息来增强输入嵌入的信息内容。换句话说，自注意力机制让模型能够权衡输入序列中不同元素的重要性，并动态调整它们对输出的影响。&lt;/p>
&lt;p>在本文，我们根据文章&lt;a href="https://magazine.sebastianraschka.com/p/understanding-and-coding-self-attention" target="_blank" rel="noopener">《Understanding and Coding Self-Attention, Multi-Head Attention, Cross-Attention, and Causal-Attention in LLMs》&lt;/a>中的内容，手撕自注意力（Self-Attention）。其中文版发表在机器之心往期文章&lt;a href="https://mp.weixin.qq.com/s/XZDG8ZaB4QqD5cgIDJT6vQ" target="_blank" rel="noopener">《大模型时代还不理解自注意力？这篇文章教你从头写代码实现》&lt;/a>上。相比于上述两篇文章，本文加入了作者自己的思考和经验。&lt;/p>
&lt;h1 id="embedding">Embedding&lt;/h1>
&lt;p>在这一章节，我们通过Embedding编码，将输入序列中的离散符号（如单词或字符）转换为连续的、高维的向量表示。简单来讲，这样做的原因是深度学习模型无法直接理解原始的文本数据，而必须通过学习这些向量中的信息来理解文本的语义和语法结构。更深入的内容可以查看知乎文章&lt;a href="https://zhuanlan.zhihu.com/p/164502624" target="_blank" rel="noopener">《一文读懂Embedding的概念，以及它和深度学习的关系》&lt;/a>。&lt;/p>
&lt;p>对于一段句子，我们希望通过Embedding将其转化为连续的向量表示，这里以句子「Life is short, eat dessert first」为例。&lt;/p>
&lt;p>在预处理阶段，我们需要对句子中的单词进行去重，然后将每一个单词与一个整数索引进行映射。这个过程可以用Python轻松表示。&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sentence&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;Life is short, eat dessert first&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="ow">in&lt;/span> &lt;span class="nb">enumerate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">sorted&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sentence&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">()))}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dc&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">{&amp;#39;Life&amp;#39;: 0, &amp;#39;dessert&amp;#39;: 1, &amp;#39;eat&amp;#39;: 2, &amp;#39;first&amp;#39;: 3, &amp;#39;is&amp;#39;: 4, &amp;#39;short&amp;#39;: 5}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>通过将单词与整数索引的映射，句子可以被索引表示。&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sentence_int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tensor&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="n">dc&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">s&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">sentence&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">()]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sentence_int&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor([0, 4, 5, 2, 1, 3])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>好了！接下来我们就要进行Embedding的关键步骤了。&lt;/p>
&lt;p>在Embedding中，每个单词都被一个多维向量所表示。向量的维度由词库大小所决定。举个例子，Llama 2 的嵌入大小为 4096。为不显冗余，在本文，我们使用三维作为样例。&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">vocab_size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">50_000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">manual_seed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">123&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Embedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vocab_size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embedded_sentence&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sentence_int&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">detach&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">embedded_sentence&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">embedded_sentence&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor([[ 0.3374, -0.1778, -0.3035],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [ 0.1794, 1.8951, 0.4954],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [ 0.2692, -0.0770, -1.0205],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [-0.2196, -0.3792, 0.7671],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [-0.5880, 0.3486, 0.6603],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [-1.1925, 0.6984, -1.4097]])
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">torch.Size([6, 3])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如输出所示，我们句子中的6个单词，被表示为了六行向量，每个向量的维度为3。这意味着，句子中的每个单词被一个由三个数字构成的向量所表示。&lt;/p>
&lt;h1 id="定义权重矩阵">定义权重矩阵&lt;/h1>
&lt;p>自这一章节，我们将介绍Transformer中赫赫有名的&amp;quot;QKV&amp;quot;机制。&lt;/p>
&lt;p>自注意力使用了三个权重矩阵，分别记为 $W_q$、$W_k$ 和 $W_v$；它们作为模型参数，会在训练过程中不断调整。这些矩阵的作用是将输入分别投射成序列的查询、键和值分量。&lt;/p>
&lt;p>相应的查询、键和值序列可通过权重矩阵 $W$ 和嵌入的输入 $x$ 之间的矩阵乘法来获得：&lt;/p>
&lt;ul>
&lt;li>查询序列：对于属于序列 $1……T$ 的 $i$，有 $q^{(i)}=x^{(i)}W_q$&lt;/li>
&lt;li>键序列：对于属于序列 $1……T$ 的 $i$，有 $k^{(i)}=x^{(i)}W_k$&lt;/li>
&lt;li>值序列：对于属于序列 $1……T$ 的 $i$，有 $v^{(i)}=x^{(i)}W_v$&lt;/li>
&lt;li>索引 $i$ 是指输入序列中的 $token$ 索引位置，其长度为 $T$。&lt;/li>
&lt;/ul>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="640.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>在本文，$q^{(i)}$ 和$k^{(i)}$都是维度为$d_k$的向量。投射矩阵$W_q$和$W_k$的形状为 $d × d_k$，而$W_v$的形状是$d × d_v$。其中，$d$表示每个词向量$x$的维度数，本文中为3。&lt;/p>
&lt;p>由于我们要计算查询和键向量的点积，因此这两个向量的元素数量必须相同（$d_q=d_k$）。很多大模型也会使用同样大小的值向量，也就是 $d_q=d_k=d_v$。但是，值向量$v^{(i)}$的元素数量可以是任意值，其决定了所得上下文向量的大小。&lt;/p>
&lt;p>在接下来的代码中，我们将设定$d_q=d_k=2$，而$d_v=4$。投射矩阵的初始化如下：&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">manual_seed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">123&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embedded_sentence&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d_q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">W_query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_q&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">W_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_k&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">W_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_v&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在原论文&lt;a href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener">《Attention is All You Need》&lt;/a>中，$d_q$、$d_k$和$d_v$通常设置为&lt;code>64&lt;/code>，而模型的总维度为&lt;code>512&lt;/code>。&lt;/p>
&lt;h1 id="计算非归一化的注意力权重">计算非归一化的注意力权重&lt;/h1>
&lt;p>在本章，我们以第二个Token为样例，来进行演示：&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="f9774001-ea9d-48bf-9857-3c911b0a279d_588x962.jpg"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>如上图所示，我们需要将输入$x$与 $W_q$、$W_k$ 、$W_v$分别相乘。&lt;/p>
&lt;p>代码如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">x_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embedded_sentence&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">query_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_query&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">key_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">value_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query_2&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key_2&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">value_2&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">torch.Size([2])
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">torch.Size([2])
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">torch.Size([4])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>推而广之，我们可以将&lt;code>embedded_sentence&lt;/code>与$W_k$ 、$W_v$分别相乘，在后续的步骤中会被用到。&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">keys&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embedded_sentence&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">values&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embedded_sentence&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;keys.shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;values.shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">values&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">keys.shape: torch.Size([6, 2])
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">values.shape: torch.Size([6, 4])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>现在我们已经拥有了$query^{(2)}$和所有的&lt;code>keys&lt;/code>、&lt;code>values&lt;/code>，让我们接下来计算非归一化注意力权重$\omega$，如下图所示：&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="baf9e308-223b-429e-8527-a7b868003e8c_814x912.jpg"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>如上图所示，$\omega (i,j)$ 是查询和键序列之间的点积 $\omega (i,j) = q^{(i)}k^{(j)}$。&lt;/p>
&lt;p>举个例子，我们能以如下方式计算查询第2个Token与第5个Token之间的非归一化注意力矩阵：&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">omega_24&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">query_2&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">keys&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">omega_24&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor(1.2903)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>推而广之，我们可以将&lt;code>query_2&lt;/code>与&lt;code>keys&lt;/code>相乘，获得第2个Token与其他Token之间的非归一化注意力矩阵。&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">omega_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">query_2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">keys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">T&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">omega_2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor([-0.6004, 3.4707, -1.5023, 0.4991, 1.2903, -1.3374])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="计算注意力权重">计算注意力权重&lt;/h1>
&lt;p>在上一章，我们已经计算出了第2个Token与其他Token之间的非归一化注意力矩阵。在实际应用中，我们还需要对注意力矩阵进行归一化。&lt;/p>
&lt;p>对注意力矩阵进行归一化的目的在于，将每个序列位置上的注意力权重都在0到1之间，且所有位置的权重加起来等于1。这样的概率解释使模型能够以概率的形式表达对序列中不同部分的关注程度，其中较高的权重表示模型在该位置上给予更多的关注。&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="2222.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>如上图所示，在自注意力机制中，会先用 $1/√{d_k} $对$\omega$进行缩放，然后使用softmax 函数进行归一化。&lt;/p>
&lt;p>按$d_k$进行缩放可确保权重向量的欧几里得长度都大致在同等尺度上。这有助于防止注意力权重变得太小或太大 —— 这可能导致数值不稳定或影响模型在训练期间收敛的能力。&lt;/p>
&lt;p>我们可以这样用代码实现注意力权重的计算：&lt;/p>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch.nn.functional&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">F&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">attention_weights_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">F&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">omega_2&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">d_k&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="mf">0.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attention_weights_2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor([0.0386, 0.6870, 0.0204, 0.0840, 0.1470, 0.0229])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最后一步是计算上下文向量 $z^{(2)}$，即原始查询输入$x^{(2)}$ 经过注意力加权后的版本，其通过注意力权重将所有其它输入元素作为了上下文：&lt;/p>
&lt;center> &lt;img style="border-radius: 0.3125em; box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" src="9999999999999999999999.png"> &lt;br> &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9; display: inline-block; color: #999; padding: 1px;">&lt;/div>&lt;/center>
&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">context_vector_2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">attention_weights_2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context_vector_2&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context_vector_2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">torch.Size([4])
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tensor([0.5313, 1.3607, 0.7891, 1.3110])
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>请注意，这个输出向量的维度（$d_v=4$）比输入向量（$d=3$）多，因为我们之前已经设定了 $d_v &amp;gt; d$。但是，$d_v$的嵌入大小可以任意选择。&lt;/p>
&lt;h1 id="自注意力">自注意力&lt;/h1>
&lt;p>现在，总结一下之前小节中自注意力机制的代码实现。&lt;/p>
&lt;p>我们可以将之前的代码总结成一个紧凑的Self-Attention 类：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch.nn&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">nn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">SelfAttention&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Module&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_kq&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_v&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">d_out_kq&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">d_out_kq&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_kq&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_kq&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Parameter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rand&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_v&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">forward&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">keys&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">queries&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_query&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">values&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">W_value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">queries&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">keys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="c1"># unnormalized attention weights &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_weights&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_scores&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">d_out_kq&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="mf">0.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_vec&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">attn_weights&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">context_vec&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输入：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">manual_seed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">123&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># reduce d_out_v from 4 to 1, because we have 4 heads&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_kq&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sa&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SelfAttention&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_kq&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_out_v&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sa&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">embedded_sentence&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-txt" data-lang="txt">&lt;span class="line">&lt;span class="cl">tensor([[-0.1564, 0.1028, -0.0763, -0.0764],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [ 0.5313, 1.3607, 0.7891, 1.3110],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [-0.3542, -0.1234, -0.2627, -0.3706],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [ 0.0071, 0.3345, 0.0969, 0.1998],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [ 0.1008, 0.4780, 0.2021, 0.3674],
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> [-0.5296, -0.2799, -0.4107, -0.6006]], grad_fn=&amp;lt;MmBackward0&amp;gt;)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>可以从第二行看到，其值与前一节中 context_vector_2 的值完全一样：tensor ([0.5313, 1.3607, 0.7891, 1.3110])。&lt;/p>
&lt;h1 id="总结">总结&lt;/h1>
&lt;p>在本文，我们根据文章&lt;a href="https://magazine.sebastianraschka.com/p/understanding-and-coding-self-attention" target="_blank" rel="noopener">《Understanding and Coding Self-Attention, Multi-Head Attention, Cross-Attention, and Causal-Attention in LLMs》&lt;/a>中的内容，手撕自注意力（Self-Attention），提供了代码和解释。&lt;/p></description></item><item><title>论文解读 | Auto CoT——利用聚类自动生成CoT</title><link>https://geyuyao.com/post/auto-cot/</link><pubDate>Sat, 02 Mar 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/auto-cot/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Automatic Chain of Thought Prompting in Large Language Models&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Shanghai Jiao Tong University, Amazon Web Services&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Zhuosheng Zhang, Aston Zhang, Mu Li, Alex Smola&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2210.03493" target="_blank" rel="noopener">https://arxiv.org/abs/2210.03493&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2022.10.7&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>此前，CoT有两种范式，一种是Zero-shot，在问题末尾添加&amp;quot;Let’s think step by step&amp;quot;；另一种Manual CoT(Few-shot CoT)，每个例子由问题和推理链组成。第二种方法表现是否好取决于CoT写的好不好，不过这需要人手工来写。本文通过提出Auto-CoT这一方法使得Few-shot CoT可以自动生成，解放双手！&lt;/p>
&lt;h1 id="动机">动机&lt;/h1>
&lt;p>相比于Zero-shot CoT，Manual CoT(Few-shot CoT)效果更好，也更浪费人力，因此作者想设计Auto CoT。&lt;/p>
&lt;h1 id="发现">发现&lt;/h1>
&lt;p>与开门见山介绍方法的论文不同，本文首先进行了探索性的实验，然后再提出方法。&lt;/p>
&lt;p>首先作者对比Retrieval-Q-CoT和Random-Q-CoT方法在MultiArith，GSM8K，AQuA三个数据集上进行试验。作者发现在MultiArith问题上，Retrieval-Q-CoT甚至不如Random-Q-CoT，这显然是不符合常理的。作者怀疑，这是因为Zero-shot生成的CoT质量太差。于是，作者又在GSM8K，AQuA两个数据集上进行实验，与MultiArith数据集不同的是，这两个数据集的CoT是人工标注的。果然，在这两个数据集上Retrieval-Q-CoT好于Random-Q-CoT。于是作者得出结论，Zero-shot生成的CoT并不如人工编制的。&lt;/p>
&lt;blockquote>
&lt;p>Retrieval-Q-CoT：使用Sentence-BERT对问题进行编码，然后将相似度最高的前k个相似问题作为demo，$q_i^{demo}(i=1,..,k)$。对于这k个问题，使用Zero-shot生成CoT——$c_i^{demo}$，然后将$q_i^{demo},c_i^\text{demo}(i=1,&amp;hellip;,k),q^{test}$串联拼接作为输入提问大模型。&lt;/p>
&lt;p>Random-Q-CoT：相比Retrieval-Q-CoT随机选取k个问题。&lt;/p>
&lt;/blockquote>
&lt;p>为了进一步验证是否是错误的CoT导致推理效果不好，作者在600个样例中的128个中使用了错误的CoT，结果表明，Retrieval-Q-CoT受到了误导，进一步证明了CoT方法中正确的CoT的重要性。&lt;/p>
&lt;p>进一步，作者将所有的问题按照相似性使用k-means方法划分为k个类别，然后使用Zero-shot的方法生成CoT进行推理。作者想知道某些簇是否包含Zero-Shot-
CoT经常失败的问题，因此，作者计算每个簇的错误率。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709469511695.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示，2号簇的错误率特别高，这说明对于某一类问题，Zero-shot无法生成好的CoT，这可能就是导致Retrieval-Q-CoT表现不好的原因。&lt;/p>
&lt;h1 id="auto-cot">Auto CoT&lt;/h1>
&lt;p>结合上述发现，作者提出Auto CoT方法。&lt;/p>
&lt;p>Auto-CoT包括两个主要阶段：&lt;/p>
&lt;ol>
&lt;li>聚类：将给定数据集的问题划分为几个簇&lt;/li>
&lt;li>抽样：从每个簇中选择一个代表性问题，并使用简单的启发式方法使用Zero-Shot-CoT生成其推理链&lt;/li>
&lt;/ol>
&lt;p>整个过程如下图所示：&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709469718524.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>具体而言：&lt;/p>
&lt;ol>
&lt;li>在聚类阶段，将所有的问题Sentence-BERT生成向量表示，然后使用k-means聚类将问题划分为k类问题。对于每一簇内的问题，按照距离簇心距离排序，生成升序列表$\mathbf{q}^{(i)}=[q_1^{(i)},q_2^{(i)},\ldots]$。&lt;/li>
&lt;li>在抽样阶段，对于每一个簇，按照升序列表依次遍历每一个问题，对于当前问题，使用Zero-shot生成CoT，如果CoT满足token不大于60个且不超过五个步骤，则将此问题和CoT作为此簇中的每个问题的样例CoT，拼接在这类问题的前面。&lt;/li>
&lt;/ol>
&lt;h1 id="实验">实验&lt;/h1>
&lt;p>实验在三类推理任务、十个基准数据集和GPT-3上进行&lt;/p>
&lt;ol>
&lt;li>算术推理（MultiArith，GSM8K，AddSub，AQUA-RAT，SingleEq，SVAMP）&lt;/li>
&lt;li>常识推理（CSQA，StrategyQA）&lt;/li>
&lt;li>符号推理（Last Letter Concatenation，Coin Flip）&lt;/li>
&lt;/ol>
&lt;p>作为对比的方法有Zero-Shot，Zero-Shot-CoT，Few-Shot和Manual-CoT。&lt;/p>
&lt;p>如下图所示Auto-CoT 一贯匹配或超越了需要手动设计演示的CoT方法的性能。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709470146077.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;h1 id="总结">总结&lt;/h1>
&lt;p>从24年的角度看，本文方法相比于ReAct等比较简单，然而需要注意的是，本文提出的时间较早，大家都是摸着石头过河，能有如此方法已经难能可贵。事实上，即使是从最新的方法上也能看到Auto CoT的影子。&lt;/p></description></item><item><title>论文解读 | 思维链越长大模型越聪明？</title><link>https://geyuyao.com/post/reasoning-step-length/</link><pubDate>Mon, 26 Feb 2024 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/reasoning-step-length/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> The Impact of Reasoning Step Length on Large Language Models&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Northwestern University, University of Liverpool, New Jersey Institute of Technology, Rutgers University&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Mingyu Jin, Qinkai Yu, Dong Shu, Haiyan Zhao, Wenyue Hua, Yanda Meng, Yongfeng Zhang, Mengnan Du&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2401.04925" target="_blank" rel="noopener">https://arxiv.org/abs/2401.04925&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2024.1.20&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>思维链(Chain of thought - CoT)在过去的实践中已经证明对提升大模型的推理能力有显著帮助。然而，目前还没有一项工作解释思维链长度与推理能力之间的关系。本文围绕这一核心问题，围绕CoT做了系统实验，并给出许多有意思和反直觉的结论。&lt;/p>
&lt;h1 id="结论">结论&lt;/h1>
&lt;p>闲言少叙，直接上结论&lt;/p>
&lt;ol>
&lt;li>对于Few-shot CoT，模型回答的准确率与推理的步数呈线性关系。步数越长，模型回答越准确。相反，减少CoT长度，即使保证链条里的关键信息与长链条相同，也会显著降低模型的准确率。&lt;/li>
&lt;li>即使CoT链条中存在不正确的推理，如果保持必要的推理长度，也会产生有利的结果。也就是说，只要链条更长，即使中间步骤推错了，也会提高准确率。&lt;/li>
&lt;li>简单任务需要的步数少，复杂任务需要的步数多。&lt;/li>
&lt;li>即使是Zero-shot CoT，加了一句&amp;quot;你必须使用更多的步骤&amp;quot;相比于只有&amp;quot;让我们来一步一步思考&amp;quot;也会提高大模型的性能。&lt;/li>
&lt;/ol>
&lt;h1 id="实验设置">实验设置&lt;/h1>
&lt;h2 id="zero-shot-cot">Zero-shot CoT&lt;/h2>
&lt;p>文中的Zero-shot CoT默认设置为&amp;quot;Let’s think step by step&amp;quot;，作者在本文探究其与&amp;quot;Let’s think step by step, you must think more steps&amp;quot;对llm的影响。&lt;/p>
&lt;h2 id="few-shot-cot">Few-shot CoT&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709036168663.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示，在本文的Few-shot Cot被设置为了如下的几个步骤：&lt;/p>
&lt;ol>
&lt;li>Think About The Word： 作者首先让LLM思考问题中单词的意义（想好每个词啥意思再回答）。比如说对于问题&amp;quot;Could someone in Tokyo take a taxi to the Metropolitan Museum of Art?&amp;quot;，如下图所示，作者会让LLM先想一想&amp;quot;Tokyo&amp;quot;, &amp;ldquo;taking a taxi&amp;rdquo;, &amp;ldquo;Metropolitan Museum of Art&amp;rdquo; 都是什么意思——&amp;ldquo;Think about Tokyo&amp;hellip; Think about taking a taxi&amp;hellip; Think about Metropolitan Museum of Art&amp;hellip;&amp;quot;。&lt;/li>
&lt;/ol>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709038629109.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;ol start="2">
&lt;li>
&lt;p>Read the question again：让LLM重读一遍问题（再审一遍题）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Repeat State：让LLM对问题形成一个摘要，简化记忆，减少CoT中的其他单词的影响（提取问题中的关键信息）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Self-Verificatio：增加了一个自我验证过程，根据一些基本信息来判断答案是否合理。（先自己想一下你的回答对不对）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Make Equation：对于数学问题，让LLM对问题进行建模&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="实验及结论">实验及结论&lt;/h1>
&lt;h2 id="步数与准确率的关系">步数与准确率的关系&lt;/h2>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709038719656.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示，每张子图的x轴为CoT链条的长度(推理步数)，y轴为LLM的准确率。显然，&lt;strong>CoT链条越长，准确率越高&lt;/strong>。这一发现横跨所有的数据集和任务。&lt;/p>
&lt;h2 id="cot中一个环节推错了会发生什么">CoT中一个环节推错了，会发生什么？&lt;/h2>
&lt;p>对于CoT的研究者而言，最重要的研究莫过于如何让CoT的每一步都推对，从而接近正确的答案。在这一章节，作者提出问题，如果CoT中某一链推错了，对LLM推出结果会产生什么影响呢？&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709038869996.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如下图所示，x轴表示8类任务/数据集，两个颜色的柱状图分别表示全对的链条和包含错误回答的链条。作者发现：&lt;/p>
&lt;ol>
&lt;li>对于数学问题，某一环节错了，影响很小。作者认为llm学习的是计算模式而不是计算的结果本身，因此不受影响。例子如下图所示，本图中，右侧的错误prompt将&lt;code>10+8&lt;/code>的结果计算为了错误的&lt;code>48&lt;/code>。&lt;/li>
&lt;li>对于逻辑问题，错一点会导致思维链破裂，影响很大。&lt;/li>
&lt;/ol>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709039099537.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;h2 id="压缩推理步骤会发生什么">压缩推理步骤，会发生什么？&lt;/h2>
&lt;p>这里的压缩推理步骤指的是在每个步骤，用更简短的语言来提问。结果表明压缩推理步骤导致其性能接近Zero-shot，进一步说明推理步骤和LLM的准确率重要关联。&lt;/p>
&lt;h2 id="模型的参数量对结果的影响">模型的参数量对结果的影响&lt;/h2>
&lt;p>如下图，显而易见，参数量越大越准确。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709039362935.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;h2 id="不同的cot生成方法区别大吗">不同的CoT生成方法区别大吗？&lt;/h2>
&lt;p>由于本文主要研究推理步骤对性能的影响，因此需要确认CoT中问题本身对LLM的性能没有影响。&lt;/p>
&lt;p>因此，本文在LLM为GPT-3.5-turbo-1106的设置下，选择了两个数据集（MultiArith和GSM8K）和两种CoT方法（Auto CoT和Few-shot CoT）进行这项研究。&lt;/p>
&lt;p>如下图所示，初步观察表明，这些修改对性能的影响微乎其微。 这一初步发现表明，在推理过程中，步骤的长度，而不是问题本身的性质，主要影响大型模型的推理能力。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1709039615751.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;h1 id="评价">评价&lt;/h1>
&lt;p>本文虽然难度不大，但是对CoT的评测却很全面，角度很新奇，也发现了很多有意思的结论。&lt;/p></description></item><item><title>Frequency-Importance Gaussian Splatting for Real-Time Lightweight Radiance Field Rendering</title><link>https://geyuyao.com/publication/chen2024gaussian/</link><pubDate>Wed, 21 Feb 2024 19:00:00 +0000</pubDate><guid>https://geyuyao.com/publication/chen2024gaussian/</guid><description>&lt;h2 id="abstract">Abstract:&lt;/h2>
&lt;p>Recently, there have been significant developments in the realm of novel view synthesis relying on radiance fields. By incorporating the Splatting technique, a new approach named Gaussian Splatting has achieved superior rendering quality and real-time performance. However, the training process of the approach incurs significant performance overhead, and the model obtained from training is very large. To address these challenges, we improve Gaussian Splatting and propose Frequency-Importance Gaussian Splatting. Our method reduces the performance overhead by extracting the frequency features of the scene. First, we analyze the advantages and limitations of the spatial sampling strategy of the Gaussian Splatting method from the perspective of sampling theory. Second, we design the Enhanced Gaussian to more effectively express the high-frequency information, while reducing the performance overhead. Third, we construct a frequency-sensitive loss function to enhance the network&amp;rsquo;s ability to perceive the frequency domain and optimize the spatial structure of the scene. Finally, we propose a Dynamically Adaptive Density Control Strategy based on the degree of reconstruction of the background of the scene, which adaptive the spatial sample point generation strategy dynamically according to the training results and prevents the generation of redundant data in the model. We conducted experiments on several commonly used datasets, and the results show that our method has significant advantages over the original method in terms of memory overhead and storage usage and can maintain the image quality of the original method.&lt;/p></description></item><item><title>论文解读 | 大模型的涌现是幻影</title><link>https://geyuyao.com/post/emergent-abilities-mirage/</link><pubDate>Sat, 16 Dec 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/emergent-abilities-mirage/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Are Emergent Abilities of Large Language Models a Mirage?&lt;/p>
&lt;p>&lt;strong>Institution:&lt;/strong> Computer Science, Stanford University&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Rylan Schaeffer, Brando Miranda, Sanmi Koyejo&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2304.15004" target="_blank" rel="noopener">https://arxiv.org/abs/2304.15004&lt;/a>&lt;/p>
&lt;p>&lt;strong>Comments:&lt;/strong> NeurIPS 2023&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2023.04.28&lt;/p>
&lt;h1 id="前言">前言&lt;/h1>
&lt;p>本文于2023.04.28在Arxiv上发布。前后两版，在NeurIPS 2023会议上获得了主会场最佳论文奖（2/3584）。&lt;/p>
&lt;h1 id="涌现现象-emergent-ability">涌现现象 (Emergent ability)&lt;/h1>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="0.jpg">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">图 1&lt;/div>
&lt;/center>
&lt;p>文章称有许多工作生成大型语言模型显示出涌现的能力，而这些能力在较小规模的模型中不存在，但在较大规模的模型中却存在，这就是人们常说的Emergent ability即涌现。&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;emergent ability&amp;rdquo;（涌现能力）指的是当模型变得足够大时，它能展现出之前小模型所没有的新能力或行为，如某些性能指标陡然上升。&lt;/p>
&lt;/blockquote>
&lt;p>如上图所示，以LaMDA、GPT-3等系列模型为例，随着模型参数量的增加，当参数量达到某一临界点时，Accuracy陡然增加，这就是涌现。&lt;/p>
&lt;p>Emergent ability有两个特点：&lt;/p>
&lt;ul>
&lt;li>Sharpness：随着参数量的线性增加，陡然上升&lt;/li>
&lt;li>Unpredictability：在某个不确定的临界参数量突然出现&lt;/li>
&lt;/ul>
&lt;h1 id="涌现是否真的存在">涌现是否真的存在？&lt;/h1>
&lt;p>先说结论，本文揭示了大模型并不存在「涌现」，大模型的能力随着参数的增长是线性增长的。&lt;/p>
&lt;p>产生涌现的真相是：涌现的出现并不是因为模型参数量的上升，而是因为研究者选择的度量指标导致的假象。&lt;/p>
&lt;p>作者的出发点在于，前人度量模型能力的指标是离散的，而非线性的，会出现Emergent ability。然而，如果使用线性的或者连续的度量方式，模型的能力会不会是平滑、连续、可预测的呢？&lt;/p>
&lt;h1 id="emergent-abilities的解释">Emergent Abilities的解释&lt;/h1>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">图 2&lt;/div>
&lt;/center >
&lt;p>作者首先自问自答，如何让模型性能中平滑、连续、可预测的变化显得陡然变化且不可预测？答案是，研究人员对非线性或不连续度量方式的选择可能会扭曲模型的性能表现，使其看起来陡然变化而不可预测。&lt;/p>
&lt;p>过去的经验表明，神经网络的能力与训练数据及大小、参数量、耗费的计算资源成一定比例。根据这个经验，我们首先假设下式是正确的 &lt;strong>(图 2.A)&lt;/strong> ：
$$
\mathcal{L}_{CE}(N)=\left(\frac Nc\right)^\alpha
$$
其中，$L_CE$表示交叉熵，$N$表示参数量，$c&amp;gt;0$和$\alpha&amp;lt;0$为常数。
在实际应用中，交叉熵的定义为：
$$
\mathcal{L}_{CE}(N)\overset{\mathrm{def}}{\operatorname*{=}}-\sum_{v\in V}p(v)\log\hat{p}_N(v)
$$
此公式衡量的是模型对整个词汇表
$V$的预测分布
$\hat{p}_N$真实分布
$p$之间的差异。对于每个可能的token $v$，真实分布$p(v)$表示token $v$出现的真实概率，而$\hat{p}_N(v)$是模型预测token $v$出现的概率。&lt;/p>
&lt;p>由于
$p(v) = 0$对于所有
$v \neq v^*$，和
$p(v^*) = 1$，只有
$v = v^*$的项在求和中保留，公式简化为：&lt;/p>
&lt;p>$$
\mathcal{L}_{CE}(N)=-\log\hat{p}_N(v^*)
$$&lt;/p>
&lt;p>每个token被正确预测的概率为 &lt;strong>(图 2.B)&lt;/strong> :
$$
\begin{align*}
p(\text{single token correct})&amp; =\exp\left(-\mathcal{L}_{CE}(N)\right)\\ &amp; =\exp\left(-(N/c)^\alpha\right)
\end{align*}
$$
假设研究人员随后选择了需要正确选择$L$个token的度量方法。例如，任务可能是$L$位数整数加法，如果模型的所有$L$个输出数字完全与所有目标数字匹配，没有增加、删除或替换，就得分为$1$，否则得分为$0$。如果每个标记正确的概率是独立的，那么得分为$1$的概率为：
$$
\begin{align*}
\operatorname{Accuracy}(N) &amp;\approx p_N\left(\text{single token correct}\right)^\text{num. of tokens} \\
&amp;= \exp\left(-(N/c)^\alpha\right)^L
\end{align*}
$$
&lt;/p>
&lt;blockquote>
$$\text{Exact String Match}\stackrel{\text{def}}{=}\begin{cases}1&amp;\text{if output string exactly matches target string}\\0&amp;\text{otherwise}\end{cases}$$
&lt;/blockquote>
&lt;p>这种度量方法的选择会使得性能随着标记序列长度的增加而非线性缩放。当在linear-log图上绘制性能时 &lt;strong>(图 2.C)&lt;/strong>，可以看到更长序列上出现了陡然上升、不可预测的突变，这与其他学者所声称的涌现能力非常吻合。&lt;/p>
&lt;p>而如果使用线性的度量方式Token Edit Distance又会出现什么呢？
$$
\begin{aligned}
\text{Token Edit Distance}(N) &amp;\approx L(1-p_N(\text{single token correct})) \\
&amp;= L\left(1-\exp\left(-(N/c)^\alpha\right)\right)
\end{aligned}
$$
当使用线性的度量指标Token Edit Distance来衡量模型的能力时，模型的能力变得平滑、连续、可预测 &lt;strong>(图 2.E)&lt;/strong>。&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;标记编辑距离&amp;rdquo;（Token Edit Distance）是一种度量两个序列差异的方法。它计算的是将一个序列转换成另一个序列所需的最小编辑操作数，这些操作包括插入、删除和替换单个标记。在这里的上下文中，一个&amp;quot;标记&amp;quot;（token）通常指的是一个词、字符或者其他的语言单位。&lt;/p>
&lt;p>举例来说，如果我们有两个词序列，序列A是“cat”而序列B是“bat”，那么序列A变为序列B的标记编辑距离是1，因为只需将“c”替换为“b”即可。&lt;/p>
&lt;/blockquote>
&lt;p>如果使用离散的度量指标Multiple Choice Grade，则会观察到涌现现象 &lt;strong>(图 2.D)&lt;/strong>，但是如果使用连续度量指标Brier Score，涌现现象则会消失 &lt;strong>(图 2.F)&lt;/strong>。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Multiple Choice Grade：&lt;/strong>&lt;/p>
$$\\ \text{Multiple Choice Grade}\stackrel{\text{def}}{=}\begin{cases}1&amp;\text{if highest probability mass on correct option}\\0&amp;\text{otherwise}\end{cases}$$
&lt;p>&lt;strong>Brier Score：&lt;/strong>
$$ BS = \frac{1}{N} \sum_{i=1}^{N} (f_i - o_i)^2$$
其中：&lt;/p>
&lt;ul>
&lt;li>$N$ 是预测的数量。&lt;/li>
&lt;li>$f_i$是第$i$个预测的发生概率（模型预测的概率）。&lt;/li>
&lt;li>$o_i$是第$i$个实际发生结果的观察值（通常用1表示事件发生，用0表示未发生）。&lt;/li>
&lt;/ul>
&lt;p>举例来讲，假设你正在预测一个足球比赛是否会打平。对于三场比赛，你的模型预测打平的概率分别为0.3、0.6和0.2。实际结果是第一场比赛打平了（1），而第二场和第三场没有（0）。&lt;/p>
&lt;p>那么，Brier Score将计算如下：&lt;/p>
&lt;ul>
&lt;li>对于第一场比赛，预测误差为 $ (0.3 - 1)^2 = 0.49 $。&lt;/li>
&lt;li>对于第二场比赛，预测误差为 $ (0.6 - 0)^2 = 0.36 $。&lt;/li>
&lt;li>对于第三场比赛，预测误差为 $ (0.2 - 0)^2 = 0.04 $。
Brier Score是这些误差的平均值，所以在这个例子中，Brier Score为 $ \frac{0.49 + 0.36 + 0.04}{3} = 0.2967 $。&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>总结来讲，造成涌现现象的假象有两点&lt;/p>
&lt;ol>
&lt;li>前人采取的度量标准是离散的而非连续的或线性的，从而导致出现涌现现象的出现。&lt;/li>
&lt;li>前人只在模型参数量的小范围内进行实验。具体而言，一般模型的大小有6b，7b，13b，33b，70b等，这些模型参数量只覆盖了很小的一部分范围。如果有6b，6.1b，6.2b，6.3b&amp;hellip;70.1b，70.2b等大小人们就会观察到离散的度量标准与模型参数量间呈指数关系，而不是突变关系。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>本文作为NeurIPS 2023的Best paper可谓实至名归，虽然研究基于简单的出发点，但论文提出了有深远影响的见解，极富创造性和启示价值。在本文发表之前，涌现现象一度成为业内公认的“神奇现象”，关于此现象的研究开展了很多包括使用探针进行实验等，但本文在此情况下从细节入手，揭示“涌现”其实不存在令包括笔者在内的许多研究者醍醐灌顶。&lt;/p></description></item><item><title>我们该如何监督比人类更强的AI？ | Weak-to-strong generalization</title><link>https://geyuyao.com/post/weak-to-strong-generalization/</link><pubDate>Fri, 15 Dec 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/weak-to-strong-generalization/</guid><description>&lt;h1 id="前言">前言&lt;/h1>
&lt;p>2023.12.14 OpenAI发布了文章&lt;a href="https://cdn.openai.com/papers/weak-to-strong-generalization.pdf" target="_blank" rel="noopener">WEAK-TO-STRONG GENERALIZATION: ELICITING STRONG CAPABILITIES WITH WEAK SUPERVISION&lt;/a>，同时在OpenAI的网站上也发布了对应的博客&lt;a href="https://openai.com/research/weak-to-strong-generalization" target="_blank" rel="noopener">Weak-to-strong generalization&lt;/a>。笔者在本文对文章Weak-to-strong generalization进行浅析。&lt;/p>
&lt;p>文章中提到：如今AI的能力越来越强，接近甚至已经超越人类的能力，人类已经很难监督这类超人AI了。那么该如何监督比人类更强大的超人AI呢？&lt;/p>
&lt;p>研究团队通过一个简单的Demo来研究这个问题，他们发现可以使用GPT-2级别的模型来激发出GPT-4大部分的能力，使得其接近GPT-3.5的能力，即使在小模型失败的困难问题上也能正确泛化。&lt;/p>
&lt;p>&lt;strong>这可能是一个新的研究领域。&lt;/strong>&lt;/p>
&lt;h1 id="问题">问题&lt;/h1>
&lt;p>作者团队相信，超级人工智能可能在未来十年之内发展起来。然而目前人类对AI系统的认识太过肤浅，以至于不知道如何可靠地引导和控制超人工智能，这对人类来说是很危险的。&lt;/p>
&lt;p>试想，如果人类利用一个强人工智能撰写了十几万行代码，并投入生产环境使用，而一旦这些代码中潜藏着危险的代码，就会导致严重的后果。&lt;/p>
&lt;p>在上述例子中，人类处于弱监督者的位置，而AI处于超人AI的地位。核心问题在于：如何让一个不聪明的弱监督者监督一个聪明的超人AI呢？&lt;/p>
&lt;h1 id="方法">方法&lt;/h1>
&lt;p>作者团队提出的方法是：可以利用一个弱AI来监督一个强AI。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/weak-to-strong-generalization/1702645780054_hu5b6f9922a5becdaaad625fa8110ccc61_132830_0679e88fbd12bb1f182ad9da9b4dabe2.webp 400w,
/post/weak-to-strong-generalization/1702645780054_hu5b6f9922a5becdaaad625fa8110ccc61_132830_22a5437be490ce65edbf2b10a752aa22.webp 760w,
/post/weak-to-strong-generalization/1702645780054_hu5b6f9922a5becdaaad625fa8110ccc61_132830_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/weak-to-strong-generalization/1702645780054_hu5b6f9922a5becdaaad625fa8110ccc61_132830_0679e88fbd12bb1f182ad9da9b4dabe2.webp"
width="760"
height="385"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>如上图所示，最左侧子图表示传统机器学习，即人类作为监督者监督弱人工智能；中间子图表明，人类如今需要监督比自己更加强大的AI，这对人类来说是困难的；右侧子图表明在作者团队的实验中，作者使用一个弱的AI来监督一个相对较强的AI。&lt;/p>
&lt;p>一方面，从直觉上来看，我们并不会期望一个强大的AI经过一个弱的AI监督之后，表现得比弱AI更好。因为弱AI可能会误导强AI。但是从另一方面讲，强AI经过预训练后，本身具备非常强大的基本能力和性能。我们只需要使用弱AI来激发出强AI潜在的知识。&lt;/p>
&lt;p>那么问题来了，强AI是会被弱AI激发，从而发挥它的全部潜力；还是会被弱AI提供的不完整或有缺陷的标签所误导，导致性能更差？&lt;/p>
&lt;blockquote>
&lt;p>注意，上文中的强AI指的是经过预训练但是没有进行任务微调的模型。&lt;/p>
&lt;/blockquote>
&lt;h1 id="结果及结论">结果及结论&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/weak-to-strong-generalization/1702646606737_hu1f7243db76b2fb04624975d990057391_6360_5f20de7855fcc698baab8ad3a8b16b29.webp 400w,
/post/weak-to-strong-generalization/1702646606737_hu1f7243db76b2fb04624975d990057391_6360_ecf7849fc06b2d714acade0c74547385.webp 760w,
/post/weak-to-strong-generalization/1702646606737_hu1f7243db76b2fb04624975d990057391_6360_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/weak-to-strong-generalization/1702646606737_hu1f7243db76b2fb04624975d990057391_6360_5f20de7855fcc698baab8ad3a8b16b29.webp"
width="732"
height="381"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>如上图所示，使用GPT-2（弱AI）监督的GPT4（强AI，未经微调）可以达到接近GPT3.5的水平。作者团队使用了较弱的监督，就可以激发GPT4大部分的能力。&lt;/p>
&lt;p>尽管此实验较为简单，但意味着此方法在实践上是初步可行的。此外，作者还是在其他方法中看到了积极的迹象，如bootstrapping和optimal early stopping似乎显示出了潜力。&lt;/p>
&lt;ol>
&lt;li>简单的人类监督如RLHF——在没有进一步工作的情况下，可能难以扩展到超人AI&lt;/li>
&lt;li>weak-to-strong generalization是可行的&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>此项研究很有创新性和启发性，人们总是在思考如何提高AI的能力，但是却鲜有人考虑当AI超越人类之后该如何监督超人AI。正如文中提到的 &lt;em>“This opens up a new research direction that allows us to directly tackle a central challenge of aligning future superhuman models while making iterative empirical progress today.”&lt;/em> 这是一个新的领域，有许多的low hanging fruit等待着学者们去探索。&lt;/p></description></item><item><title>启发式最短路算法</title><link>https://geyuyao.com/post/heuristic-shortest-path/</link><pubDate>Tue, 05 Dec 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/heuristic-shortest-path/</guid><description>&lt;h1 id="前言">前言&lt;/h1>
&lt;p>由于笔者最近开展LLM enhance Graph相关的工作，因此对图上的启发式算法产生了一定的兴趣。通过搜索引擎发现了这篇发表于2006年的综述性论文。尽管文章的发表时间比较久远，但是一来最短路算法在近20年并不是热门研究领域因此新工作很少，二来最近很多LLM Reasoning方向的论文的灵感都来源于传统算法，因此在此对该文章进行提炼和总结。&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>尽管标准的最短路最优算法已经可以解决大部分的最短路问题，但是在大规模图、低时延的任务中标准最短路算法往往不能满足任务的需求。例如，在车载路线导航系统，需要立即响应。而在这些任务中，一些任务对结果的要求不一定是“最优的”，而是“较优的”，因此启发式最短路算法应运而生。&lt;/p>
&lt;p>在过去的六十年间，有学者提出了许多启发式方法来减少最短路径算法的计算时间。本文对过去开发的各种启发式最短路径算法进行了调查和回顾。&lt;/p>
&lt;h1 id="最短路问题及最优算法">最短路问题及最优算法&lt;/h1>
&lt;p>设有向图为$G(N,A)$构成，图中有$N$个顶点，$A$条有向边。$n = |N|$表示顶点的个数，$m = |A|$表示边的个数。$a=(i,j)\in A$表示一条从$i$到$j$的有向边，$c_{i,j}$ 表示从$i$到$j$的代价。一条从起点$o$到终点$d$的路径可被定义为$path = (o,j),\ldots,(i,d)$，其代价为每一条边的代价的总和$cost_{path} = \sum_{(i,j)\in path} c_{i,j}$。最短路径问题就是找到使$cost$最小的路径
$path = {\arg \min}_{path \in \text{all paths}} (cost_{path})$。&lt;/p>
&lt;h2 id="最优算法">最优算法&lt;/h2>
&lt;p>这个最短路径问题(SPP)已经在不同的领域研究了 40 多年，如计算机科学和交通。由于它们的计算可操作性，这一领域的大多数研究都集中在开发日益高效的最优算法来解决该问题。大多数最优最短路径算法本质上是动态规划理论在图中搜索最短路径方面的应用。最短路径是通过从源节点到目的节点的递归决策过程来找到的。&lt;/p>
&lt;p>大多数最短路径算法都遵循下面这样一个标准程序：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>初始化：&lt;/p>
$\begin{array}{l}i=o;L_{(i)}=0;L_{(j)}=\infty;\forall j\neq i;P_{(i)}=\text{NULL.}\\Q=\{i\};\end{array}$
&lt;/li>
&lt;li>
&lt;p>节点选择：&lt;/p>
&lt;p>选择并从$Q$中删除节点$i$&lt;/p>
&lt;/li>
&lt;li>
&lt;p>扩充节点&lt;/p>
&lt;p>扫描从$i$出发的边. 对于边 $\alpha=(i,j)$ 如果
$L_{(i)}+c_{a}&amp;lt;L_{(j)}$
则
$L_{(j)}=L_{(i)}+c_{a};P_{(j)}=a$
将$j$插入集合$Q$&lt;/p>
&lt;/li>
&lt;li>
&lt;p>停止检查&lt;/p>
&lt;p>如何$Q = \emptyset $则停止，反之，重复Step 2&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>其中，从原节点$o$到节点$i$的代价被定义为$L(i)$，$P$表示存储到每个节点的最短路径树上来自的边的列表，$P(i)$表示到节点$i$的最短路径上的来自的边，$Q$表示待扫描的节点集，它管理着搜索过程中要检查的节点。&lt;/p>
&lt;h3 id="label-setting-algorithm-ls">Label-setting algorithm (LS)&lt;/h3>
&lt;p>$Q$中的元素根据当前的代价进行排序&lt;/p>
&lt;p>它的一个显著特点是，如果只需要从起始节点到单个目的地节点的路径，当目的地节点的代价被计算出来时，算法就可以终止。这种类型的操作通常被称为一对一搜索模式。&lt;/p>
&lt;p>如dijkstra。&lt;/p>
&lt;h3 id="label-correcting-algorithm-lc">Label-correcting algorithm (LC)&lt;/h3>
&lt;p>$Q$中的元素在最短路径树构建的过程中被填充和扫描。&lt;/p>
&lt;p>它的特点是，在确定到网络中每个节点的最短路径之前，它不能提供两个节点之间的最短路径，称为一对多搜索模式。&lt;/p>
&lt;p>如Bellman-Ford、SPFA。&lt;/p>
&lt;h2 id="计算性能">计算性能&lt;/h2>
&lt;p>在 LC 算法中，双端队列（double ended queue）和阈值列表结构（threshold list data structures）在计算效率方面占主导地位。&lt;/p>
&lt;p>在 LS 算法中，Dial的桶实现（Dial’s bucket implementation）和二进制堆结构（binary heap data structure）是最有效的。&lt;/p>
&lt;h1 id="启发式最短路算法">启发式最短路算法&lt;/h1>
&lt;p>在上文中讨论的最优最短路径算法，对于现实中的实时问题来说，计算量往往太大。&lt;/p>
&lt;p>这种“低效”源于这样一个事实：这些算法采用了“无信息量”的向外搜索技术，没有利用关于起点和 终点节点的位置、路径组成和网络结构的先验知识。&lt;/p>
&lt;p>例如，如果起始节点位于城市中心，而目的节点位于城南，那么优化算法搜索原点节点以北的最小路径路线的可能性与搜索原点节点以南的可能性相同。&lt;/p>
&lt;p>直观地说，如果在搜索过程中使用更多的信息，算法的效率就可以提高。后一点很早就被 AI 领域的研究人员认识到，并提出了许多启发式方法，试图使用各种额外知识来源来减少搜索工作。&lt;/p>
&lt;p>启发式搜索策略一般可以分为四种策略：&lt;/p>
&lt;ol>
&lt;li>限制搜索区域（Limit the search area）&lt;/li>
&lt;li>分解搜索问题（decompose the search problem）&lt;/li>
&lt;li>限制搜索的边（limit the links searched）&lt;/li>
&lt;li>上述的某种组合&lt;/li>
&lt;/ol>
&lt;p>接下来，我们将研究这些启发式搜索策略及其在最短路径搜索中的应用。&lt;/p>
&lt;h2 id="限制搜索区域">限制搜索区域&lt;/h2>
&lt;p>“限制搜索区域”策略背后的思想是利用一些关于从原点节点到目的节点的最短路径的先验知识，将最短路径搜索限制在一定的区域内。&lt;/p>
&lt;p>由此产生的搜索区域将比无先验知识的最优算法的搜索区域小得多。&lt;/p>
&lt;h3 id="剪枝">剪枝&lt;/h3>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701861151889.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>此基本思想试图通过“修剪”那些几乎不可能到达目标节点的最短路径上的中间节点来限制搜索区域。&lt;/p>
&lt;p>在经典的城市交通网络中，每个路段(或路段)通常只与相邻节点(如路口)相连，路段上的旅行时间通常与其长度相关。这个性质使搜索区域被限制在原点节点和终点节点周围的指定区域内。这个区域之外的节点被假定在最短路径上的概率很小，因此在搜索过程中无需进一步检查就可以被排除。&lt;/p>
&lt;p>问题的关键在于定义搜索区域，这样可以有效地减少计算时间，同时获得一个好的解决方案。&lt;/p>
&lt;p>有学者提出使用下式约束搜索范围：
$$
L_{(i)}+e_{(i,d)}\leqslant E_{(o,d)},
$$
其中，$L(i)$是当前从原点节点 $o$ 到节点 $i$的最小代价；$e(i,d)$表示节点$i$到目的节点$d$的预计代价；$E(o,d)$表示从起点节点到目的节点的最小代价的上界。&lt;/p>
&lt;p>将该方法加入到LC最优算法的过程中只需要对Step 2进行修改&lt;/p>
&lt;ol start="2">
&lt;li>选择并从$Q$中删除节点$i$。如果$L_{(i)}+e_{(i,d)}\leqslant E_{(o,d)}$则跳到第四步。&lt;/li>
&lt;/ol>
&lt;p>分支修剪算法的效率如上图所示。可以看出新的启发式策略将搜索区域从最优 LS 算法展开的圆缩小到椭圆。在理想的欧几里得网格中，这些启发式算法的搜索区域可能小到LS 算法的搜索区域的20%。&lt;/p>
&lt;p>分支剪枝最短路径算法的效率和精度取决于估计函数$e(i,d)$和 $E(o ,d )$的质量。易见，只有当估计$e(i,d )$始终低于从节点$ i $到目的节点$ d $的最小代价，同时$E(o ,d)$的估测值大于从原点节点$ o $到目的节点$ d $的最小代价时，剪枝算法的最优性才会保留。此外，可以注意到，当$e(i,d )$趋近于零、 $E(o,d )$趋近于无穷时，分支剪枝算法将成为最优最短路径算法。&lt;/p>
&lt;p>简而言之，使用上述方法时，$e$要往小估，$E$要往大估。&lt;/p>
&lt;h3 id="a">A*&lt;/h3>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701862771059.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>在剪枝方法中，具有低概率在最短路径上的节点被修剪。而A*算法将这些节点保持在$Q$中，但给它们分配低优先级。&lt;/p>
&lt;p>A*算法利用了一个启发式的评估函数$F_{(i)}=L_{(i)}+e_{(i,d)}$作为节点$i $的标签，其中$ L(i)$是当前评估路径从原点节点到节点$ i $的代价，$e(i,d)$是从节点$ i $到目的节点$ d $的估计代价。两个函数的和$F$反映了$i$在最短路上的可能性。$F$越高，$i$越可能出现在最短路上。基于这个思路，该算法执行了一种最优先搜索，即它维护一个按照它们的$F$值排序的节点列表$Q$以供扫描，并选择一个$F$值最低的节点进行扩展。被选中的节点通过访问它的邻接点来扩展，根据邻接点的$F$值，将邻接点有序放入$Q$中。这一过程持续进行，直到选择目的节点进行扩展。因此，A*算法与LS算法有相似之处。&lt;/p>
&lt;blockquote>
&lt;p>此处推荐一个了解A*算法的文章，逻辑清晰且提供了交互页面：https://www.redblobgames.com/pathfinding/a-star/introduction.html&lt;/p>
&lt;/blockquote>
&lt;p>与LS算法相比，A*使用评估函数是$F(i)$来确定$Q$中的节点顺序而不是$ L ( i)$。&lt;/p>
&lt;p>主要的区别在于Step 3，修改如下:&lt;/p>
&lt;ol start="3">
&lt;li>
&lt;p>扩充节点&lt;/p>
&lt;p>扫描从$i$出发的边。对于边 $\alpha=(i,j)$ 如果&lt;/p>
&lt;p>$L_{(i)}+c_{ij}+e_{(j,d)}&amp;lt;F_{(j)},$&lt;/p>
&lt;p>则&lt;/p>
&lt;p>$\begin{array}{l}L_{(j)}=L_{(i)}+c_{ij};F_{(j)}=L_{(i)}+c_{ij}+e_{(i,d)};P_{(j)}=a,\end{array}$&lt;/p>
&lt;p>将$j$插入集合$Q$&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>由于A*算法基于最优优先思想，因此满足以下不等式的节点将在算法终止之前被扫描
$$
L_{(i)}+e_{(i,d)}\leqslant L_{(d)}.
$$
因此，只要估计函数不要高估代价，就可以找到最优解。&lt;/p>
&lt;h2 id="分解搜索问题">分解搜索问题&lt;/h2>
&lt;p>人们普遍认识到，解决一个通用搜索问题所需的计算量通常比问题本身的规模增长得更快。例如，从一个起始节点到一个目标节点找到最短路径所需要的计算时间取决于在到达目标节点之前搜索的节点数，因此计算量是距离的高阶多项式函数。因此，如果原始问题可以分解为更小的子问题，就可以大量降低复杂度。&lt;/p>
&lt;p>本节介绍了如何使用双向搜索方法和子目标方法来实现这种策略。&lt;/p>
&lt;h3 id="双向搜索策略">双向搜索策略&lt;/h3>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701863759361.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>双向搜索策略试图将搜索过程划分为两个独立的过程。一个从起始点向前推进，另一个从结尾向回推进。当这两个搜索过程在某个中间阶段相遇时，就找到了解决方案。&lt;/p>
&lt;p>如上图所示，该算法将同时从起点和终点向外构建最短路径树，直到满足某种停止条件为止。&lt;/p>
&lt;p>双向算法的效果受两个因素影响。&lt;/p>
&lt;ol>
&lt;li>前向和后向的算法的交替规则&lt;/li>
&lt;li>算法什么时候停止&lt;/li>
&lt;/ol>
&lt;p>对于前者，最直观的方法是平等交替。然而，平等交替不一定是最高效的。最好的策略应该在扫描最少的节点下找到最短路径。&lt;/p>
&lt;p>对于后者，有学者提出下式：
$$
L_{(i)}^o+L_{(i)}^d\leqslant\min_{j\in N}{L_{(j)}^o}+\min_{j\in N}{L_{(j)}^d}
$$
这个式子的意思反应的是，对于任意节点$j$，从$o$到$j$的最小代价加上从$j$到$d$的最小代价大于等于$o$到$d$经过$i$的最短距离。此时，$i$一定是$o$到$d$的最短路上的一个节点。&lt;/p>
&lt;p>然而聪明的读者很快就会发现，这是一个相当愚蠢的判断标准。&lt;/p>
&lt;p>果不其然，有学者证明，当使用这个停止准则时，由此产生的双向搜索算法不如单向算法。据推测，由双向搜索过程扩展的节点可能在满足条件之前生长成几乎完全的单向树，而不是在起点和终点之间的“中间”相遇。&lt;/p>
&lt;p>后又有多位学者在此基础上进行改进。如使用改变了估计函数的双向A*算法、使用多个相遇的中间节点的双向A*算法等。&lt;/p>
&lt;h3 id="子目标方法">子目标方法&lt;/h3>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701864575057.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>子目标可以定义为问题最优解的中间状态。对于道路交通网络中的最短路径搜索问题，子目标可能是位于起点和终点之间的那些节点或边，需要确定它们之间的最短路径。如果预先知道子目标的位置，那么从起点到终点寻找最短路径的问题可以分解为两个或更多较小的问题。&lt;/p>
&lt;p>例如，如果有一个子目标节点，原始问题可以通过解决两个子问题来解决：一个是找到从起点到子目标节点的最短路径，另一个是找到从子目标节点到终点的最短路径。&lt;/p>
&lt;p>如果已知一个子目标节点，并且位于从起点到终点的最短路径的中间，那么使用这个子目标节点将使搜索区域与LS算法相比减少大约50%，如图上图所示。如果同时使用了限制搜索区域的技术之一，计算节省将会更大。&lt;/p>
&lt;p>此方法可行的原因在于，如果我们已知$i$是从$o$到$d$的最短路上的一个中间节点，那么从$o$到$d$的最短路的代价一定等于从$o$到$i$的最短路的代价加上从$i$到$d$的最短路的代价。&lt;/p>
&lt;h2 id="限制搜索的边">限制搜索的边&lt;/h2>
&lt;p>在最短路径搜索过程中，每次迭代期间的主要决策涉及从每个节点发出的边的扫描。在传统的最短路径算法中，当选择一个节点进行扩展时，将扫描来自该节点的所有边， 无论它们在最短路径上的可能性有多大。&lt;/p>
&lt;p>限制搜索的边的基本思想是跳过对那些要么在最短路径上，要么在实际情况中使用的概率很低的边的检查。通过使用下一节讨论的分层搜索方法，可以有效地实现这一思想。&lt;/p>
&lt;h3 id="分层搜索">分层搜索&lt;/h3>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701865101410.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>分层搜索背后的基本思想是，为了有效地找到一个复杂问题的解，搜索过程首先应集中在问题的本质特征上，而不考虑较低层次的细节，然后再完成细节。&lt;/p>
&lt;p>举例来讲，在驾驶者查找两个地点的路线的问题中，我们先找到需要路径中的主干道，然后再找这些主干道间的小路。通过“先找到需要路径中的主干道”就可以将搜索的范围缩小至所有主干道，而“再找这些主干道间的小路”则将搜索范围缩小至与这些主干道相连的小道。&lt;/p>
&lt;p>此方法有两个问题需要解决&lt;/p>
&lt;ol>
&lt;li>如何将现实道路映射到分层图中？&lt;/li>
&lt;li>如何控制不同层间的转换？什么时候切换到下一个层？&lt;/li>
&lt;/ol>
&lt;p>高速公路和交通大动脉是为长距离运输而设计的，而地方的街道则主要用于当地车辆出行。因此，道路连接可以根据它们的功能方便地分类。有学者提出以边的长度为标准，提取长边形成高层子网络，并将较短的边及其节点分组为低层子网络。又有学者提出根据限速、车道数等属性将所有道路划分为高低两级。&lt;/p>
&lt;p>分层搜索算法的一个问题在于无法在两个主干道间走捷径。比如通过使用住宅区道路从一条主干道转到另一条主干道。分层搜索算法在设计时是为了简化搜索过程，通过将道路分为不同的等级（如高速公路、干道、住宅道路等）来减少需要考虑的道路数量。这种方法通常会首先考虑等级较高的道路（如高速公路），而不是等级较低的道路（如住宅道路）。&lt;/p>
&lt;h1 id="reference">Reference&lt;/h1>
&lt;p>&lt;strong>Title:&lt;/strong> Heuristic shortest path algorithms for transportation applications: State of the art&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> University of Waterloo, Chongqing University, University of Nebraska-Lincoln&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> L. Fua, D. Sunb, L.R. Rilettc&lt;/p>
&lt;p>&lt;strong>DOI:&lt;/strong> &lt;a href="https://doi.org/10.1016/j.cor.2005.03.027" target="_blank" rel="noopener">https://doi.org/10.1016/j.cor.2005.03.027&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2006.11.01&lt;/p></description></item><item><title>次模及其优化问题</title><link>https://geyuyao.com/post/submodular-functions/</link><pubDate>Tue, 28 Nov 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/submodular-functions/</guid><description>&lt;h1 id="前言">前言&lt;/h1>
&lt;p>次模函数（Submodular Functions）是组合优化和离散数学中的一个重要概念，广泛应用于计算机科学、经济学、系统工程等领域。&lt;/p>
&lt;p>例如，在机器学习和数据挖掘中，次模函数用于特征选择、聚类、影响力最大化等问题。具体来讲，选择最能代表数据集的特征子集是一个次模优化问题。次模函数的边际递减性质保证了选择的每个新特征提供的信息量随着已选择特征的增加而递减，帮助避免过拟合。&lt;/p>
&lt;p>又如，在图论中，次模函数用于解决最小割、最大流等问题。网络分析中的影响力最大化问题也是一个典型的次模函数应用，如在社交网络中最大化信息传播。&lt;/p>
&lt;h1 id="from-concavity-to-submodularity">From concavity to submodularity&lt;/h1>
&lt;p>在了解Submodularity之前，我们先来了解一下什么是Controlcavity(由于各文献对该词翻译不一，一说凹面性，一说凸面性，故不做翻译)。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701264966028.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>如上图所示，对于函数$f$，如果$f^{\prime}(\mathbf{x})$是不增的，则$f:\mathbb{R}\to\mathbb{R}$ 是 concave的。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="2228.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>类似的，如上图所示，对任意$i$ ，若$\partial_if(x)=f(x+e_i)-f(x)$是不增的，则$f:{0,1}^n\to\mathbb{R}$是Submodular(次模)的。值得注意的是Submodular function的定义域是离散。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701265745802.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
有了个这个认识之后，接下来给出次模的两个定义：
&lt;ol>
&lt;li>
&lt;p>如上图所示$S\subset T,j\notin T$，若$f$满足
$$
f(S \cup \{j\}) - f(S) \geq f(T \cup \{j\}) - f(T)
$$
则称$f$是submodular的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>若$f:2^{[n]}\to\mathbb{R}$满足对任意$S$，$T$满足下式，则$f$是submodular的。
$$
f(S\cup T)+f(S\cap T)\leq f(S)+f(T).
$$
也就是说，对于任何两个嵌套的子集(例如,$A\subset B$), 向A和B中添加同一个新元素，A的增益至少与B的增益一样大。这反映了一种“边际递减”的特性。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>次模函数可以用来描述诸如“越多越便宜”或“规模经济”这样的现象。例如，考虑一个购物场景，购买第一个商品可能带来较大的满足感，但随着购买的商品数量增加，每增加一个商品带来的额外满足感会逐渐减少。&lt;/p>
&lt;h1 id="optimization-of-submodular-function">Optimization of Submodular Function&lt;/h1>
&lt;p>对于一个次模函数，如何求它的最大值和最小值？&lt;/p>
&lt;h2 id="lovász-extension">Lovász extension&lt;/h2>
&lt;p>前人(Grötschel-Lovász-Schrijver, 1981; Iwata-Fleischer-Fujishige / Schrijver, 2000)利用&lt;strong>Lovász扩展&lt;/strong>可以在多项式时间内解决任何次模函数$f:{0,1}^n\to\mathbb{R}$的最小化问题。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701307156462.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>通过Lovász扩展，次模函数( f )可以转化为一个convex function $ f^L $。
$$
f^L(x) = \mathbb{E}_{\lambda\in[0,1]}[f(\{i : x_i > \lambda\})]
$$
转化之后的$f^L$由于在连续的定义域上，因此可以轻松的求出最小值。而$f^L(x) $的最小化值可以转换为$f(S) $的最小化值。&lt;/p>
&lt;p>通过这种方式，次模函数的最小化问题转化为convex optimization问题得以解决。&lt;/p>
&lt;h2 id="greedy">Greedy&lt;/h2>
&lt;p>回想上文子模函数的定义，在直觉上它与concave functio很相似，但实际上子模函数的最大化是一个典型的NP-hard问题！(实际问题有Max Cut和Max Coverage问题)&lt;/p>
&lt;blockquote>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="2228.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
类似的，如上图所示，对任意$i$ ，离散导数$\partial_if(x)=f(x+e_i)-f(x)$是不增的，则$f:\{0,1\}^n\to\mathbb{R}$是submodular(次模)的。
&lt;p>有关P, NP, NPC, NP-hard的内容详见 &lt;a href="http://www.matrix67.com/blog/archives/105" target="_blank" rel="noopener">http://www.matrix67.com/blog/archives/105&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701312231714.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>至此，问题无法解决了吗？其实不然，即使无法完全求出子模函数的最大值，如果可以求出最优解的近似值也是可以接受的。&lt;/p>
&lt;p>首先我们对问题进行定义：
$$
\max_{S\subseteq\mathcal{V},S\in\mathcal{I}}f(S),S\subset T\Rightarrow f(S)\leq f(T)
$$
其中 $f(\cdot)$ 是定义在数据集 $\nu$ 上的次模函数，$\mathcal{I}$ 是依赖于具体场景的约束(很多时候可能不能选全集)。值得注意的是，&lt;strong>这次我们限制了$f$是单调递增的&lt;/strong>。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701308842950_1.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>对于此问题，可以使用贪心的思想来求解。每次选择一个可以最大化收益的元素加入集合$S$中。即确保元素$i$，使得$ f(S+i)-f(S)$最大，同时确保$S$保持在可行域$\mathcal{I}$中。&lt;/p>
&lt;p>Nemhauser, Wolsey, Fisher在1978年的定理指出，如果$f$是单调且次模的，则贪心算法找到的解至少为问题$\max_{S\subseteq\mathcal{V},S\in\mathcal{I}}:|S| ≤ k$最优解的$ (1 - 1/e) $倍。&lt;/p>
&lt;blockquote>
&lt;p>Nemhauser,Wolsey,Fisher ’78 &lt;a href="https://www.cs.toronto.edu/%7Eeidan/papers/submod-max.pdf]" target="_blank" rel="noopener">https://www.cs.toronto.edu/%7Eeidan/papers/submod-max.pdf]&lt;/a>&lt;/p>
&lt;p>证明见&lt;a href="https://zhuanlan.zhihu.com/p/560699106" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/560699106&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>至此我们对submodular problem的求解有了基础的认识，但是上述方案仍然有几个问题没有解决&lt;/p>
&lt;ul>
&lt;li>对于形式化为最大化$f(S)$的问题，当 $f$是单调次模的并且$I$形成一个拟阵时，最优的近似程度是多少。&lt;/li>
&lt;li>非单调次模函数的优化问题。&lt;/li>
&lt;li>更一般的约束条件，或者是多种简单约束的组合。&lt;/li>
&lt;/ul>
&lt;p>此后又有一些学者提出了基于贪心的Submodular Optimiaztion方法&lt;/p>
&lt;h2 id="multilinear-relaxation">Multilinear Relaxation&lt;/h2>
&lt;p>有学者(Calinescu,Chekuri,Pál,V. ’07)尝试用次模函数的多线性松弛(Multilinear Relaxation)将离散优化问题转换成连续优化问题&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701310302491_1.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>多线性扩展 $F(x) $是通过以下方式定义的：
$$
F(x) = \mathbb{E}[f(\hat{x})]
$$
其中$\hat{x}$ 是通过将每个$x_i$ 以$x_i$ 的概率随机舍入到0或1获得。&lt;/p>
&lt;p>Multilinear Relaxation有以下性质：&lt;/p>
&lt;ul>
&lt;li>$F(x)$既不是全局concave也不是全局convex。&lt;/li>
&lt;li>对$F$的二阶导数$\frac{\partial^2 F}{\partial x_i^2}$为零&lt;/li>
&lt;li>如果$\vec{d}$是非负的则$F(x + \lambda \vec{d})$是关于$\lambda$的concave function。&lt;/li>
&lt;/ul>
&lt;p>通过将离散问题转化为连续问题，使用连续优化手段来寻找近似解，然后将这些解舍入到最接近的整数解以用于解决离散问题。&lt;/p>
&lt;h2 id="continuous-greedy">Continuous Greedy&lt;/h2>
&lt;p>求解$F(x)$的最大值$\max{F(x):x\in P)}$，F为单调子模函数的多线性扩展(multilinear extension)。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701311389331.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>对于每一个 $x \in P$， $v(x)$为
$$
v(x) = argmax_{v \in P}(v \cdot \nabla F(x))
$$
定义 $x(t)$：&lt;/p>
&lt;ul>
&lt;li>$x(0) = 0$&lt;/li>
&lt;li>$\frac{dx}{dt} = v(x)$&lt;/li>
&lt;/ul>
&lt;p>其中 $t \in [0, 1]$ 范围内变化，返回 $x(1)$。&lt;/p>
&lt;p>在该方法中$x(1) \in P$, $F(x(1))$至少是最优解(OPT)的$(1-\frac1e)$倍。&lt;/p>
&lt;center>
&lt;img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="1701312111082_1.png">
&lt;br>
&lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
display: inline-block;
color: #999;
padding: 1px;">&lt;/div>
&lt;/center>
&lt;p>根据链式法则
$$
\frac{dF}{dt}=\frac{dx}{dt}\cdot\nabla F(x(t))=v(x)\cdot\nabla F(x(t))\geq OPT-F(x(t)).
$$
得
$$
F(x(t))\geq(1-e^{-t})\cdot OPT.
$$
&lt;/p>
&lt;hr>
&lt;h1 id="reference">Reference:&lt;/h1>
&lt;p>[1] &lt;a href="https://theory.stanford.edu/~jvondrak/data/SIDMA-plenary-talk.pdf" target="_blank" rel="noopener">https://theory.stanford.edu/~jvondrak/data/SIDMA-plenary-talk.pdf&lt;/a>&lt;/p>
&lt;p>[2] &lt;a href="https://zhuanlan.zhihu.com/p/560699106" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/560699106&lt;/a>&lt;/p>
&lt;p>[3] &lt;a href="https://www.cs.toronto.edu/%7Eeidan/papers/submod-max.pdf" target="_blank" rel="noopener">https://www.cs.toronto.edu/%7Eeidan/papers/submod-max.pdf&lt;/a>&lt;/p></description></item><item><title>论文解读 | 面向LLM的图结构多模态表示</title><link>https://geyuyao.com/post/which-modality-text-motif-image/</link><pubDate>Tue, 21 Nov 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/which-modality-text-motif-image/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Which Modality should I use &amp;ndash; Text, Motif, or Image? : Understanding Graphs with Large Language Models&lt;/p>
&lt;p>&lt;strong>Institution:&lt;/strong> Minnesota NLP, University of Minnesota&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Debarati Das, Ishaan Gupta, Jaideep Srivastava, Dongyeop Kang&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2311.09862" target="_blank" rel="noopener">https://arxiv.org/abs/2311.09862&lt;/a>&lt;/p>
&lt;p>&lt;strong>Code Link:&lt;/strong> None&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2023.11.16&lt;/p>
&lt;p>&lt;strong>Abstract:&lt;/strong> Large language models (LLMs) are revolutionizing various fields by leveraging large text corpora for context-aware intelligence. Due to the context size, however, encoding an entire graph with LLMs is fundamentally limited. This paper explores &lt;strong>how to better integrate graph data with LLMs and presents a novel approach using various encoding modalities (e.g., text, image, and motif) and approximation of global connectivity of a graph using different prompting methods to enhance LLMs&amp;rsquo; effectiveness in handling complex graph structures.&lt;/strong> The study also introduces GraphTMI, a new benchmark for evaluating LLMs in graph structure analysis, focusing on factors such as homophily, motif presence, and graph difficulty. Key findings reveal that image modality, supported by advanced vision-language models like GPT-4V, is more effective than text in managing token limits while retaining critical information. The research also examines the influence of different factors on each encoding modality&amp;rsquo;s performance. This study highlights the current limitations and charts future directions for LLMs in graph understanding and reasoning tasks.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/0_hu37f7d3b533cfd0b7b7bf2750d5f7c747_300803_71bb801e75943e65819746c213eef02d.webp 400w,
/post/which-modality-text-motif-image/0_hu37f7d3b533cfd0b7b7bf2750d5f7c747_300803_ddc2059d98391802d4843e99de7a1c5e.webp 760w,
/post/which-modality-text-motif-image/0_hu37f7d3b533cfd0b7b7bf2750d5f7c747_300803_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/0_hu37f7d3b533cfd0b7b7bf2750d5f7c747_300803_71bb801e75943e65819746c213eef02d.webp"
width="524"
height="462"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h1 id="introduction">&lt;strong>Introduction:&lt;/strong>&lt;/h1>
&lt;p>In this paper, we explore the impact of encoding global and local graph structures using &lt;strong>different modalities&lt;/strong>, particularly focusing on &lt;strong>node classification tasks&lt;/strong>.&lt;/p>
&lt;p>In specific, this paper compare three modalities: &lt;strong>Text&lt;/strong>, &lt;strong>Motif&lt;/strong>, and &lt;strong>Image&lt;/strong>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/1_hu6850a7b1bf3ec126681fc77a7f3881b6_206925_81f81a543f14e84f03d87431f10ccaa0.webp 400w,
/post/which-modality-text-motif-image/1_hu6850a7b1bf3ec126681fc77a7f3881b6_206925_85bc0f971de2e49fd1816a1f2f129324.webp 760w,
/post/which-modality-text-motif-image/1_hu6850a7b1bf3ec126681fc77a7f3881b6_206925_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/1_hu6850a7b1bf3ec126681fc77a7f3881b6_206925_81f81a543f14e84f03d87431f10ccaa0.webp"
width="760"
height="489"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The reason why this paper introduce MOTIFS :&lt;/p>
&lt;blockquote>
&lt;p>However, it becomes &lt;strong>too verbose&lt;/strong> for large graphs, potentially &lt;strong>exceeding the input context limits&lt;/strong> of large language models like GPT-4 . To circumvent this, &lt;strong>we suggest Motif modality encoding, which captures essential patterns within the node’s vicinity, offering a balanced local and global perspective.&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;h1 id="methodology">Methodology&lt;/h1>
&lt;h2 id="text-encoder-modality">Text Encoder Modality&lt;/h2>
&lt;p>Encoding graphs as text can be separated into two key parts：&lt;/p>
&lt;ol>
&lt;li>the mapping of nodes to their corresponding labels in the graph
&lt;ul>
&lt;li>{node ID: node label}&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>the encoding of edges between the nodes&lt;/li>
&lt;/ol>
&lt;p>We consider the importance of some factors that can influence the performance of text modality encoding :&lt;/p>
&lt;ul>
&lt;li>Edge Encoding Function&lt;/li>
&lt;li>Graph Structure&lt;/li>
&lt;li>Sampling Strategy&lt;/li>
&lt;/ul>
&lt;h3 id="edge-encoding-function">Edge Encoding Function&lt;/h3>
&lt;ul>
&lt;li>Edgelist&lt;/li>
&lt;li>Edgetext&lt;/li>
&lt;li>Adjacency List&lt;/li>
&lt;li>GML&lt;/li>
&lt;li>GraphML&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Edgelist:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Node to Label Mapping : Node 69025: Label 34| Node 17585: Label 10|...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Edge list: [(69025, 96211), (69025, 17585), (17585, 104598), (17585, 18844), (17585, 96211), (96211, 34515)]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Edgetext:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Node to Label Mapping : Node 85328: Label 16| Node 158122: Label ?|...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Edge connections (source node - target node): Node 85328 is connected to Node 158122. Node 158122 is connected to Node 167226.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Adjacency List:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Node to Label Mapping : Node 2339: Label 3| Node 2340: Label ?|...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Adjacency list: 1558: [2339, 2340], 2339: [1558, 2340], 2340: [2339,1558]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>GML:&lt;/strong>&lt;/p>
&lt;p>A GraphML format consists of an unordered sequence of node and edge elements enclosed within [].&lt;/p>
&lt;p>The node label information is embedded within the structure, &lt;strong>meaning no node-label mapping is notneeded&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">GraphML:graph [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> node [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> id 2339
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> label 3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> node [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> id 2340
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> label ?
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> node [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> id 1558
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> label 3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> edge [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> source 2339
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> target 1558
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> edge [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> source 2339
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> target 2340
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>GraphML:&lt;/strong>&lt;/p>
&lt;p>A GraphML file consists of an XML file containing a graph element, within which is an unordered sequence of node and edge elements.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">GraphML:&amp;lt;graphml xmlns=http://graphml.graphdrawing.org/xmlns
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">xsi:schemaLocation=http://graphml.graphdrawing.org/xmlns
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;graph edgedefault=undirected&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;node id=2339 label=3 /&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;node id=2340 label=? /&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;node id=1558 label=3 /&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;edge source=2339 target=1558 /&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;edge source=2339 target=2340 /&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;lt;/graph&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;lt;/graphml&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="graph-structure">Graph Structure&lt;/h3>
&lt;p>We selected real-world citation datasets with differing network properties to explore the significance of graph structure on node classification.&lt;/p>
&lt;ul>
&lt;li>CORA&lt;/li>
&lt;li>Citeseer&lt;/li>
&lt;li>Pubmed&lt;/li>
&lt;/ul>
&lt;h3 id="sampling-strategy">Sampling Strategy&lt;/h3>
&lt;ul>
&lt;li>Ego graph&lt;/li>
&lt;li>Forest Fire sampling&lt;/li>
&lt;/ul>
&lt;h3 id="example-">Example :&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Task: Node Label Prediction (Predict the label of the node marked with a ?) given the adjacency list information as a dictionary of type “node: neighborhood” and node-label mapping in the text enclosed in triple backticks. Response should be in the format “Label of Node = &amp;lt;predicted label&amp;gt;”.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">If the predicted label cannot be determined, return “Label of Node = -1”.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">```AdjList: {1: [2,3], 2: [3,4], 3: [1,2]}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Node-Label Mapping: {1: A, 2: B, 3: ?} ```
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="motif-modality">Motif Modality&lt;/h2>
&lt;p>Encoding graphs as motifs can be separated into two key parts:&lt;/p>
&lt;ol>
&lt;li>the encoding of nodes to their corresponding labels in the graph&lt;/li>
&lt;li>the motifs present around the ? (unlabeled) node.&lt;/li>
&lt;/ol>
&lt;h3 id="motif-information">Motif information&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Type of Motif&lt;/th>
&lt;th>Motif Encoding&lt;/th>
&lt;th>Description of Motif&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Node-Label Mapping&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip;&lt;/td>
&lt;td>Only the node-label mapping is provided (&lt;strong>this gives no connectivity information to LLM&lt;/strong>)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No. of Star Motifs&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Number of star motifs: 0|&lt;/td>
&lt;td>Star motifs signify centralized networks with influential central nodes, where a central node is connected to others that aren’t interlinked. We pass the count of the star motifs present in the graph.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No. of Triangle Motifs&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Number of triangle motifs: 6|&lt;/td>
&lt;td>Triangle motifs (triads connecting three nodes) are foundational in social networks, indicating transitive relationships, community structures, and strong social ties. We pass the count of the triads present in the graph.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No. of Triangle Motifs Attached&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Triangle motifs attached to ? node: |1893,2034,1531|, |1893,1531,429|&lt;/td>
&lt;td>We pass the triangle motifs attached to the ? label, which gives an idea of the influential triads connected to the ? node.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No. of Star Motifs Attached&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Star motifs connected to ? node: | |&lt;/td>
&lt;td>We pass the star motifs attached to the ? label, which gives an idea of the influential nodes connected to the ? node.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No. of Star and Triangle Motifs&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Number of star motifs: 0| Number of triangle motifs: 6|&lt;/td>
&lt;td>We pass the count of the triads and star motifs present in the graph, to give the LLM an idea of the graph structure.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Star and Triangle Motifs attached&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Triangle motifs attached to ? node: |1893,2034,1531|, |1893,1531,429| Star motifs connected to ? node: | |&lt;/td>
&lt;td>We pass the star motifs and triads attached to the ? label, which gives an idea of the influential nodes and triads connected to the ? node.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No of cliques ? Node is part of&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: Number of cliques in graph: 0| Node is a part of these cliques: | |&lt;/td>
&lt;td>We pass the number of cliques in the network, which gives an idea of its clustered nature. We also pass the cliques the ? label is a part of, which gives an idea of the immediate community of the unlabelled node.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No of cliques ? Node is attached to&lt;/strong>&lt;/td>
&lt;td>Node to Label Mapping : Node 1889: Label 4 | &amp;hellip; Node 1893: Label 2|&amp;hellip; Graph motif information: ? Node is attached to these cliques: | |&lt;/td>
&lt;td>We pass the cliques the ? label is attached to, which gives an idea of the neighboring influential community of the unlabelled node.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="example">Example&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Task: Node Label Prediction (Predict the label of the node marked with a ?) given the node-label mapping and graph
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">motif information in the text enclosed in triple backticks. Response should be in the format “Label of Node = &amp;lt;predicted
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">label&amp;gt;”.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">If the predicted label cannot be determined, return “Label of Node = -1”.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">```Node-Label Mapping: {1: A, 2: A, 3: ?}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Graph-motif information: No of triangles: 1| Triangles
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">attached to ? Node : [1,2,3]| ```
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="image-modality">Image Modality&lt;/h2>
&lt;p>We first generate the graph rendering of our sampled graphs using NetworkX and color the nodes per the label values of each node.&lt;/p>
&lt;p>We set the **unlabeled node always to be “red” and have a mark as a &amp;lsquo;?&amp;rsquo; label on the node. **&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_21c08e385f7536e625b1ff9e60eb8ec2.webp 400w,
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_3be6f98198df36573d49675758ac7202.webp 760w,
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_21c08e385f7536e625b1ff9e60eb8ec2.webp"
width="760"
height="380"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h3 id="image-representation">Image representation&lt;/h3>
&lt;p>How applying &lt;strong>different changes to the image representation can enhance an image’s human readability&lt;/strong>. We then use these image encodings to evaluate the performance of node classification.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Original NetworkX Graph" srcset="
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_21c08e385f7536e625b1ff9e60eb8ec2.webp 400w,
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_3be6f98198df36573d49675758ac7202.webp 760w,
/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/2_hu6db36b47bfd4e591c1bcaaaf776ac24f_63556_21c08e385f7536e625b1ff9e60eb8ec2.webp"
width="760"
height="380"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/3_hub733509d0039654cf8b9849fe0ce31b7_135919_913d51ec9206eb86beed63680f3ac7d2.webp 400w,
/post/which-modality-text-motif-image/3_hub733509d0039654cf8b9849fe0ce31b7_135919_ce90ca453440684c255f776abcc7eb5b.webp 760w,
/post/which-modality-text-motif-image/3_hub733509d0039654cf8b9849fe0ce31b7_135919_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/3_hub733509d0039654cf8b9849fe0ce31b7_135919_913d51ec9206eb86beed63680f3ac7d2.webp"
width="696"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/4_hue3063915b844d21e4e373471578bf40f_99213_dfd14fef8ae86e5d044d5474db2893ba.webp 400w,
/post/which-modality-text-motif-image/4_hue3063915b844d21e4e373471578bf40f_99213_5e0687a3b03fef3625fab1f6209eb518.webp 760w,
/post/which-modality-text-motif-image/4_hue3063915b844d21e4e373471578bf40f_99213_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/4_hue3063915b844d21e4e373471578bf40f_99213_dfd14fef8ae86e5d044d5474db2893ba.webp"
width="696"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">Original NetworkX Graph&lt;/td>
&lt;td style="text-align:center">Node Size Increase&lt;br />增加节点大小&lt;/td>
&lt;td style="text-align:center">Contrasting Text Color&lt;br />这个子图对文本标签和节点颜色进行了对比，以提高标签的“人类可读性”。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/5_hue3063915b844d21e4e373471578bf40f_98630_98584f9f136778711ee53e308fffd5ee.webp 400w,
/post/which-modality-text-motif-image/5_hue3063915b844d21e4e373471578bf40f_98630_11eda88fc9497092fb21c3fe9d571fcc.webp 760w,
/post/which-modality-text-motif-image/5_hue3063915b844d21e4e373471578bf40f_98630_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/5_hue3063915b844d21e4e373471578bf40f_98630_98584f9f136778711ee53e308fffd5ee.webp"
width="696"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/6_hu6db36b47bfd4e591c1bcaaaf776ac24f_133436_39665cf138849486972235083e257bb9.webp 400w,
/post/which-modality-text-motif-image/6_hu6db36b47bfd4e591c1bcaaaf776ac24f_133436_db5695abb4a09ed45e3208e0ee333d55.webp 760w,
/post/which-modality-text-motif-image/6_hu6db36b47bfd4e591c1bcaaaf776ac24f_133436_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/6_hu6db36b47bfd4e591c1bcaaaf776ac24f_133436_39665cf138849486972235083e257bb9.webp"
width="709"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/7_hu6db36b47bfd4e591c1bcaaaf776ac24f_136864_4a0191e1f8d03e4268f3134c2e416157.webp 400w,
/post/which-modality-text-motif-image/7_hu6db36b47bfd4e591c1bcaaaf776ac24f_136864_f9c25723e504d290ccb6022644106537.webp 760w,
/post/which-modality-text-motif-image/7_hu6db36b47bfd4e591c1bcaaaf776ac24f_136864_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/7_hu6db36b47bfd4e591c1bcaaaf776ac24f_136864_4a0191e1f8d03e4268f3134c2e416157.webp"
width="709"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">Distinctive Node Colors&lt;br />通过为不同标签的节点选择不同的颜色，可以更好地区分各个节点。&lt;/td>
&lt;td style="text-align:center">Node Size increase based on 1-Hop distance&lt;br />增加了邻接节点的大小&lt;/td>
&lt;td style="text-align:center">Aggregate all changes&lt;br />应用上述所有优化方式&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h1 id="result">Result&lt;/h1>
&lt;h2 id="results-across-all-modalities">Results Across All Modalities&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Cora&lt;/th>
&lt;th>Citeseer&lt;/th>
&lt;th>Pubmed&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>GNN Baselines&lt;/strong>&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GCN&lt;/td>
&lt;td>0.7584 ±0.121&lt;/td>
&lt;td>0.6102 ±0.087&lt;/td>
&lt;td>0.7546 ±0.076&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GAT&lt;/td>
&lt;td>0.7989 ±0.092&lt;/td>
&lt;td>0.6583 ±0.074&lt;/td>
&lt;td>0.7490 ±0.060&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GraphSage&lt;/td>
&lt;td>0.7719 ±0.124&lt;/td>
&lt;td>0.6017 ±0.103&lt;/td>
&lt;td>0.7193 ±0.076&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>LLMs + Encoding Modality&lt;/strong>&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Text🥇&lt;/td>
&lt;td>&lt;strong>0.81&lt;/strong> ±0.04 [0.07 ±0.03]&lt;/td>
&lt;td>&lt;strong>0.75&lt;/strong> ±0.05 [0.07 ±0.01]&lt;/td>
&lt;td>&lt;strong>0.83&lt;/strong> ±0.01 [0.08 ±0.01]*&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Motif&lt;/td>
&lt;td>0.73 ±0.06 [0.06 ±0.01]&lt;/td>
&lt;td>0.59 ±0.01 [0.32 ±0.02]&lt;/td>
&lt;td>0.77 ±0.06 [0.13 ±0.04]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Image🥈&lt;/td>
&lt;td>0.77 ±0.05 [0.04 ±0.02]*&lt;/td>
&lt;td>0.71 ±0.09 [0.06 ±0.01]*&lt;/td>
&lt;td>0.79 ±0.03 [0.19 ±0.01]&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>⭐From this table, we find that &lt;strong>the text modality is comparable with graph baselines in all three datasets&lt;/strong>, while &lt;strong>the image modality comes a close second&lt;/strong>. This shows the potential of LLMs to be a good foundational model for graphs.&lt;/p>
&lt;p>⭐We also observe that **the lowest denial rate is for the image ** &lt;strong>modality in the smaller CORA and Citeseer datasets, while the bigger Pubmed dataset shows a higher denial rate&lt;/strong>. &lt;strong>This could be because of bigger subgraphs sampled, leading to congestion in the image modality, causing the LLM to deny a classification.&lt;/strong>&lt;/p>
&lt;h3 id="qualitative-analysis-of-denial-of-classification-in-the-image-modality">Qualitative analysis of denial of classification in the Image Modality&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/8_hu50f5ef895b83b1f9aca3ea2c070d4b5e_136864_7161144cab83023581de3c6a3a7d36ff.webp 400w,
/post/which-modality-text-motif-image/8_hu50f5ef895b83b1f9aca3ea2c070d4b5e_136864_b1cf2a03f10d556b894812db6569f49e.webp 760w,
/post/which-modality-text-motif-image/8_hu50f5ef895b83b1f9aca3ea2c070d4b5e_136864_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/8_hu50f5ef895b83b1f9aca3ea2c070d4b5e_136864_7161144cab83023581de3c6a3a7d36ff.webp"
width="709"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/9_huef89299bc4723200b091b7122d4eb312_55737_3e3ff28b4aae543c6dbb85930e8bef63.webp 400w,
/post/which-modality-text-motif-image/9_huef89299bc4723200b091b7122d4eb312_55737_b452da54084491d0ba688c8ede7377e1.webp 760w,
/post/which-modality-text-motif-image/9_huef89299bc4723200b091b7122d4eb312_55737_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/9_huef89299bc4723200b091b7122d4eb312_55737_3e3ff28b4aae543c6dbb85930e8bef63.webp"
width="578"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;th style="text-align:center">
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/10_huc800ead9d84e82a592fdcf76873b1010_72137_0551c3f479b0a01bf7695a892d8a62cc.webp 400w,
/post/which-modality-text-motif-image/10_huc800ead9d84e82a592fdcf76873b1010_72137_128bda22b89578509e201de8fc755431.webp 760w,
/post/which-modality-text-motif-image/10_huc800ead9d84e82a592fdcf76873b1010_72137_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/10_huc800ead9d84e82a592fdcf76873b1010_72137_0551c3f479b0a01bf7695a892d8a62cc.webp"
width="680"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">a.(Ground = 0) Without additional context or rules for how labels are assigned, it is not possible to accurately predict the label of the red node.&lt;br />其他的节点都是按照label进行染色，然而?节点被染成了红色，这会使llm困惑。&lt;/td>
&lt;td style="text-align:center">b.(Ground = 4) The label cannot be determined with certainty due to the lack of a discernible pattern or rule that associates a node’s color or its connections with its label.&lt;br />图中存在异质性 3-?-4&lt;/td>
&lt;td style="text-align:center">c.(Ground = 2) The label cannot be determined with certainty due to the lack of a clear pattern in the graph and no previous examples of red nodes to infer from.&lt;br />需要few-shot&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>We observe that a) &lt;strong>the LLM requires context about how labels are assigned to each node&lt;/strong>. We left this information implicit in our image modality encoder, where every node is colored per its label. The red color is reserved for the ? node, which is unlabeled. This information is not explicit to the LLM. With image (b), there is &lt;strong>no clear pattern associating the node’s color with its label, which is a confusion induced by the great amount of heterophily in the graph.&lt;/strong> Image (c) brings up the need for few-shot learning, &lt;strong>This information is not explicit to the LLM&lt;/strong> given other graph examples.&lt;/p>
&lt;h3 id="insights-from-graphtmi">Insights from GraphTMI&lt;/h3>
&lt;p>&lt;strong>Easy problems (high homophily, simple graph structure) have higher accuracy with the image modality encoding&lt;/strong>. Graphs categorized as &lt;strong>medium or hard&lt;/strong>, because of a heterophyllous nature or complex graph structure, have a &lt;strong>higher accuracy with the text modality&lt;/strong>, though the image modality is not far behind.&lt;/p>
&lt;h2 id="text-modality-results">Text Modality Results&lt;/h2>
&lt;h3 id="edge-encoding-function-1">Edge Encoding Function&lt;/h3>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/11_hude1f17329fd53fec27a9de9e63c6f88c_27282_df65bc75420ceda4053faef055b382db.webp 400w,
/post/which-modality-text-motif-image/11_hude1f17329fd53fec27a9de9e63c6f88c_27282_2f31c71466dbe1f8ab4070cd8ddb3e6f.webp 760w,
/post/which-modality-text-motif-image/11_hude1f17329fd53fec27a9de9e63c6f88c_27282_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/11_hude1f17329fd53fec27a9de9e63c6f88c_27282_df65bc75420ceda4053faef055b382db.webp"
width="665"
height="552"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Figure shows that using the 🌟&lt;strong>Adjacency List&lt;/strong> as the mode of edge representation with node label mapping is the most informative encoding function, which balances the trade-off between &lt;strong>high accuracy&lt;/strong> and &lt;strong>low token limit fraction&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;ul>
&lt;li>accuracy rate(↑)&lt;/li>
&lt;li>mismatch rate (↓)&lt;/li>
&lt;li>denial rate (↓)&lt;/li>
&lt;li>token limit fraction (↓)&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;h3 id="impact-of-graph-structure-and-graph-sampling">Impact of graph structure and graph sampling:&lt;/h3>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/12_hu0215aad2b98e5015f27d3389660cb7bb_38416_ea9f9765902a61f0ff5b209fa9719f81.webp 400w,
/post/which-modality-text-motif-image/12_hu0215aad2b98e5015f27d3389660cb7bb_38416_28314784bff6dab1c8d3bd109f3bb8f4.webp 760w,
/post/which-modality-text-motif-image/12_hu0215aad2b98e5015f27d3389660cb7bb_38416_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/12_hu0215aad2b98e5015f27d3389660cb7bb_38416_ea9f9765902a61f0ff5b209fa9719f81.webp"
width="641"
height="435"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>&lt;strong>Green is the accuracy rate, Blue is the mismatch rate, Red is the&lt;/strong> &lt;strong>denial rate, and Pink is the token limit fraction.&lt;/strong> The desired trends for each metric are given in brackets - (↑) accuracy rate, (↓) mismatch rate, (↓) denial rate, and (↓) token limit fraction. The x-axis distinguishes between ego graph sampling (ego) and forest fire sampling (ff) through different bar textures.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>在准确率上影响不大，主要影响的是token limit fraction&lt;/p>
&lt;/li>
&lt;li>
&lt;p>两种采样方式在CORA上表现地都最好，可能因为它更小，更稠密，更聚集&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="motif-modality-results">Motif Modality Results&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/13_hu1788f8020edba344d46a779ff3621a71_25511_7c98368e672768e36c179b94e3afbaec.webp 400w,
/post/which-modality-text-motif-image/13_hu1788f8020edba344d46a779ff3621a71_25511_6a9a4c4866a6240b07c66b2c7e895af1.webp 760w,
/post/which-modality-text-motif-image/13_hu1788f8020edba344d46a779ff3621a71_25511_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/13_hu1788f8020edba344d46a779ff3621a71_25511_7c98368e672768e36c179b94e3afbaec.webp"
width="629"
height="426"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>We observe that the mean accuracy rate goes up on adding the “triangle and star attached to ? node” motif, while the other metrics for the same setting
are low.&lt;/p>
&lt;ul>
&lt;li>此部分几乎没有进行分析，只提了“triangle and star attached to ? node” 最好，且一笔带过&lt;/li>
&lt;/ul>
&lt;h2 id="image-modality-results">Image Modality Results&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/which-modality-text-motif-image/14_huaba5ad6a60126399392ce35176f86715_22216_81e955c7fc8330515a0f0728d6043ef8.webp 400w,
/post/which-modality-text-motif-image/14_huaba5ad6a60126399392ce35176f86715_22216_e1005cd699a46cdff7ce38f071b585e1.webp 760w,
/post/which-modality-text-motif-image/14_huaba5ad6a60126399392ce35176f86715_22216_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/which-modality-text-motif-image/14_huaba5ad6a60126399392ce35176f86715_22216_81e955c7fc8330515a0f0728d6043ef8.webp"
width="632"
height="424"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>We observe that the “rendering change” offers the highest bump in accuracy, which only goes down when “node size is changed on hop”. This is probably because the LLM is confused bydifferent node sizes and their meaning. This could be resolved by clarifying the text prompt or using different shapes to represent nodes at different hop distances. Based on Figure 11, when “all the changes are applied”, the denial rate is minimum,and the accuracy rate is highest (0.7).&lt;/p>
&lt;ol>
&lt;li>渲染变化确实能提高准确率&lt;/li>
&lt;li>当“应用所有变化”时，拒绝率最低，准确率最高（0.7）&lt;/li>
&lt;/ol>
&lt;h1 id="总结">总结&lt;/h1>
&lt;ul>
&lt;li>使用image和motif模态来表示图作为llm的输入是之前没有看到过的&lt;/li>
&lt;li>受限于算力和token limit，最大跳数被设置为了3&lt;/li>
&lt;/ul></description></item><item><title>论文解读 | Graph-Guided Reasoning for Multi-Hop Question Answering in Large Language Models</title><link>https://geyuyao.com/post/graph-guided-reasoning/</link><pubDate>Mon, 20 Nov 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/graph-guided-reasoning/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Graph-Guided Reasoning for Multi-Hop Question Answering in Large Language Models&lt;/p>
&lt;p>&lt;strong>Institution:&lt;/strong> Korea University, Amazon Alexa AI&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Jinyoung Park, Ameen Patel, Omar Zia Khan, Hyunwoo J. Kim, Joo-Kyung Kim&lt;/p>
&lt;p>&lt;strong>Arxiv Link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2311.09762" target="_blank" rel="noopener">https://arxiv.org/abs/2311.09762&lt;/a>&lt;/p>
&lt;p>&lt;strong>Code Link:&lt;/strong> None&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2023.11.16&lt;/p>
&lt;p>&lt;strong>Abstract:&lt;/strong> Chain-of-Thought (CoT) prompting has boosted the multi-step reasoning capabilities of Large Language Models (LLMs) by generating a series of rationales before the final answer. This paper analyzes the reasoning paths generated by CoT and identifies two issues in multi-step reasoning: (i) Generating rationales irrelevant to the question, (ii) Unable to compose subquestions or queries for generating/retrieving all the relevant information. To address these issues, the authors propose a graph-guided CoT prompting method, which guides the LLMs to reach the correct answer with graph representation/verification steps. This involves leveraging LLMs to construct a &amp;ldquo;question/rationale graph&amp;rdquo; using knowledge extraction prompting given the initial question and the rationales generated in previous steps. Then, the graph verification step diagnoses the current rationale triplet by comparing it with the existing question/rationale graph to filter out irrelevant rationales and generate follow-up questions to obtain relevant information. Additionally, CoT paths that exclude the extracted graph information are generated to represent the context information missed from the graph extraction. The proposed graph-guided reasoning method shows superior performance compared to previous CoT prompting and its variants on multi-hop question answering benchmark datasets.&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>提出了一种基于大模型的图引导的面向多步推理问题的推理方式。&lt;/p>
&lt;p>本文的主要贡献有两点&lt;/p>
&lt;ul>
&lt;li>
&lt;p>提出上述推理方式&lt;/p>
&lt;/li>
&lt;li>
&lt;p>提出允许变量定义的用于知识三元组提取的上下文学习方法&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="基于大模型的图引导的面向多步推理问题的推理方式">基于大模型的图引导的面向多步推理问题的推理方式&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/graph-guided-reasoning/0_hu0f66cdcc68e358d32e99a1b4d1779110_573654_f3b3002e4029257a44f883eae11a6219.webp 400w,
/post/graph-guided-reasoning/0_hu0f66cdcc68e358d32e99a1b4d1779110_573654_b24547e48059ceb9432c86c4d8899890.webp 760w,
/post/graph-guided-reasoning/0_hu0f66cdcc68e358d32e99a1b4d1779110_573654_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/graph-guided-reasoning/0_hu0f66cdcc68e358d32e99a1b4d1779110_573654_f3b3002e4029257a44f883eae11a6219.webp"
width="760"
height="623"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>该方法分为四个步骤&lt;/p>
&lt;ol>
&lt;li>
&lt;p>生成问题图&lt;/p>
&lt;/li>
&lt;li>
&lt;p>问题分解，生成中间子问题&lt;/p>
&lt;/li>
&lt;li>
&lt;p>回答子问题&lt;/p>
&lt;/li>
&lt;li>
&lt;p>验证中间逻辑推理&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="问题图">问题图&lt;/h2>
&lt;p>问题图通过从问题中提取三元组构成。所谓的基于图，本质上就是将问题转换成符号推理过程构成图的一部分。&lt;/p>
&lt;p>举例来讲，对于问题“When did the director of film Hypocrite (Film) die?”，可被转换为两个子问题作为图中的两个边“(‘Hypocrite(Film)’, directed by, $1),“($1, death date, $2）”。&lt;/p>
&lt;p>文章在此处的创新点在于，以类似于1st-order logic (FOL)的形式将形式逻辑引入了推理过程。在这个过程中变量（$1，$2）只能作为个体，而不能是命题或其他函数。&lt;/p>
&lt;p>作者团队将变量实体引入是为了解决wh-question。&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Wh-questions&amp;rdquo; are a type of question in English that begin with &amp;ldquo;wh-&amp;rdquo; words, such as &amp;ldquo;who,&amp;rdquo; &amp;ldquo;what,&amp;rdquo; &amp;ldquo;where,&amp;rdquo; &amp;ldquo;when,&amp;rdquo; &amp;ldquo;why,&amp;rdquo; and &amp;ldquo;how&amp;rdquo; (though &amp;ldquo;how&amp;rdquo; does not start with &amp;ldquo;wh,&amp;rdquo; it is grouped with them functionally).&lt;/p>
&lt;/blockquote>
&lt;h2 id="中间子问题生成">中间子问题生成&lt;/h2>
&lt;p>与其他成果相比，本文的中间子问题生成的特点主要在于本文的子问题生成是在图的引导下进行的。&lt;/p>
&lt;p>具体而言，本文过滤掉那些主体和客体都只是变量或实体的问题三元组，这意味着此过程只关注由实体主体和变量客体或变量主体和实体客体组成的三元组。&lt;/p>
&lt;p>这很好理解，对于三元组(variable1, relationship, variable2)和三元组(entity1, relationship, entity2)已经没有进一步分解的意义。&lt;/p>
&lt;h2 id="回答子问题">回答子问题&lt;/h2>
&lt;p>相比于原问题，子问题更短更简单，因此更容易产生正确回答。由于大模型易产生幻觉或大模型没有在指定的文档上进行过训练，可能会导致错误的输出，因此可以考虑使用RAG提高回答的准确性。&lt;/p>
&lt;h2 id="验证中间逻辑推理">验证中间逻辑推理&lt;/h2>
&lt;p>通过验证回答是否与问题图对齐来验证生成的推理三元组是否合格。&lt;/p>
&lt;p>具体而言，三元组的至少两个组件在推理三元组和问题图三元组之间需要相同，则我们接受与匹配三元组对应的推理，如果相应的三元组与问题图中的任何三元组都不匹配，则拒绝它。&lt;/p>
&lt;p>例如，给定推理三元组（‘伪君子（电影）’，导演，‘Miguel Morayta’）和问题图（‘伪君子（电影）’，导演，$1），（$1，死亡日期，$2）。由于问题图包含三元组（‘伪君子（电影）’，导演，$1），其中主体是‘伪君子（电影）’且关系是导演，因此接受推理。&lt;/p>
&lt;p>具一个反例，例如，问题图中没有与推理三元组（‘Miguel Morayta’，死亡地点，‘墨西哥’）匹配的三元组。因此被拒绝。&lt;/p>
&lt;h1 id="实验">实验&lt;/h1>
&lt;h2 id="setup">Setup&lt;/h2>
&lt;p>&lt;strong>Dataset :&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>2WikiMultihopQA consists of 2-hop complex questions requiring the composition or comparison.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>MuSiQue is a more challenging dataset where the problems include 2 to 4 hop questions that can be decomposed into simpler questions.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Bamboogle is a dataset consisting of 125 two-hop questions where the supporting evidence is from Wikipedia.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Models :&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Llama-2 13B&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Llama-2 70B&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="result">Result&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/graph-guided-reasoning/1_hu310f500650c2062e66119e68d761ff2e_124095_21b21beede2fdbf356af9834b9e84ffd.webp 400w,
/post/graph-guided-reasoning/1_hu310f500650c2062e66119e68d761ff2e_124095_9e2de38129fd37705b1a75501716996a.webp 760w,
/post/graph-guided-reasoning/1_hu310f500650c2062e66119e68d761ff2e_124095_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/graph-guided-reasoning/1_hu310f500650c2062e66119e68d761ff2e_124095_21b21beede2fdbf356af9834b9e84ffd.webp"
width="760"
height="459"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>上图展示了部分实验结果，与各个Baseline相比，本文方法获得了最好的performance。&lt;/p></description></item><item><title>论文解读 | GraphText —— 图到文本的映射</title><link>https://geyuyao.com/post/graphtext/</link><pubDate>Tue, 14 Nov 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/graphtext/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> GraphText: Graph Reasoning in Text Space&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> Université de Montréal&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Jianan Zhao, Le Zhuo, Yikang Shen, Meng Qu, Kai Liu, Michael Bronstein, Zhaocheng Zhu, Jian Tang&lt;/p>
&lt;p>&lt;strong>link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2310.01089" target="_blank" rel="noopener">https://arxiv.org/abs/2310.01089&lt;/a>&lt;/p>
&lt;p>&lt;strong>Date:&lt;/strong> 2023.10.02&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>之前我们介绍过使用大模型来解决图问题的两篇论文，两篇文章的作者将LLM Reasoning领域的Prompt引入到图问题上进行实验并提出BenchMark。尽管两文成果颇丰，但是并没有针对图的特点提出新的Prompt生成方式。在本文，作者跟据图结构的特点提出了一种将图映射到文本空间的框架&lt;strong>GRAPHTEXT&lt;/strong>。&lt;/p>
&lt;p>&lt;strong>GRAPHTEXT为&lt;/strong>每个图创建其对应的图语法树，图语法树同时封装了节点属性和节点间关系。通过遍历这棵树，可以产生图文序列，然后通过大型语言模型（LLM）处理，将图形任务视为文本生成任务。&lt;/p>
&lt;p>除了&lt;strong>将图空间映射到文本空间&lt;/strong>这一最大的优点外，本文还有如下贡献:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>传统的GNN方式需要针对每一个图训练一个GNN模型，而本文只需要通用的LLM通过上下文学习就可以了&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>GRAPHTEXT&lt;/strong>是一套通用框架，在普通图和文本属性图上都可以使用&lt;/p>
&lt;/li>
&lt;li>
&lt;p>可交互&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="方法论">方法论&lt;/h1>
&lt;h2 id="概述">概述&lt;/h2>
&lt;p>本方法可用如下公式概括:&lt;/p>
$\tilde{y}_i=h(f_{LLM}(g(G)_i;\phi))$
&lt;p>参数表:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>
$G$ 图&lt;/p>
&lt;/li>
&lt;li>
&lt;p>
$g(G)_i=T_{in}[i]$
$i$节点的文本表述&lt;/p>
&lt;/li>
&lt;li>
&lt;p>
$\phi$ LLM参数&lt;/p>
&lt;/li>
&lt;li>
&lt;p>
$f_\text{LLM}(\cdot;\phi):\mathcal{T}\to\mathcal{T}$ 基于LLM的映射函数，在输入和输出上都处于文本空间&lt;/p>
&lt;/li>
&lt;li>
&lt;p>
$h:T_{out}\mapsto\tilde{Y}$ 将LLM的输出映射至label&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="图语法树的构建">图语法树的构建&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/graphtext/0_hu79b6ab7b5c623d3f005ceb0977f9b4e1_171722_1c24ddb4a0f7c44123d0180255aa4b54.webp 400w,
/post/graphtext/0_hu79b6ab7b5c623d3f005ceb0977f9b4e1_171722_7d2579037a01b5238cbec74d53d6f8df.webp 760w,
/post/graphtext/0_hu79b6ab7b5c623d3f005ceb0977f9b4e1_171722_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/graphtext/0_hu79b6ab7b5c623d3f005ceb0977f9b4e1_171722_1c24ddb4a0f7c44123d0180255aa4b54.webp"
width="760"
height="276"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>首先需要明确的是在本文，图由两个部分构成，分别是节点的属性。&lt;/p>
&lt;p>图语法树的根节点是空节点，叶子节点
$\tilde{T}_\mathrm{L}$是图节点的文本属性，中间节点$\tilde{T}_{I}$是自然语言序列。&lt;/p>
&lt;p>图语法树的构建可由三部分构成&lt;/p>
&lt;ol>
&lt;li>
&lt;p>首先构建自我子图（ego-subgraph）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>选择叶子节点&lt;/p>
&lt;/li>
&lt;li>
&lt;p>构建中间节点和边&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>如上图(c) 所示，图中的属性为
$F={\mathrm{F}_{X}[i],\mathrm{F}_{Y}[i]|\forall v_{i}\in V}$，关系被定义为最短路 : center-node, 1st-hop, and 2nd-hop，即
$R={\boldsymbol{R_{\mathrm{SPD=0}}},\boldsymbol{R_{\mathrm{SPD=1}}},\boldsymbol{R_{\mathrm{SPD=2}}}}$。以0为中心点，自我子图被构建了起来。然后构建叶子节点
$\tilde{T_{\mathrm{L}}}={\mathrm{F_{\mathrm{X}}[0]},\mathrm{F_{\mathrm{X}}[1]},\mathrm{F_{\mathrm{X}}[2]}\mathrm{F_{\mathrm{X}}[3]},\mathrm{F_{\mathrm{X}}[4]},\mathrm{F_{\mathrm{Y}}[1]},\mathrm{F_{\mathrm{Y}}[3]}}$、中间节点
$\tilde{T}_\mathrm{I}=\{\text{“center-node",“}1\text{st-}\text{hop",“2nd-hop”,“label”,“feature”}\}$和树的边。最后遍历图语法树即可生成自然语言序列。&lt;/p></description></item><item><title>论文解读 | ReAct——LLM推理范式 推理+动作</title><link>https://geyuyao.com/post/react/</link><pubDate>Fri, 27 Oct 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/react/</guid><description>&lt;p>&lt;strong>titile:&lt;/strong> REACT: SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS&lt;/p>
&lt;p>&lt;strong>institute:&lt;/strong> Department of Computer Science, Princeton University&lt;/p>
&lt;p>&lt;strong>author:&lt;/strong> Shunyu Yao,Jeffrey Zhao, Dian Yu, Nan Du, Izhak Shafran, Karthik Narasimhan, Yuan Cao&lt;/p>
&lt;p>&lt;strong>Link:&lt;/strong> &lt;a href="https://arxiv.org/pdf/2210.03629.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2210.03629.pdf&lt;/a>&lt;/p>
&lt;p>&lt;strong>Shared Link:&lt;/strong> &lt;a href="https://mp.weixin.qq.com/s/5DFnutIpNIPRyJ7EUlfiEw" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/5DFnutIpNIPRyJ7EUlfiEw&lt;/a>&lt;/p>
&lt;h1 id="动机">动机&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>CoT方法是黑盒推理，推理过程和知识局限于模型内部&lt;/p>
&lt;/li>
&lt;li>
&lt;p>前人有工作探索了在互动环境中使用预训练语言模型进行规划和行动&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="启发">启发&lt;/h1>
&lt;p>人类在两个行动之间会通过语言来追踪进展，例如“现在所有的食材都切好了，我应该烧水了”。作者从人类的这个现象中获得启发，希望能够将大模型的推理过程显式表达出来。&lt;/p>
&lt;h1 id="react">ReAct&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://picdl.sunbangyan.cn/2023/11/03/36bea36781157e6f982ac30387947ca3.png" alt="image.png" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1698584125954.png" srcset="
/post/react/9ea5e0e989d7c7d5e8eab5058b037ca7_huc36ecd77dbf9df6eb35314cdbb7d6b00_49432_98d0528a3a1c44fc291a6ba48595fecb.webp 400w,
/post/react/9ea5e0e989d7c7d5e8eab5058b037ca7_huc36ecd77dbf9df6eb35314cdbb7d6b00_49432_19d732dde721bcb36537b680ab5c80e7.webp 760w,
/post/react/9ea5e0e989d7c7d5e8eab5058b037ca7_huc36ecd77dbf9df6eb35314cdbb7d6b00_49432_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/react/9ea5e0e989d7c7d5e8eab5058b037ca7_huc36ecd77dbf9df6eb35314cdbb7d6b00_49432_98d0528a3a1c44fc291a6ba48595fecb.webp"
width="760"
height="295"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>ReAct是一套针对大模型能够将thought和Act结合起来的框架。&lt;/p>
&lt;p>在$t$时刻，设观察到的信息为$o_t\in\mathcal{O}$，Act为$a_t\in\mathcal{A}$，其中$a_t$遵循策略$\pi(a_t|c_t)$，$c_t=\left(o_1,a_1,\cdots,o_{t-1},a_{t-1},o_t\right)$。然而直接$c_t\mapsto a_t$这个过程是隐式的且需要大量计算的。&lt;/p>
&lt;p>而ReAct的方法很简单就是扩充$\mathcal{A}$集为$\hat{\mathcal{A}}=\mathcal{A}\cup\mathcal{L}$。而$\mathcal{L}$集就是思考或推理过程。此时$\hat a_t\in\mathcal{L}$就是根据上下文$c_t$获得的Act。在下一轮中$c_{t+1}=\left(c_{t},\hat{a}_{t}\right)$作为上下文供生成Act。&lt;/p>
&lt;p>ReAct的每一个过程都是行动、思考、环境观察。&lt;/p>
&lt;p>然而这个过程存在缺点，那么就是模型容量必须足够大，具体而言，本文中使用的就是540B的模型。&lt;/p>
&lt;p>作者将任务话分成两类分别是推理主导任务和决策主导任务。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>推理主导：对于推理很重要的任务，作者使用思考-行动-观察流程。例如多推理的任务。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>决策主导：相反，对于涉及大量操作的决策任务，思考只需要偶尔出现就可以了。例如，你在一个厨房里，环境是xxx，你需要找xxx。&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>论文解读 | Reasoning with Language Model is Planning with World Model</title><link>https://geyuyao.com/post/rap/</link><pubDate>Thu, 26 Oct 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/rap/</guid><description>&lt;p>&lt;strong>Title:&lt;/strong> Reasoning with Language Model is Planning with World Model&lt;/p>
&lt;p>&lt;strong>Institute:&lt;/strong> UCSan Diego, University of Florida&lt;/p>
&lt;p>&lt;strong>Authors:&lt;/strong> Shibo Hao Yi Gu Haodi Ma Joshua Jiahua Hong Zhen Wang Daisy Zhe Wang Zhiting Hu&lt;/p>
&lt;p>&lt;strong>Link:&lt;/strong> &lt;a href="https://arxiv.org/pdf/2305.14992.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2305.14992.pdf&lt;/a>&lt;/p>
&lt;p>&lt;strong>Shared Link:&lt;/strong> &lt;a href="https://mp.weixin.qq.com/s/ZLktf__PCPsMYdX-Ikm_5A" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/ZLktf__PCPsMYdX-Ikm_5A&lt;/a>&lt;/p>
&lt;h1 id="简介">简介&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://picss.sunbangyan.cn/2023/11/03/4d42c35d2b5aa8f42937109c06d235f6.png" alt="" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>过去的研究证明，人类拥有一个内部的世界模型，使人类能够模拟行动及其对世界状态的影响，以进行复杂任务的有意识的规划，包括运动控制、想象、推理和决策。而大模型只能通过自回归的方式进行推理，作者认为限制大模型的推理的原因主要有三个：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>缺少内部模型对当前状态的模拟&lt;/p>
&lt;/li>
&lt;li>
&lt;p>缺少奖励机制来指导模型推理&lt;/p>
&lt;/li>
&lt;li>
&lt;p>无法在对未来的探索和对过去经验的汲取间达到平衡&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>对于第一个问题，作者将&lt;strong>强化学习&lt;/strong>概念引入reasoning提出使用llm作为world model实现对当前状态的模拟&lt;/p>
&lt;p>对于第二个问题，作者&lt;strong>基于大模型设计了四种奖励方式&lt;/strong>&lt;/p>
&lt;p>对于第三个问题，作者使用&lt;strong>蒙特卡洛树搜索&lt;/strong>解决&lt;/p>
&lt;h1 id="世界模型">世界模型&lt;/h1>
&lt;p>此处的世界模型是强化学习中的概念，可以理解为外界环境、对行动的模拟、行为的结果等概念。在这里作者使用prompting + llm实现世界模型。&lt;/p>
&lt;p>令当前状态为
$s_{t,t=0,1,2,3...T}$。大模型作为agent通过
$s_t$ 和prompt
$ c$ 推理出行动 $a_t$ 的过程可以被描述为
$a_t \sim p(a|s_t,c)$ 。此时作为世界模型的llm根据
$ a_t$ 和
$s_t$ 预测出下一个时刻的状态
$s_{t+1}$。&lt;/p>
&lt;h1 id="奖励">奖励&lt;/h1>
&lt;p>在推理步骤中，需要考量每一次推理的可行性用于指导推理。设计评估函数
$r_t=r(s_t,a_t)\in\mathbb{R}$，根据t时刻的状态$s_t$和动作$a_t$来获得回报。&lt;/p>
&lt;h1 id="基于蒙特卡洛树搜索的推理过程">基于蒙特卡洛树搜索的推理过程&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://picst.sunbangyan.cn/2023/11/03/7e2aa5c36dcec92ef666a82d215af279.png" alt="1698568853722.png" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>蒙特卡洛树搜索主要可分为如下四个步骤&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Selection: 在Selection阶段根据UCB值选取期望回报最高的叶子节点&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Expansion: 在Expansion阶段对该叶子节点进行拓展&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Simulation: 对拓展的叶子节点进行仿真，判断结果&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Back-propagation: 反向传播&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>重点介绍Selection和Simulation阶段&lt;/p>
&lt;h2 id="selection">Selection：&lt;/h2>
&lt;p>对于候选节点，根据UCB公式计算每个节点的UCB值&lt;/p>
$a^*=\arg\max\limits_{a\in A(s)}\left[Q(s,a)+w\sqrt{\frac{\ln N(s)}{N(c(s,a))}}\right]$
&lt;ul>
&lt;li>
&lt;p>作为第一项的Q值表示此节点在过去时间的平均奖赏，是对过去经验的汲取。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>第二项中的
$N$是访问次数，
$c(s,a)$是此节点(将$a$动作施加于$s$状态)的子节，是对未来的探索。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>$w$是第二项的权重&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>根据此公式可知，Selection策略具有如下特点&lt;/p>
&lt;ul>
&lt;li>
&lt;p>向于选择过去获得回报更高的节点&lt;/p>
&lt;/li>
&lt;li>
&lt;p>倾向于选择未被探索的节点&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>这样，通过蒙特拉洛树搜索中的UCB公式就可以解决&lt;strong>exploration vs. exploitation&lt;/strong>难题。&lt;/p>
&lt;h2 id="simulation">Simulation&lt;/h2>
&lt;p>这个阶段使用&lt;strong>世界模型&lt;/strong>来模拟当前节点的未来情况。从上面的当前节点开始，在每个节点
$s_t$处，我们按照一个扩展策略创建一个动作
$a_t$，并使用世界模型预测下一个状态
$a_{t+1}$。扩展过程会一直进行，直到达到一个终止状态。&lt;/p>
&lt;p>如上图$(c)$&lt;/p></description></item><item><title>论文解读 | Can Language Models Solve Graph Problems in Natural Language?</title><link>https://geyuyao.com/post/lm-graph-problems-natural-language/</link><pubDate>Mon, 23 Oct 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/lm-graph-problems-natural-language/</guid><description>&lt;p>&lt;strong>title:&lt;/strong> Can Language Models Solve Graph Problems in Natural Language?&lt;/p>
&lt;p>&lt;strong>institute:&lt;/strong> Xi&amp;rsquo;an Jiaotong University University of Washington&lt;/p>
&lt;p>&lt;strong>authors:&lt;/strong> Heng Wang , Shangbin Feng , Tianxing He, Zhaoxuan Tan , Xiaochuang Han , Yulia Tsvetkov&lt;/p>
&lt;p>Date: 2023.5.13&lt;/p>
&lt;p>&lt;strong>link:&lt;/strong> &lt;a href="https://arxiv.org/pdf/2305.10037v1.pdf" target="_blank" rel="noopener">2305.10037v1.pdf (arxiv.org)&lt;/a>&lt;/p>
&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>本文首次尝试使用大模型来解决图问题。在本文作者基于自然语言提出了含有千余个图基础问题的BenchMark &lt;strong>NLGraph&lt;/strong>。作者在GPT3/4上进行实验获得了一些结论。在论文的最后，作者提出了两个可以提升大模型处理图问题的方法。&lt;/p>
&lt;p>总结来讲，本文贡献如下：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>提出了首个使用自然语言处理图问题的BenchMark &lt;strong>NLGraph&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在GPT3/4上进行实验并统计LLM performance，获得了一些规律&lt;/p>
&lt;/li>
&lt;li>
&lt;p>提出了两个改善方法&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="nlgraph">NLGraph&lt;/h1>
&lt;p>这个BenchMark简单来讲就是一堆用自然语言描述的图并配有其对应的答案。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1698054409045.png" srcset="
/post/lm-graph-problems-natural-language/1698054409045_hu504f3e25b55bd5ba15d736a9ebae437e_200646_a8a5ae77c609fd8d4b6d3e1d3b45ccdf.webp 400w,
/post/lm-graph-problems-natural-language/1698054409045_hu504f3e25b55bd5ba15d736a9ebae437e_200646_2c38f700d49a37368dcb52912112c525.webp 760w,
/post/lm-graph-problems-natural-language/1698054409045_hu504f3e25b55bd5ba15d736a9ebae437e_200646_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/lm-graph-problems-natural-language/1698054409045_hu504f3e25b55bd5ba15d736a9ebae437e_200646_a8a5ae77c609fd8d4b6d3e1d3b45ccdf.webp"
width="760"
height="462"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h2 id="图生成">图生成&lt;/h2>
&lt;p>生成n个节点，每个节点间有边的概率设置为p。使用n和p来控制图的生成。对于个别的任务有更多的限制因子。&lt;/p>
&lt;h2 id="任务">任务&lt;/h2>
&lt;p>NLGraph包含8种任务&lt;/p>
&lt;ul>
&lt;li>
&lt;p>联通验证：询问两个点是否联通&lt;/p>
&lt;/li>
&lt;li>
&lt;p>图中是否存在环&lt;/p>
&lt;/li>
&lt;li>
&lt;p>拓扑排序&lt;/p>
&lt;/li>
&lt;li>
&lt;p>最短路&lt;/p>
&lt;/li>
&lt;li>
&lt;p>最大流&lt;/p>
&lt;/li>
&lt;li>
&lt;p>二分图匹配&lt;/p>
&lt;/li>
&lt;li>
&lt;p>哈密尔顿路&lt;/p>
&lt;/li>
&lt;li>
&lt;p>模拟图神经网络&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="统计">统计&lt;/h2>
&lt;p>基础版本包含5902个样例，拓展版本包含29370个样例。&lt;/p>
&lt;h1 id="实验设置">实验设置&lt;/h1>
&lt;h2 id="baseline">Baseline：&lt;/h2>
&lt;p>作者使用了多种Prompt作为baseline：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>ZERO-SHOT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>FEW-SHOT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>CoT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>0-CoT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>least-to-most (LTM-2023)：将一个大问题拆分成多个子问题逐个击破&lt;/p>
&lt;/li>
&lt;li>
&lt;p>self-consistency (SC-2023)：同一个问题多种问法，最后取最一致的结果&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>同时作者也将随机作为一种Baseline，例如对于是否的问题，Baseline设置为50%，对于最短路问题将随机选取的路径是否正确作为baseline。&lt;/p>
&lt;h2 id="models">Models：&lt;/h2>
&lt;p>TEXT-DAVINCI-003、GPT3/4&lt;/p>
&lt;h1 id="结论">结论&lt;/h1>
&lt;h2 id="大模型对图问题有初步的推理能力">大模型对图问题有初步的推理能力&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>在联通验证、是否存在环、最短路问题上LLM performance显著高于Random，说明大模型不是随机给的答案，具有初步推理能力。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用COT or COT+SC Prompt的准确率比Random准确率吧高了37.33%-57.82%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在联通验证、最短路问题上，使用ZERO-SHOT比Random准确率分别高了33.81%和23.33%&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在最短路问题上，COT and COT+SC比Random高了22.81%-62.83%&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="高级prompt不一定是有益的">高级Prompt不一定是有益的&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>高级Prompt如CoT，SC在大多数问题上提高了准确率&lt;/p>
&lt;/li>
&lt;li>
&lt;p>但是在复杂的图问题上，高级Prompt如COT, COT+SC, andLTM的效果反而低于Few-SHOT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>作者认为这种现象的原因是大模型无法生成复杂图问题的思考链&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="上下文prompt可能适得其反">上下文Prompt可能适得其反&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1698055792161.png" srcset="
/post/lm-graph-problems-natural-language/1698055792161_huf190611a72718e30715fe8539042b440_96291_a7938673582cb69f1aad9172082e95b2.webp 400w,
/post/lm-graph-problems-natural-language/1698055792161_huf190611a72718e30715fe8539042b440_96291_9b983cb6b8895ce05338b775cca50f5f.webp 760w,
/post/lm-graph-problems-natural-language/1698055792161_huf190611a72718e30715fe8539042b440_96291_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/lm-graph-problems-natural-language/1698055792161_huf190611a72718e30715fe8539042b440_96291_a7938673582cb69f1aad9172082e95b2.webp"
width="760"
height="314"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1698055805107.png" srcset="
/post/lm-graph-problems-natural-language/1698055805107_hud43d18fe55e4ba45109a16ffb52f7783_12839_4ac4946568c475b0e4ee387fec347c54.webp 400w,
/post/lm-graph-problems-natural-language/1698055805107_hud43d18fe55e4ba45109a16ffb52f7783_12839_221c235a1cb021fc8d76605ecb6a12c9.webp 760w,
/post/lm-graph-problems-natural-language/1698055805107_hud43d18fe55e4ba45109a16ffb52f7783_12839_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/lm-graph-problems-natural-language/1698055805107_hud43d18fe55e4ba45109a16ffb52f7783_12839_4ac4946568c475b0e4ee387fec347c54.webp"
width="701"
height="320"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;ul>
&lt;li>
&lt;p>在复杂图形推理问题上，如哈密尔顿路径和二分图匹配问题上，ZERO-SHOT的效果好于Few-SHOT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这可能是在复杂问题上，LLM无法从上下文中获得知识，反而会降低注意力&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="llms是不出奇地脆弱">LLMs是（不）出奇地脆弱&lt;/h2>
&lt;p>标题的意思是LLM有可能曲解了问题的推理过程。&lt;/p>
&lt;p>尽管LLM的效果很好，但是LLM可能通过利用某些虚假相关性来获得正确答案。举例来讲，由于更高度节点更常被提及且它们更有可能相连，语言模型可能只是计算节点出现次数而非实际查找路径。换言之，在连接性问题上，一些度特别多的点往往是相互连接的，这导致大模型可能人为度多的点就相互连接，而不是通过路径。&lt;/p>
&lt;p>于是作者特地设计了两组数据。&lt;/p>
&lt;h3 id="chain">Chain&lt;/h3>
&lt;p>将一张图分为k个部分，每个部分是一条独立的链，查询每个链的首节点和尾节点是否相连。首尾虽然是度最小的，但是却相连。&lt;/p>
&lt;h3 id="clique">Clique&lt;/h3>
&lt;p>建立k个稠密的独立子图。从不同的子图中选取两个点，由于是稠密图，因此这两个点的度都很高。但是由于独立，这两个点却不相连。&lt;/p>
&lt;p>不出意料的，LLM在这两个数据集上的performance下降了40%，证实了作者的猜想。&lt;/p>
&lt;h1 id="提高performance的两个方法">提高Performance的两个方法&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1698056360356.png" srcset="
/post/lm-graph-problems-natural-language/1698056360356_hu33ef9c02b962bb1d7ad6cfe6ef415abc_190365_008a01937721bf2f20642f3a5dbaa6d4.webp 400w,
/post/lm-graph-problems-natural-language/1698056360356_hu33ef9c02b962bb1d7ad6cfe6ef415abc_190365_bb52e1eb2d0947f457b60a436c5b5b16.webp 760w,
/post/lm-graph-problems-natural-language/1698056360356_hu33ef9c02b962bb1d7ad6cfe6ef415abc_190365_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/lm-graph-problems-natural-language/1698056360356_hu33ef9c02b962bb1d7ad6cfe6ef415abc_190365_008a01937721bf2f20642f3a5dbaa6d4.webp"
width="760"
height="414"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h2 id="build-a-graph-prompting-bag">Build-a-Graph Prompting (BAG)&lt;/h2>
&lt;p>作者认为将图的文本描述映射到实际概念空间可能会有帮助。因此加了一句“让我们首先构建一个带有节点和边的图”&lt;/p>
&lt;h2 id="algorithmic-prompting">Algorithmic Prompting&lt;/h2>
&lt;p>提示LLM可以使用一些具体的算法解决问题。比如告诉他使用DFS或者BFS来解决这个问题&lt;/p>
&lt;h2 id="result">Result&lt;/h2>
&lt;p>在简单问题上，作者的两个方法可以提高3.07%-16.85% 的Performance。但是对于复杂问题，没有提升。&lt;/p>
&lt;h1 id="总结">总结&lt;/h1>
&lt;h2 id="对比论文talk-like-a-graph-encoding-graphs-for-large-language-models">对比论文TALK LIKE A GRAPH： ENCODING GRAPHS FOR LARGE LANGUAGE MODELS&lt;/h2>
&lt;p>由于《TALK LIKE A GRAPH： ENCODING GRAPHS FOR LARGE LANGUAGE MODELS》在时间上更新，因此在下文简称为后者。而本文称为前者。&lt;/p>
&lt;h3 id="benchmark">BenchMark&lt;/h3>
&lt;p>在BenchMark上两篇文章互补，问题种类上存在交集&lt;/p>
&lt;h3 id="在prompt上">在Prompt上&lt;/h3>
&lt;p>后者相比于前者增加了Encoding部分&lt;/p>
&lt;p>在Prompt上两者各有区别，前者有LTM和SC两种Prompt，而后者有Bag prompting (COT-BAG)。不知道为什么后者遗弃了LTM、SC。&lt;/p>
&lt;h3 id="在实验上">在实验上&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>后者增加了模型容量对Performance 的影响&lt;/p>
&lt;/li>
&lt;li>
&lt;p>后者增加了图的形状的影响&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在简单图任务上，两者的ZERO-SHOT都好于ZERO-COT&lt;/p>
&lt;/li>
&lt;li>
&lt;p>两人都发现复杂图任务使用高级Prompt会降低LLM Performance&lt;/p>
&lt;/li>
&lt;li>
&lt;p>两者都认为将“图的文本描述映射到实际概念空间可能会有帮助”，前者只是加了一句“Let&amp;rsquo;s construct a graph with the nodes and edges first”，但是后者却真的将LLM在现实问题上进行了实验。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="在创新上">在创新上&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>前者的创新集中在数据集、实验设计、开创性上&lt;/p>
&lt;/li>
&lt;li>
&lt;p>后者的创新集中在将Encoding纳入变量上&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="question">Question&lt;/h2>
&lt;h3 id="solve">Solve&lt;/h3>
&lt;p>由于本人是先阅读的后者，因此对前者的工作此前没有了解过，故在后者的解析中提出了几个问题，在此回答一下&lt;/p>
&lt;ul>
&lt;li>
&lt;p>LLM在处理最短路问题上性能如何？其复杂度是否与环问题相同？&lt;/p>
&lt;ul>
&lt;li>
&lt;p>首先两个任务的性质是不同的，一个是找到正确路径，一个是True/False的问题&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在本文，最短路和环的难度并不一样。环被划分为基础问题，有三个难度分级。而最短路被划分为进阶问题，有两个难度分级。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="generated">Generated&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>类似于后者，还有哪些变量可以被挖掘出来做实验？&lt;/p>
&lt;ul>
&lt;li>
&lt;p>语言？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>点和边的数量上，小图$\rightarrow$大图&lt;/p>
&lt;/li>
&lt;li>
&lt;p>邻接矩阵表示图&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>树相关的经典问题似乎没有提及到&lt;/p>
&lt;ul>
&lt;li>
&lt;p>最小生成树&lt;/p>
&lt;/li>
&lt;li>
&lt;p>树的直径&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&amp;hellip;&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Tuning/Lora&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>论文解读 | TALK LIKE A GRAPH： ENCODING GRAPHS FOR LARGE LANGUAGE MODELS</title><link>https://geyuyao.com/post/talk-like-a-graph/</link><pubDate>Sat, 21 Oct 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/talk-like-a-graph/</guid><description>&lt;p>&lt;strong>institute:&lt;/strong> Google Research&lt;/p>
&lt;p>&lt;strong>authors:&lt;/strong> Bahare Fatemi, Jonathan Halcrow, Bryan Perozzi&lt;/p>
&lt;p>&lt;strong>link:&lt;/strong> &lt;a href="https://arxiv.org/abs/2310.04560" target="_blank" rel="noopener">https://arxiv.org/abs/2310.02207&lt;/a>&lt;/p>
&lt;h1 id="介绍">介绍：&lt;/h1>
&lt;p>本文尝试使用不同自然语言的方式将图输入大模型测试并测试性能&lt;/p>
&lt;h2 id="前言">前言：&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="image.png" srcset="
/post/talk-like-a-graph/image_hu02e2fad61fff912c806a4d42755f5d18_392821_abeb4f56ef02cee0947fe6a71ab064a3.webp 400w,
/post/talk-like-a-graph/image_hu02e2fad61fff912c806a4d42755f5d18_392821_9d05613e253d796b32678ce443788720.webp 760w,
/post/talk-like-a-graph/image_hu02e2fad61fff912c806a4d42755f5d18_392821_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/talk-like-a-graph/image_hu02e2fad61fff912c806a4d42755f5d18_392821_abeb4f56ef02cee0947fe6a71ab064a3.webp"
width="760"
height="215"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>目前学界有四种方法使用LLM处理图问题&lt;/p>
&lt;ol>
&lt;li>
&lt;p>使用自然语言输入&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Embedding&lt;/p>
&lt;/li>
&lt;li>
&lt;p>LLM tuning&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Hybrid : GNN &amp;amp; LLM&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>其中，本文主要探讨使用第一种方法处理图的问题。作者提到使用我们在本文中发现的规律来编码图可以使大模型的性能从4.8%提升至61.8%。&lt;/p>
&lt;h2 id="本文贡献">本文贡献&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>作者尝试找到一种最适合的方式使llm处理graph reasoning 问题，作者将此问题分成了下面的两个方面&lt;/p>
&lt;ol start="2">
&lt;li>
&lt;p>encoding&lt;/p>
&lt;/li>
&lt;li>
&lt;p>prompt&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>
&lt;p>提出了一组新的benchmarks &lt;strong>GraphQA&lt;/strong>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="encoding">Encoding：&lt;/h1>
&lt;p>Encoding graph as text 可以被分为两个部分，分别是对节点的编码和对边的编码。&lt;/p>
&lt;p>Encoding Nodes：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>整型表示&lt;/p>
&lt;/li>
&lt;li>
&lt;p>英文姓&lt;/p>
&lt;/li>
&lt;li>
&lt;p>影视剧角色&lt;/p>
&lt;/li>
&lt;li>
&lt;p>政客姓&lt;/p>
&lt;/li>
&lt;li>
&lt;p>字母表示&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Encoding Edges：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>圆括号表示&lt;/p>
&lt;/li>
&lt;li>
&lt;p>好友关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>共同作者关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>社交关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>箭头&lt;/p>
&lt;/li>
&lt;li>
&lt;p>连接.例：Node 0 is connected to nodes 1, 2.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>本文对图的编码就是对上述两种方式的排列组合：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Adjacency.：整型+圆括号表示&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Incident.：整型+连接&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Friendship.：英文姓+好友关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Co-authorship.：英文姓+共同作者关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>SP.：影视剧角色+好友关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>GOT.：影视剧角色+好友关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Social network.：英文姓+社交关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Politician.：政客姓+社交关系&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Expert.：字母表示+箭头&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1697950797666.png" srcset="
/post/talk-like-a-graph/1697950797666_hu6325ec6162427af0e7c21f48cf7c2ac8_125251_16b1dc3c2dda9f39ebf3d6f904a9e2bd.webp 400w,
/post/talk-like-a-graph/1697950797666_hu6325ec6162427af0e7c21f48cf7c2ac8_125251_a61e27aa5a0982b35ada41dc289c4191.webp 760w,
/post/talk-like-a-graph/1697950797666_hu6325ec6162427af0e7c21f48cf7c2ac8_125251_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/talk-like-a-graph/1697950797666_hu6325ec6162427af0e7c21f48cf7c2ac8_125251_16b1dc3c2dda9f39ebf3d6f904a9e2bd.webp"
width="760"
height="335"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h1 id="prompt">Prompt：&lt;/h1>
&lt;ol>
&lt;li>
&lt;p>Zero-shot prompting(ZERO-SHOT)：描述问题，直接提问&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Few-shot in-context learning (FEW-SHOT)：举例&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Chain-of-thought (CoT)：提供例子，以及解决问题的步骤&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Zero-shot CoT prompting (ZERO-COT)：给予解决问题的步骤，但是不给例子。“Let’s think step by step”&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Bag prompting (COT-BAG)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="graphqa">GraphQA&lt;/h1>
&lt;p>GraphQA包含多种图领域的基本问题&lt;/p>
&lt;ul>
&lt;li>
&lt;p>边存在&lt;/p>
&lt;/li>
&lt;li>
&lt;p>节点存在&lt;/p>
&lt;/li>
&lt;li>
&lt;p>节点计数&lt;/p>
&lt;/li>
&lt;li>
&lt;p>边计数&lt;/p>
&lt;/li>
&lt;li>
&lt;p>是否是连通图&lt;/p>
&lt;/li>
&lt;li>
&lt;p>环检查&lt;/p>
&lt;/li>
&lt;li>
&lt;p>是否是孤立点图&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="experiments">Experiments&lt;/h1>
&lt;h2 id="1-encoding--prompt">1. Encoding &amp;amp; Prompt&lt;/h2>
&lt;p>实现对象：PaLM 62B&lt;/p>
&lt;ul>
&lt;li>
&lt;p>大模型在图基础问题上表现很差&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对于简单的图的任务，ZERO-SHOT好于ZERO-COT，对于复杂任务则相反&lt;/p>
&lt;/li>
&lt;li>
&lt;p>不同的Encoding方法对性能影响很大&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用整型Encoding Nodes会提高性能&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="2varying-prompt-questions">2.Varying Prompt Questions&lt;/h2>
&lt;ul>
&lt;li>在绝大部分的实验中，将图问题编码成现实问题可以提高模型性能&lt;/li>
&lt;/ul>
&lt;h2 id="3多种关系编码">3.多种关系编码&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>使用多种关系对图编码不仅没有损害LLM的性能，反而提高了&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这种改进可能是因为多样化关系与LLM的训练集更接近&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="4模型容量">4.模型容量&lt;/h2>
&lt;ul>
&lt;li>模型容量显著影响性能&lt;/li>
&lt;/ul>
&lt;h2 id="5孤立图推理">5.孤立图推理&lt;/h2>
&lt;ul>
&lt;li>接近于0.LLM对于孤立图几乎没有推理能力&lt;/li>
&lt;/ul>
&lt;h2 id="6图的形状是否有影响">6.图的形状是否有影响&lt;/h2>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1697955235299.png" srcset="
/post/talk-like-a-graph/1697955235299_hu295a6d321f042d77c91d1fe056d7fedf_113069_21a3d37be40b5837702d144089db037c.webp 400w,
/post/talk-like-a-graph/1697955235299_hu295a6d321f042d77c91d1fe056d7fedf_113069_2f77dde521b0001ad66aac9b5897fe9d.webp 760w,
/post/talk-like-a-graph/1697955235299_hu295a6d321f042d77c91d1fe056d7fedf_113069_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/talk-like-a-graph/1697955235299_hu295a6d321f042d77c91d1fe056d7fedf_113069_21a3d37be40b5837702d144089db037c.webp"
width="760"
height="156"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;ul>
&lt;li>
&lt;p>图的结构显著影响LLM性能&lt;/p>
&lt;/li>
&lt;li>
&lt;p>图中多余的结构会影响LLM性能：LLM在Path和Star结构的图上的性能最好&lt;/p>
&lt;/li>
&lt;li>
&lt;p>提供实例和推理链可以提高LLM性能&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="结论">结论&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>LLM在基础图问题上表现很差&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Graph Encoding方式显著影响LLM性能&lt;/p>
&lt;/li>
&lt;li>
&lt;p>模型参数量对精度影响显著&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="thinking">Thinking&lt;/h1>
&lt;ol>
&lt;li>
&lt;p>模型上&lt;/p>
&lt;p>a. 在6B、7B模型上的表现如何？&lt;/p>
&lt;p>b. 适应小模型的Encoding方式&lt;/p>
&lt;p>c. Emergence Feature为什么没有在图问题上出现？&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1697957401519.png" srcset="
/post/talk-like-a-graph/1697957401519_hu9617bce70174b13b7fbeac0fecb86da4_100731_8ba8ab1c7071da43393eb8ceee3d058b.webp 400w,
/post/talk-like-a-graph/1697957401519_hu9617bce70174b13b7fbeac0fecb86da4_100731_7a3d8da967be5be7f04bd1be4e1b6986.webp 760w,
/post/talk-like-a-graph/1697957401519_hu9617bce70174b13b7fbeac0fecb86da4_100731_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/talk-like-a-graph/1697957401519_hu9617bce70174b13b7fbeac0fecb86da4_100731_8ba8ab1c7071da43393eb8ceee3d058b.webp"
width="760"
height="587"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;/li>
&lt;li>
&lt;p>实验所用到的图主要是小图&lt;/p>
&lt;p>a. LLM的性能与图的大小是呈怎样的关系？&lt;/p>
&lt;p>b. 能否设计出一种针对大图的输入方式？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>为什么LLM在处理现实的图问题上表现要更好？这种现象是否存在于其他问题？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>能否使用Lora/对Lora Tuning的方式改进大模型的性能？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>为什么没有与Embedding的方式进行对比？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>LLM在处理最短路问题上性能如何？其复杂度是否与环问题相同？&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>论文解读 | LANGUAGE MODELS REPRESENT SPACE AND TIME</title><link>https://geyuyao.com/post/language-models-space-time/</link><pubDate>Wed, 11 Oct 2023 00:00:00 +0000</pubDate><guid>https://geyuyao.com/post/language-models-space-time/</guid><description>&lt;h1 id="介绍">介绍&lt;/h1>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/language-models-space-time/0_hu0acef256e944c0f868092f682b01bdf8_412123_ffb7e3dac81177bf904517cb2f300a51.webp 400w,
/post/language-models-space-time/0_hu0acef256e944c0f868092f682b01bdf8_412123_ad154cc1a733832db35ff9b324b56c8f.webp 760w,
/post/language-models-space-time/0_hu0acef256e944c0f868092f682b01bdf8_412123_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/language-models-space-time/0_hu0acef256e944c0f868092f682b01bdf8_412123_ffb7e3dac81177bf904517cb2f300a51.webp"
width="760"
height="324"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>大语言模型诸多惊人的能力难道只是海量数据统计的结果吗？大语言模型的内部是否存在一个世界模型？近日，MIT的两位作者在Arxiv上发布的论文《&lt;strong>LANGUAGE MODELS REPRESENT SPACE AND TIME&lt;/strong>》引发了学界的广泛关注。在这篇文章中，作者以llama2系列为实验对象，在自制的时空数据集上进行了实验，发现了后者存在的证据。&lt;/p>
&lt;p>在这篇文章中作者产出了六个贡献，其中包含四个大贡献和两个小贡献。&lt;/p>
&lt;p>主要贡献：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>产出了三个空间数据集和三个时间数据集&lt;/p>
&lt;/li>
&lt;li>
&lt;p>证明LLMs对时空的表达是存在的且与模型、数据集有关&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这种表达是线性的&lt;/p>
&lt;/li>
&lt;li>
&lt;p>这种表达对prompt的改变具有鲁棒性&lt;/p>
&lt;/li>
&lt;li>
&lt;p>鲁棒性检测&lt;/p>
&lt;/li>
&lt;li>
&lt;p>时间和空间神经元&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>第一个贡献是产出了六个数据集，工作量达标。&lt;/p>
&lt;p>第二至四个贡献是侧面发现了LLMs内部存在世界模型的证据。在此之前，前人仅在小模型上进行过类似的实验。&lt;/p>
&lt;p>第五个和第六个实验，笔者认为，是为了实验的严谨性和凑创新点。尤其是第六个，说存在”空间神经元“和”时间神经元“难免有搞噱头、博眼球之嫌。&lt;/p>
&lt;p>为方便读者理解，在读者开始阅读之前，笔者需要对几个名词进行解释。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>文中出现的“&lt;strong>表达&lt;/strong>”在原文中是“representation”，笔者认为作者用这个词想表达的是LLMs内部隐藏层的状态。举例来讲，引述中提到的“LLMs对时间和空间的表达都是线性的”在原文中对应的实验为使用LLMs内部的隐藏层状态到$label$的映射是线性的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>文中出现的“&lt;strong>实体&lt;/strong>”在原文中对应的是“entity”，这个词在原文中有“sample”之意，代表数据集中的一个样例。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>文中玄乎的所谓的“&lt;strong>世界模型&lt;/strong>”到底是什么？如果LLMs仅仅是对一段文字可能出现的下一个字进行预测，那么LLMs内部就不存在”世界模型“。反之，如果能找到LLMs内针对时空的结构化存储的证据，就可以说LLMs内部存在”世界模型“。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>作者在本文中主要应用“&lt;strong>探针&lt;/strong>”进行的实验，探针在原文中用“probe”表达。设输入为$X$，大模型输出为$Y$，隐藏层状态$h$。用$h$为feature，$Y$为label训练一个浅层小模型，这个浅层小模型就是探针——probe。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>“&lt;strong>时空&lt;/strong>”是对“时间和空间”的简写。在本文中空间的表达有“spatial“和”space“，时间的表达有”temporal“和”time“&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="论文解析">论文解析&lt;/h1>
&lt;h2 id="摘要">摘要&lt;/h2>
&lt;p>大语言模型（LLM）的领军位置引发了大模型系统到底只是对海量数据进行肤浅地统计还是真正学习到了世界模型的争论。在本文，作者以llama2为实验对象，在三个空间数据集和三个时间数据集上进行了实验发现了后者存在的证据。作者发现不同参数量的LLMs对时间和空间的表达都是线性的；LLMs对时间和空间的表达对prompt的改变具有鲁棒性；这些表达是跨实体类型的（例如城市和地标）；发现了“空间神经元”和“时间神经元”。&lt;/p>
&lt;h2 id="起因">起因&lt;/h2>
&lt;p>虽然LLMs的出现引发了世界各界的广泛关注，但是人们对LLMs内部的细节理解十分有限。LLMs的运行过程是对海量数据进行统计还是经过思考的，自LLMs诞生起就争论不休。&lt;/p>
&lt;p>在本文，作者从时间和空间的角度试图解释这个问题。&lt;/p>
&lt;h2 id="准备工作">准备工作&lt;/h2>
&lt;h3 id="数据集">数据集&lt;/h3>
&lt;p>作者创建了六个数据集，其中三个是空间数据集，三个是时间数据集。对于每一个数据集中的每个实体，由一个名字和对应位置或时间构成的。三个空间数据集分别由世界、美国、纽约的地名构成。三个时间数据集分别由历史人物、作品、新闻构成。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>数据集&lt;/th>
&lt;th>样例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>世界&lt;/td>
&lt;td>洛杉矶，圣彼得堡，里海&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>美国&lt;/td>
&lt;td>芬威球场，哥伦比亚，河滨县（位于加州）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>纽约&lt;/td>
&lt;td>波登大道大桥，特朗普国际酒店&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>人物&lt;/td>
&lt;td>Cleopatra（埃及艳后），Dante Alighieri（但丁），Carl Sagan（卡尔·萨根）&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>作品&lt;/td>
&lt;td>小丑回魂，波西米亚狂想曲&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新闻&lt;/td>
&lt;td>略&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="模型">模型&lt;/h3>
&lt;p>llama2 family&lt;/p>
&lt;h3 id="激活数据集">激活数据集&lt;/h3>
&lt;p>设某数据集中具有n个实体，LLM有$d_{model}$层。那么将n个实体分别输入LLM，在各隐藏层检测激活状态并记录，即可获得&lt;strong>激活状态数据集&lt;/strong>$A\in\mathbb{R}^{n\times d_{model}}$。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/language-models-space-time/1_hue37acbb3f56b6b46d3ee5f803142d09f_254777_a5dd6228ef3d494a38cde73f239cf72b.webp 400w,
/post/language-models-space-time/1_hue37acbb3f56b6b46d3ee5f803142d09f_254777_f6749acfd7769811a857c970206b5da2.webp 760w,
/post/language-models-space-time/1_hue37acbb3f56b6b46d3ee5f803142d09f_254777_1200x1200_fit_q99_h2_lanczos.webp 1200w"
src="https://geyuyao.com/post/language-models-space-time/1_hue37acbb3f56b6b46d3ee5f803142d09f_254777_a5dd6228ef3d494a38cde73f239cf72b.webp"
width="687"
height="621"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h3 id="探针">探针&lt;/h3>
&lt;p>作者将地名或人名等作为输入$x$输入大模型$model$。用隐藏层状态$h$作为$feature$，用$x$对应的$y$作为$label$，训练探针，并在测试集上测试探针的性能。&lt;/p>
&lt;blockquote>
&lt;p>Understanding intermediate layers using linear classifier probes.
Probing classifiers: Promises, shortcomings, and advances.&lt;/p>
&lt;/blockquote>
&lt;h3 id="评估标准">评估标准&lt;/h3>
&lt;p>$R^2$ &amp;amp; Spearman rank&lt;/p>
&lt;h2 id="主要实验设计及结果">主要实验设计及结果&lt;/h2>
&lt;h3 id="1-llms内部是否存在针对时空的表达如果有在哪里跟模型的参数量是否有关系">1. LLMs内部是否存在针对时空的表达？如果有，在哪里？跟模型的参数量是否有关系？&lt;/h3>
&lt;p>作者用从自制六个数据集得到的六个激活状态数据集训练探针，然后将探针在测试集上进行实验，获得了探针在不同参数量的LLM上、不同层深度上、不同数据集上的精度。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/language-models-space-time/2_hu2f9399fec2b6957abecebda8ce813a8e_294298_ff91e585680363253a3f38bd42e3e6ca.webp 400w,
/post/language-models-space-time/2_hu2f9399fec2b6957abecebda8ce813a8e_294298_e4d6653c068e6777e64972d454ad8cd2.webp 760w,
/post/language-models-space-time/2_hu2f9399fec2b6957abecebda8ce813a8e_294298_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/language-models-space-time/2_hu2f9399fec2b6957abecebda8ce813a8e_294298_ff91e585680363253a3f38bd42e3e6ca.webp"
width="760"
height="384"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>作者从上图得到了五个发现。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>时空feature都可以被线性探针拟合&lt;/p>
&lt;/li>
&lt;li>
&lt;p>模型参数量越大，探针精度越高&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在前50%层精度平滑上升&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在三个空间数据集中，NYC的表现最差。作者猜测是因为NYC的地图范围较小，很多的地名都是默默无闻的，因此大模型不认识&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在NYC地图中，模型参数量带来的精度差距最为明显&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>笔者认为从逐步上升的曲线就可以看出，模型内部关于时空信息的表达是有一定结构性的规律的，以至于可以被探针学习到。同时，第四个和五个发现侧面印证了模型内存在知识库或存储库的可能。&lt;strong>如果这个可能可以被证实，大模型或许可以作为一种数据压缩的手段&lt;/strong>。&lt;/p>
&lt;h3 id="2-llms对时空信息的表达是否是线性的">2. LLMs对时空信息的表达是否是线性的？&lt;/h3>
&lt;p>作者在这里首先叠了一下甲，阐明自己相比前人的创新点。作者说虽然前人有一些工作证明在神经网络内部线性表达的假说，但是前人的工作是针对二分类或多分类等离散任务的，而本文任务的label是连续的。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/language-models-space-time/3_hu6907df4d2c48b4c5e900a673861b3418_73906_d93098147b1874b46c62d05f22f18667.webp 400w,
/post/language-models-space-time/3_hu6907df4d2c48b4c5e900a673861b3418_73906_0065f17e2b9b9de9024722ceb6dde2ea.webp 760w,
/post/language-models-space-time/3_hu6907df4d2c48b4c5e900a673861b3418_73906_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/language-models-space-time/3_hu6907df4d2c48b4c5e900a673861b3418_73906_d93098147b1874b46c62d05f22f18667.webp"
width="760"
height="210"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>作者分别训练简单的线性探针和非线性的MLP探针并在测试集上进行测试，对比上图发现两个探针的精度差异几乎不存在。对一个映射关系$f$，如果它是线性的，那么线性模型和非线性模型都可以很好地拟合且性能差距较小。如果它是非线性的，那么线性模型拟合效果要差于非线性模型。因此作者认为$h$到$label$的映射关系是线性的。也就是文中所说的“LLM对时间和空间的表达是线性的”。&lt;/p>
&lt;h3 id="3-对prompt的敏感性">3. 对prompt的敏感性&lt;/h3>
&lt;p>为了验证时空表达对prompt的变化是否敏感作者设计了此实验。&lt;/p>
&lt;p>对于除新闻外的五个数据集，作者设计了如下四种prompt。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>empty：无其他prompt&lt;/p>
&lt;/li>
&lt;li>
&lt;p>coords/when：添加“What is the latitude and longitude of &lt;place>” or “What was the release date of &lt;author>’s &lt;book>.”等描述性和消歧性的prompt和几乎不会降低性能&lt;/p>
&lt;/li>
&lt;li>
&lt;p>baseline：添加10个随机tokens&lt;/p>
&lt;/li>
&lt;li>
&lt;p>all_cap：全大写&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>新闻数据集，作者设计了如下四种prompt。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>empty prompt&lt;/p>
&lt;/li>
&lt;li>
&lt;p>加句号&lt;/p>
&lt;/li>
&lt;li>
&lt;p>添加述性和消歧性的prompt&lt;/p>
&lt;/li>
&lt;li>
&lt;p>添加述性和消歧性的prompt的基础上加句号&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/post/language-models-space-time/4_hue44053098355c970e8bc2b5467bd0327_353157_edc3792a8e812db26c10d03608a7d449.webp 400w,
/post/language-models-space-time/4_hue44053098355c970e8bc2b5467bd0327_353157_aa03916c1d70ea352e70fcfdc5cd8127.webp 760w,
/post/language-models-space-time/4_hue44053098355c970e8bc2b5467bd0327_353157_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/language-models-space-time/4_hue44053098355c970e8bc2b5467bd0327_353157_edc3792a8e812db26c10d03608a7d449.webp"
width="760"
height="367"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>观察上图，作者发现如下现象&lt;/p>
&lt;ol>
&lt;li>
&lt;p>empty和添加述性和消歧性的prompt在精度上几乎没有区别&lt;/p>
&lt;/li>
&lt;li>
&lt;p>baseline的精度很低，random tokens可以显著降低精度&lt;/p>
&lt;/li>
&lt;li>
&lt;p>大写也会降低精度，但是并不令人吃惊，因为已经有前人的发现了此现象&lt;/p>
&lt;/li>
&lt;li>
&lt;p>新闻数据集中加句号可以显著提高精度&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>整体而言，时空表达对prompt具有相当的鲁棒性。&lt;/p>
&lt;h3 id="不足">不足&lt;/h3>
&lt;p>作者在结尾提到本文还存在一些不足&lt;/p>
&lt;ol>
&lt;li>
&lt;p>可以使用离散的编码器来提取模型的时空表达&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在数据集中并不是所有的实体大模型都认识，按理说应该剔除&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h1 id="读后感">读后感&lt;/h1>
&lt;p>笔者读完的第一个感受就是”就这？“，虽然本文在贡献和创新上都比较突出，但是和媒体宣传的”世界模型“相比，难免有”标题党“之嫌。当然，当”标题党“未必是作者的本意，也可能是有些媒体为了蹭热度而为。&lt;/p>
&lt;p>在贡献上，光数据集的收集、制作、整理就满足一篇顶会的工作量，更不用说将探针部署在多个LLM的每一层上，在工作量上相比起同类论文足以遥遥领先。在创新上，本文并没有在方法上太大的创新，而是将过去小模型上的常规手段搬到大模型上。本文的发现虽然没有标题党们宣传的那么玄乎，但是LLMs对时空的线性表达这一发现足以满足一篇顶会论文的创新性。&lt;/p>
&lt;p>在内容上，本文是一篇标准的”实验报告“，没有数学证明也没有公式推导，有的只有设计实验、进行试验、结果分析。&lt;/p>
&lt;p>在语言上，本文的用词和写作很讲究。笔者作为一个中国人读起来比较吃力，和读中国人写的文章感受完全不同。&lt;/p>
&lt;p>综上，本文是一篇远超顶会及格线的论文，但是达不到标题党们宣传的证明”世界模型“的标准。&lt;/p></description></item><item><title>llama模型量化报告(二)</title><link>https://geyuyao.com/post/llama-quantization-part2/</link><pubDate>Fri, 11 Aug 2023 23:39:01 +0000</pubDate><guid>https://geyuyao.com/post/llama-quantization-part2/</guid><description>&lt;h1 id="零-任务概述">零. 任务概述&lt;/h1>
&lt;ol>
&lt;li>深入研究LLM.int8方法、&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;p>阅读&lt;a href="https://arxiv.org/pdf/2110.02861.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2110.02861.pdf&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;del>了解emergent feature现象&lt;a href="https://arxiv.org/pdf/2208.07339.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2208.07339.pdf&lt;/a>&lt;/del>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;del>在论文《LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale》中int8 absmax和zeropoint具体是什么含义？&lt;/del>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;del>作者设计这种方法的灵感来自于哪里？&lt;/del>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;del>对于猜测“outliers”的存在是为了使模型提取特征是否成立？如果成立仅保留outliers会有多少的精度损失？能否设计一种方法保留一定比例的非outliers以平衡性能损失和模型对计算资源的占用？&lt;/del>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>llama.cpp背后的算法是什么？&lt;a href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener">https://github.com/ggerganov/llama.cpp&lt;/a>&lt;/li>
&lt;/ol>
&lt;h1 id="8-bit-optimizers-via-block-wise-quantization">8-BIT OPTIMIZERS VIA BLOCK-WISE QUANTIZATION&lt;/h1>
&lt;p>Author：&lt;a href="https://timdettmers.com/" target="_blank" rel="noopener">Tim Dettmers&lt;/a>&lt;/p>
&lt;p>提出的一种对 optimizer 进行量化的方法，在不修改超参，不影响模型精度的情况下，把 adam / momentum 的状态量量化至 int8，从而缓解训练时的显存压力。&lt;/p>
&lt;p>与项目关系不大&lt;/p>
&lt;h1 id="llmint8-8-bit-matrix-multiplication">LLM.int8(): 8-bit Matrix Multiplication&lt;/h1>
&lt;p>for Transformers at Scale&lt;/p>
&lt;p>Author：&lt;a href="https://timdettmers.com/" target="_blank" rel="noopener">Tim Dettmers&lt;/a>&lt;/p>
&lt;h2 id="零-background">零. Background：&lt;/h2>
&lt;h3 id="absmax-quantization">&lt;strong>Absmax quantization：&lt;/strong>&lt;/h3>
&lt;p>最简单的量化手段，可以实现fp16$\rightarrow$int8。&lt;/p>
&lt;p>简单来讲就是将fp16映射至[-127,127]的int8整数。&lt;/p>
&lt;p>比方说有一组fp16的向量[-100,0,50,100]，经过Absmax量化后，100对应127，50对应63.5，0对应0，-100对应-98.73。&lt;/p>
&lt;p>它的问题在于&lt;strong>如果向量中出现取值较大的outliers就会导致其他的值在量化后被磨除。&lt;/strong>&lt;/p>
&lt;p>例如，当向量为[-0.10, -0.23, 0.08, -0.38, -0.28, -0.29, -2.11, 0.34, -0.53, -67.0]时，经int8量化和反量化处理后向量变为[ -0.00, -0.00, 0.00, -0.53, -0.53, -0.53, -2.11, 0.53, -0.53, -67.00]可见大部分信息在处理后都丢失了。&lt;/p>
&lt;h3 id="zeropoint-quantization">&lt;strong>Zeropoint quantization：&lt;/strong>&lt;/h3>
&lt;p>和Absmax思路类似，区别就是Absmax是非对称的，而这个方法是对称的。&lt;/p>
&lt;p>以向量[-100,0,50,100]为例，经过Zeropoint量化后，100对应127，50对应63.5，0对应0，-100对应-127。&lt;/p>
&lt;p>两种方法在&lt;strong>思路&lt;/strong>、&lt;strong>性能&lt;/strong>、&lt;strong>精度&lt;/strong>上没有区别且都&lt;strong>没有解决outliers的问题&lt;/strong>。&lt;/p>
&lt;h3 id="llmint8">LLM.int8：&lt;/h3>
&lt;p>作者首先使用了上述两种方法对模型进行量化，但是发现精度下降严重，于是希望找到一种既可以保证精度又可以减少memery占用的方法。&lt;/p>
&lt;blockquote>
&lt;p>经过实验作者发现在矩阵 $\textbf{X}_{f16}\in\mathbb{R}^{s\times h}$中存在outliers，这些outliers存在于所有的sequence维度s中但是在feature/hidden维度h中的分布却是有规律的。&lt;/p>
&lt;/blockquote>
&lt;p>基于&lt;a href="https://flowus.cn/61f7e285-74d6-4ff9-bb9f-15b38feabb58#80ff2cef-177a-4b6a-ba0c-57991f54c07c" target="_blank" rel="noopener">此现象&lt;/a>作者想到将存在outliers的维度分离出来进行fp16乘法，其他的维度进行int8乘法。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="1.png" srcset="
/post/llama-quantization-part2/1_hu72abf803e9c42b4ce83921f8d42d5bda_142267_d37f1bdb3eff015039955607f14f6b95.webp 400w,
/post/llama-quantization-part2/1_hu72abf803e9c42b4ce83921f8d42d5bda_142267_82cf3ec5c92e708b1f33394b8e637231.webp 760w,
/post/llama-quantization-part2/1_hu72abf803e9c42b4ce83921f8d42d5bda_142267_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/llama-quantization-part2/1_hu72abf803e9c42b4ce83921f8d42d5bda_142267_d37f1bdb3eff015039955607f14f6b95.webp"
width="760"
height="315"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>&lt;strong>如何定义outliers:&lt;/strong>&lt;/p>
&lt;p>作者设置了一个阈值$\alpha$，超过$\alpha$的值被定义为outliers，而存在outliers的维度需要进行fp16乘法。经过实验，作者发现$\alpha$设置为6及以上可以保证精度不下降。
当$\alpha$被设置为6的时候，有99.9%的维度会进行int8量化，而其余存在outliers的0.1%的维度不会进行量化。对于一个13B的模型，存在outliers的维度不超过7。将矩阵进行拆分的操作会额外占用0.1%的存储空间。&lt;/p>
&lt;h2 id="一-emergent-feature">一. Emergent feature&lt;/h2>
&lt;h3 id="定义">定义：&lt;/h3>
&lt;p>原文是&amp;quot;&lt;em>Emergence is a gradual change in a property that suddenly undergoes a phase shift and then changes the quality of its substrate.&lt;/em>&amp;quot;，白话文是“transformer经历了一种逐渐的变化，然后突然发生相移，之后产生了本质的变化”，用中文表达就是“量变引起质变”。在这个过程中，改变的是模型参数量。&lt;/p>
&lt;h3 id="发现">发现：&lt;/h3>
&lt;p>在了解这个过程之前作者介绍了transformer中的两个主线。第一条主线是，神经网络在逐渐提取特征。第二条主线是，神经网络在去除嘈杂的、与上下文无关的特征。用一个例子来解释这个现象：当你想对猫狗进行分类，你可以使用锐化方法，锐化可以突出动物间不同的特征（眼睛，耳朵），也可以去去除相似特征（颜色，潜在的纹理）。transformer也是这个原理。在推理的过程中，&lt;strong>transformer会去掉99%无用的信息，仅保留1%有用的信息。&lt;/strong>&lt;/p>
&lt;p>在发生&lt;strong>质变&lt;/strong>之前，各个层使用&lt;strong>不同的维度&lt;/strong>来突出重要特征。但是当&lt;strong>质变&lt;/strong>发生之后，各个层&lt;strong>使用相同的六个维度&lt;/strong>来突出这些特征。&lt;/p>
&lt;p>总结来讲就是：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>当模型的参数达到6.7B之前，outliers分布在个别层的不同维度中，分布没有规律。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>当模型的参数达到6.7B时，outliers的&lt;strong>值陡然升高&lt;/strong>且&lt;strong>忽然出现在所有层中&lt;/strong>，且是&lt;strong>仅出现在相同的六个维度&lt;/strong>。这也解释了为什么以往的量化方法不能应用于大模型：因为自6.7B开始出现了大量的outliers，而以往的量化方法无法很好的处理outliers。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>值陡然升高&lt;/strong>：6B时最大值是15，13B时最大值时60，66B时最大值时95。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>忽然出现在所有层中&lt;/strong>：在6.7B之前不同层使用不同的维度来放大特征。但是6.7B之后，所有的层共同协作来放大特征。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>仅出现在相同的六个维度&lt;/strong>：意味着注意力变得集中。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="2" srcset="
/post/llama-quantization-part2/2_huf3009565e042ecf34e44ad3f4c25b0c9_66302_08154c0e6a3200f5e0f0d2078ddcccc6.webp 400w,
/post/llama-quantization-part2/2_huf3009565e042ecf34e44ad3f4c25b0c9_66302_9d413df47d0a94861b2e1a4ac6fe46af.webp 760w,
/post/llama-quantization-part2/2_huf3009565e042ecf34e44ad3f4c25b0c9_66302_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/llama-quantization-part2/2_huf3009565e042ecf34e44ad3f4c25b0c9_66302_08154c0e6a3200f5e0f0d2078ddcccc6.webp"
width="760"
height="621"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
x轴是模型参数量，y轴是outliers影响的层的百分比。
从本图可以看到当参数量在6.7B之前，outliers仅出现在部分层中。
但是当参数量达到6.7B之后，发生了质变，它几乎出现在所有的层中。&lt;/p>
&lt;h2 id="二-反思">二. 反思：&lt;/h2>
&lt;ol>
&lt;li>Emergent feature是否只与参数量有关？
并不是，Emergent feature与ppl也有关系。&lt;/li>
&lt;/ol>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="3" srcset="
/post/llama-quantization-part2/3_hu4db7a533efe3907cd30caace30983c46_139521_1e7be55c895297b4430700d2af28fa03.webp 400w,
/post/llama-quantization-part2/3_hu4db7a533efe3907cd30caace30983c46_139521_8f24db4cd0e2f78e35d20e1ad48b1714.webp 760w,
/post/llama-quantization-part2/3_hu4db7a533efe3907cd30caace30983c46_139521_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/llama-quantization-part2/3_hu4db7a533efe3907cd30caace30983c46_139521_1e7be55c895297b4430700d2af28fa03.webp"
width="760"
height="323"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
左图是Emergent feature与参数量的关系，可以看到出现了质变。
右图是Emergent feature与ppl的关系，可以看到呈单调指数增加。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="4" srcset="
/post/llama-quantization-part2/4_huef32e0d421f23cce7ebeb813159cdbdd_77063_00c27636856fd556eadf463dd2d1278d.webp 400w,
/post/llama-quantization-part2/4_huef32e0d421f23cce7ebeb813159cdbdd_77063_953ac3888354ceb2fb885e04003e43f3.webp 760w,
/post/llama-quantization-part2/4_huef32e0d421f23cce7ebeb813159cdbdd_77063_1200x1200_fit_q99_h2_lanczos_3.webp 1200w"
src="https://geyuyao.com/post/llama-quantization-part2/4_huef32e0d421f23cce7ebeb813159cdbdd_77063_00c27636856fd556eadf463dd2d1278d.webp"
width="760"
height="295"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
左图是outliers的中位数值与ppl的关系，可以看到当Emergent发生时，中位数显著上升。
右图时outliers数量与ppl的关系，随着ppl的降低，outliers数量也在增加。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>为什么一般的量化方法如int8系列方法中的zeropoint和absmax在大模型中不适用？
因为随着参数量的增加，outliers的数量也在增加，而一般的量化方法遇到outliers就会出现严重的精度损失。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>总结一下质变发生时的现象&lt;/p>
&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;p>outliers会出现在所有的层中&lt;/p>
&lt;/li>
&lt;li>
&lt;p>outliers规律性的分布在几个维度中&lt;/p>
&lt;/li>
&lt;li>
&lt;p>outliers的值陡然上升&lt;/p>
&lt;/li>
&lt;li>
&lt;p>outliers的数量也增加&lt;/p>
&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>能否去除除outliers外的其他维度？
不可以。作者在博客中说到，如果你去除了视觉模型中95%的参数，模型的精度不会受到严重的应先向，但是在NLP的transformer模型中这个数字是30%。而当Emergent发生后，这个数字是5%。&lt;/li>
&lt;/ol></description></item><item><title>llama模型量化报告(一)</title><link>https://geyuyao.com/post/llama-quantization-part1/</link><pubDate>Fri, 04 Aug 2023 21:12:03 +0000</pubDate><guid>https://geyuyao.com/post/llama-quantization-part1/</guid><description>&lt;h2 id="零-任务概述">零. 任务概述&lt;/h2>
&lt;p>全部任务：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>了解现有的大模型，以及基于llama 的模型量化相关知识&lt;/p>
&lt;/li>
&lt;li>
&lt;p>了解量化的相关工具&lt;/p>
&lt;/li>
&lt;li>
&lt;p>做量化对比实验：效果，性能&lt;/p>
&lt;/li>
&lt;li>
&lt;p>实验评测：效果（人工？自动化？&amp;hellip;），性能（速度，没量化前占的显存-&amp;gt;量化后）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>汇总，下结论&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>本文完成任务：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>了解现有的大模型，以及基于llama 的模型量化相关知识&lt;/p>
&lt;/li>
&lt;li>
&lt;p>了解量化的相关工具&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="一-现有的大模型技术">一. 现有的大模型技术&lt;/h2>
&lt;p>目前对大模型的开发的主要方法是&lt;strong>Foundation Model+Prompt工程&lt;/strong>，前者由互联网大厂开源提供，后者由开发者针对不同的业务场景进行定制开发。&lt;/p>
&lt;p>目前主流的大模型底座包括由&lt;strong>Meta&lt;/strong>提供的&lt;strong>Llama&lt;/strong>模型等。&lt;/p>
&lt;p>其中llama系列提供了四种规格的模型，分别是7B，13B，33B和65B。&lt;/p>
&lt;p>本项目使用的底座为llama33B模型。&lt;/p>
&lt;h2 id="二-量化相关知识">二. 量化相关知识&lt;/h2>
&lt;p>Q1.什么是量化？&lt;/p>
&lt;p>量化是指将信号的连续取值近似为有限多个离散值的过程。是一种模型压缩手段。&lt;/p>
&lt;p>Q2.为什么要量化？&lt;/p>
&lt;p>目前服务对显存的占用大，在高并发的环境下可能会导致服务崩溃。因此，需要对模型进行量化节省显存和带宽。&lt;/p>
&lt;p>Q3.量化手段有几类？&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>二值化&lt;/strong>使用位运算实现并行计算的目的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>对数量化&lt;/strong>没有看到有在三大平台上实现对数量化的加速库，可能其实现的加速效果不明显。只有一些专用芯片上使用了对数量化。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>线性量化&lt;/strong>线性量化采用均匀分布的聚类中心，原始浮点数据和量化后的定点数据存在一个简单的线性变换关系，是最常用的量化手段。例如，韩松在ICLR2016上获得best paper的论文首次提出了参数量化的手段，即使用聚类算法将相近数值归为一类，复用一个数值达到量化的目的。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>但上述三种手段似乎并不能在大模型上使用。&lt;/p>
&lt;h2 id="三-量化手段介绍">三. 量化手段介绍&lt;/h2>
&lt;h3 id="1-llmint8量化">1. LLM.int8量化&lt;/h3>
&lt;p>2022年由来自华盛顿大学的博士Tim Dettmers提出。&lt;/p>
&lt;p>论文地址：&lt;a href="https://arxiv.org/pdf/2208.07339.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2208.07339.pdf&lt;/a>&lt;/p>
&lt;p>Github链接：&lt;a href="https://github.com/timdettmers/bitsandbytes" target="_blank" rel="noopener">https://github.com/timdettmers/bitsandbytes&lt;/a>&lt;/p>
&lt;h4 id="1-int8方法介绍">(1) int8方法介绍&lt;/h4>
&lt;p>在了解LLM.int8量化之前需要先了解int8量化。
int8量化的主要思想就是将浮点数FP16映射到8位int范围内，即[-127,127]。
设我们有需要量化的向量$\mathbf{x} : [1.2, -0.5, -4.3, 1.2, -3.1, 0.8, 2.4, 5.4]$，首先找到其中最大值 $max(\mathbf{x}) = 5.4$，然后算出量化系数 $\alpha = 127/5.4 = 23.5$。然后将向量中每个元素都与$\alpha$相乘得到量化后的向量$\mathbf{x&amp;rsquo;} : [28, -12, -101, 28, -73, 19, 56, 127]$。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./1.jpg" alt="1.jpg" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>&lt;a href="https://flowus.cn/737727b2-9344-4972-8073-c40202e3bab4#54618e2f-6b4e-4946-a2be-685a44a66955" target="_blank" rel="noopener">上文&lt;/a>介绍了如何对单个int8向量进行量化，但是当向量中出现&lt;strong>离群值(Emergent Features)&lt;/strong> 时int8量化方法就会出现问题。例如，当向量为[-0.10, -0.23, 0.08, -0.38, -0.28, -0.29, -2.11, 0.34, -0.53, -67.0]时，经int8量化和反量化处理后向量变为[ -0.00, -0.00, 0.00, -0.53, -0.53, -0.53, -2.11, 0.53, -0.53, -67.00]可见大部分信息在处理后都丢失了。&lt;strong>因此如果直接使用int8对模型量化会导致精度的下降&lt;/strong>。&lt;/p>
&lt;h4 id="2-llmint8-方法介绍">(2) LLM.int8 方法介绍&lt;/h4>
&lt;p>作者通过实验观察到了如下的现象(此处参考知友&lt;a href="https://zhuanlan.zhihu.com/p/624855002" target="_blank" rel="noopener">Strong&lt;/a>的文章)提出了混合量化方法 : LLM.int8。&lt;/p>
&lt;blockquote>
&lt;p>离群值几乎出现在所有的层中，如果我们贸然使用了int8量化手段会导致模型精度严重下降。但是好消息是这些离群值的分布有规律的。如果一个6.7B的transformer模型每个sequence中有150,000个离群值，那么他们只会出现在六个特征维度中（X[:，:，i]中六个不同的i值）。&lt;/p>
&lt;/blockquote>
&lt;p>基于&lt;a href="https://flowus.cn/737727b2-9344-4972-8073-c40202e3bab4#8984e294-6096-40e5-9daa-b427162f3391" target="_blank" rel="noopener">此现象&lt;/a>作者提出LLM.int8方法，即**将包含了离群值的几个维度从矩阵中分离出来，对其做高精度的矩阵乘法，其余部分进行量化。**按照作者的描述99.9%的维度都可以使用int8量化，至于0.1%的维度需要进行fp16乘法。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./2.png" alt="2.jpg" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>高亮部分为离群值，对于离群值不进行量化处理以fp16精度运算。对于非离群值则采用int8的方法进行量化。通过按行和列的绝对最大值$C_x$和$C_w$缩放，然后将输出量化为Int8，然后进行8位矩阵乘法再反量化。&lt;/p>
&lt;h4 id="3--llmint8方法精度及效率">(3) LLM.int8方法精度及效率&lt;/h4>
&lt;p>&lt;strong>在精度方法：&lt;/strong>&lt;/p>
&lt;p>如下图所示，作者在大小分别为125M,1.3B,2.7B,6.7B,13B的模型上使用不同的量化手段进行实验并评估各模型量化前后的&lt;strong>困惑值&lt;/strong>。&lt;strong>困惑值越低越好。&lt;/strong>&lt;/p>
&lt;p>可以无论是传统量化方案的对称和非对称方法，精度都会有很大下降；但是相较于其他量化手段，经LLM.int8方法量化后的模型损失很小几乎与fp32的精度一致。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./3.png" alt="3.jpg" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>可以看到当模型增大到临界值时，常规的int8方法的精度出现了大幅下降。但是LLM.int8方法几乎没有下降。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./4.png" alt="4.png" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>&lt;strong>在速度方面：&lt;/strong>&lt;/p>
&lt;p>目前关于速度方面的测试由两个来源一个是作者的博客，一个是论文。&lt;/p>
&lt;p>&lt;strong>博客：&lt;/strong>&lt;/p>
&lt;p>作者对比了不同模型大小下每个token的耗时(ms)。实验表明，&lt;strong>使用LLM.int8的BLOOM-176B比fp16版本慢15%到23%&lt;/strong>，具体数据如下图。小模型部分成倍变慢。&lt;/p>
&lt;p>作者提到在一天之内，他们将 T5-3B 的每词元推理延迟（左数第四列最底行）从 312 毫秒降低到 173 毫秒。也就是说本图中延迟的产生主要是算法的问题，作者团队目前正在优化中。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./5.png" alt="5" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
The 3 models are BLOOM-176B, T5-11B and T5-3B.&lt;/p>
&lt;p>&lt;strong>论文：&lt;/strong>&lt;/p>
&lt;p>不同大小的模型在第一个隐藏层中16位矩阵乘法相较于baseline的速度。低于1.0x是变慢了。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./6.png" alt="6" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
Experiments were conducted base on GPT3&lt;/p>
&lt;p>两种测量方法有共性也有区别，&lt;strong>共性在于&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>无论是int8量化还是LLM.int8量化在速度上都是对大模型更友好&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>区别在于&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>在使用token测速的方法中使用了LLM.int8的方法速度要低于fp16。而在隐藏层中16位矩阵乘法的测速方法中，小模型的推理出现了明显的降速，而大模型的推理速度增加了。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>显存方面&lt;/strong>&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./7.png" alt="7" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
本文的8位方法使许多以前无法访问的模型可以访问特别OPT-175B/BLOOM&lt;/p>
&lt;h4 id="4实践">（4）实践&lt;/h4>
&lt;p>使用第三方库Linear8bitLt&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch.nn&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">nn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">bitsandbytes&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">bnb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">bnb.nn&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Linear8bitLt&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">fp16_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Sequential&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Linear&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Linear&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="o">...&lt;/span> &lt;span class="n">train&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">model&lt;/span> &lt;span class="o">...&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">save&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fp16_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">state_dict&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="s2">&amp;#34;model.pt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">int8_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Sequential&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Linear8bitLt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">has_fp16_weights&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Linear8bitLt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">has_fp16_weights&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 此处标志变量 has_fp16_weights 非常重要。默认情况下，它设置为 True，用于在训练时使能 Int8/FP16 混合精度。但是，因为在推理中我们对内存节省更感兴趣，因此我们需要设置 has_fp16_weights=False。&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">int8_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_state_dict&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;model.pt&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 此时未进行量化&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">int8_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">int8_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 量化发生在此处&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 只有将模型加载至gpu中才会发生量化&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">input_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtype&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">float16&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">hidden_states&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">int8_model&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">input_&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;cuda&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>除了基础用法外，作者也给出了针对llama模型的示例代码。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">transformers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AutoModelForCausalLM&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AutoTokenizer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义生成文本的最大长度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">MAX_NEW_TOKENS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">128&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 设置使用的预训练模型名称&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;decapoda-research/llama-7b-hf&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 定义待处理的文本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;Hamburg is in which country?&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 使用tokenizer将文本转换为模型可接受的输入格式（input_ids是模型接受的整数序列）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tokenizer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoTokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">input_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tokenizer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">return_tensors&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;pt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">input_ids&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># GPU相关设置&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">free_in_GB&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cuda&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mem_get_info&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mi">1024&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">max_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cuda&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mem_get_info&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mi">1024&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">GB&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">n_gpus&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cuda&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device_count&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">max_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">max_memory&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_gpus&lt;/span>&lt;span class="p">)}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 参数load_in_8bit=True表示将模型以8位精度加载以减少内存占用&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AutoModelForCausalLM&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_pretrained&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model_name&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device_map&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;auto&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">load_in_8bit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_memory&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">max_memory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">generated_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">generate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">input_ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_length&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">MAX_NEW_TOKENS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tokenizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">generated_ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">skip_special_tokens&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="5qa">（5）Q&amp;amp;A&lt;/h4>
&lt;ol>
&lt;li>&lt;strong>为什么经过量化后模型的推理速度变慢了？&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>因为在量化的过程中需要对矩阵进行拆分，这会导致推理速度变慢。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>为什么小模型变慢的程度更大？&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>作者已经找到&lt;a href="https://github.com/TimDettmers/bitsandbytes/issues/6" target="_blank" rel="noopener">原因&lt;/a>，主要是CUDA核的问题。概括来讲就是int8无法使GPU达到饱和因此速度和fp16一样，但是由于量化的过程需要额外开销就导致推理的速度降低了。理论上来讲一个6B的模型速度会提升20-40%左右。作者没法估计开销会拉低多少的速度因为开销更为复杂与sequence的长度，batchsize都有关系。&lt;/p>
&lt;p>作者在半年前表示在后续版本中速度会更快。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>离群值的数量与时空复杂度的关系是什么？&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>作者发现的几个现象与此问题有关，但是如问题2所述量化过程中开销的问题作者自己也没有想明白。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>离群值涌现不是突然出现的而是渐进的，且与**困惑值(perplexities)**呈指数关系而与模型规模无关。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在发生phase shift之后，离群值开始迅速增长；&lt;/p>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>phase shift的意思是离群值突然在所有的层中出现并且开始相互协作。&lt;/p>
&lt;/blockquote>
&lt;h4 id="6总结">（6）总结&lt;/h4>
&lt;p>方法较新，使用简单，精度几乎不会损失，可以有效降低显存。但是&lt;strong>运行速度是否在可接受范围内需要进行实验。&lt;/strong>&lt;/p>
&lt;h4 id="7参考文献">（7）参考文献&lt;/h4>
&lt;ol>
&lt;li>
&lt;p>作者Tim Dettmers的博客 : &lt;a href="https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/" target="_blank" rel="noopener">https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>作者Younes Belkada的博客 ：&lt;a href="https://huggingface.co/blog/zh/hf-bitsandbytes-integration" target="_blank" rel="noopener">https://huggingface.co/blog/zh/hf-bitsandbytes-integration&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>B站博主&lt;a href="https://space.bilibili.com/602175518" target="_blank" rel="noopener">米粒方糖&lt;/a>的视频：&lt;a href="https://www.bilibili.com/video/BV1Tx4y1d7sG/?spm_id_from=333.880.my_history.page.click&amp;amp;vd_source=3a72dc49e723efef59bcf133fb8fe42e" target="_blank" rel="noopener">https://www.bilibili.com/video/BV1Tx4y1d7sG/?spm_id_from=333.880.my_history.page.click&amp;amp;vd_source=3a72dc49e723efef59bcf133fb8fe42e&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>原论文：&lt;a href="https://arxiv.org/pdf/2208.07339.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2208.07339.pdf&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="2-gptq量化施工中">2. GPTQ量化（施工中）&lt;/h3>
&lt;p>只需要20G显存就可以把llama33B跑起来&lt;/p>
&lt;p>由来自奥地利科技学院的Elias Frantar提出。目前该文章已发表在ICLR2023上。&lt;/p>
&lt;p>论文：&lt;a href="https://arxiv.org/pdf/2210.17323.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2210.17323.pdf&lt;/a>&lt;/p>
&lt;p>Github（针对LLama版本）：&lt;a href="https://github.com/qwopqwop200/GPTQ-for-LLaMa" target="_blank" rel="noopener">https://github.com/qwopqwop200/GPTQ-for-LLaMa&lt;/a>&lt;/p>
&lt;h4 id="1方法介绍">（1）方法介绍&lt;/h4>
&lt;p>经过从OBD到OBS到OBQ再到GPTQ。&lt;/p>
&lt;p>待完善。&lt;/p>
&lt;h4 id="2在llama33b上的表现">（2）在llama33B上的表现&lt;/h4>
&lt;p>实验在A100上进行。&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./8.png" alt="8.png" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h4 id="3使用方法">（3）使用方法&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Plain" data-lang="Plain">&lt;span class="line">&lt;span class="cl">python llama.py LLAMA_HF_FOLDER c4 --wbits 4 --true-sequential --act-order --new-eval
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="4与llmint8的区别">（4）与LLM.int8的区别&lt;/h4>
&lt;p>GPTQ是直接将fp16的模型量化成4bit的格式。而LLM.int8是读取fp16格式的权重&lt;a href="https://flowus.cn/737727b2-9344-4972-8073-c40202e3bab4#0b2da9fa-7c71-46fe-91e6-9bbe7a4da4dd" target="_blank" rel="noopener">然后将其加载到Linear8bitLt的层中&lt;/a>，在转移至GPU后发生量化。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">int8_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_state_dict&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;model.pt&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">int8_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">int8_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 量化发生在此处&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="五-todo">五. TODO&lt;/h2>
&lt;ol>
&lt;li>深入研究LLM.int8方法、&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;p>阅读&lt;a href="https://arxiv.org/pdf/2110.02861.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2110.02861.pdf&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>了解emergent feature现象&lt;a href="https://arxiv.org/pdf/2208.07339.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2208.07339.pdf&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在论文《LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale》中int8 absmax和zeropoint具体是什么含义？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>作者设计这种方法的灵感来自于哪里？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对于猜测“outliers”的存在是为了使模型提取特征是否成立？如果成立仅保留outliers会有多少的精度损失？能否设计一种方法保留一定比例的非outliers以平衡性能损失和模型对计算资源的占用？&lt;/p>
&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>llama.cpp背后的算法是什么？&lt;a href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener">https://github.com/ggerganov/llama.cpp&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>通过阅读原论文及博客完善GPTQ的原理介绍 From 知乎 &amp;amp; arxiv&lt;/p>
&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://arxiv.org/pdf/2210.17323.pdf" target="_blank" rel="noopener">https://arxiv.org/pdf/2210.17323.pdf&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://zhuanlan.zhihu.com/p/625701227" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/625701227&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://zhuanlan.zhihu.com/p/616969812" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/616969812&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://zhuanlan.zhihu.com/p/623047485" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/623047485&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>通过查看前人经验了解GPTQ &amp;amp; LLM.int8 使用方法 From youtube&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=mii-xFaPCrA" target="_blank" rel="noopener">https://www.youtube.com/watch?v=mii-xFaPCrA&lt;/a> GPTQ&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=p9_pbJwvEL8" target="_blank" rel="noopener">https://www.youtube.com/watch?v=p9_pbJwvEL8&lt;/a> GPTQ 33B&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=SvfZO47ShoU" target="_blank" rel="noopener">https://www.youtube.com/watch?v=SvfZO47ShoU&lt;/a> GPTQ&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=bTzM45kaK44" target="_blank" rel="noopener">https://www.youtube.com/watch?v=bTzM45kaK44&lt;/a> LLM.int8&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Attack based on data : A novel perspective to attack sensitive points directly</title><link>https://geyuyao.com/publication/ge2023attack/</link><pubDate>Wed, 05 Jul 2023 15:03:00 +0000</pubDate><guid>https://geyuyao.com/publication/ge2023attack/</guid><description/></item></channel></rss>