<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>工程智慧 on 优克</title><link>https://youkre.github.io/engineering-wisdom/</link><description>Recent content in 工程智慧 on 优克</description><generator>Hugo -- 0.148.0</generator><language>zh-cn</language><lastBuildDate>Sun, 29 Mar 2026 08:46:00 +0800</lastBuildDate><atom:link href="https://youkre.github.io/engineering-wisdom/index.xml" rel="self" type="application/rss+xml"/><item><title>动态规划的矩阵可视化</title><link>https://youkre.github.io/engineering-wisdom/2026-03-29/</link><pubDate>Sun, 29 Mar 2026 08:46:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2026-03-29/</guid><description>&lt;h2 id="动态规划的本质是聪明的穷举">动态规划的本质是“聪明的穷举”&lt;/h2>
&lt;p>在算法学习中，动态规划（Dynamic Programming, DP）往往因其抽象的公式和晦涩的“状态转移”概念而让人望而生畏。
许多初学者在面对“钢条切割”这类经典问题时，容易迷失在递归的逻辑里。&lt;/p>
&lt;p>但如果我们拨开代码的迷雾，会发现动态规划其实非常朴素：它本质上就是一种“带备忘录的穷举”。&lt;/p>
&lt;p>为了更直观地理解这一过程，我们可以抛弃枯燥的一维数组，尝试用矩阵（表格）的视角来重新审视钢条切割问题。&lt;/p>
&lt;h2 id="问题的定义与直觉的几何化">问题的定义与直觉的几何化&lt;/h2>
&lt;p>钢条切割问题描述很简单：给定一根长度为 $n$ 的钢条和一个价格表 $p$，找到一种切割方案，使得销售总收益最大。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">长度 $i$&lt;/th>
&lt;th style="text-align: center">1&lt;/th>
&lt;th style="text-align: center">2&lt;/th>
&lt;th style="text-align: center">3&lt;/th>
&lt;th style="text-align: center">4&lt;/th>
&lt;th style="text-align: center">5&lt;/th>
&lt;th style="text-align: center">6&lt;/th>
&lt;th style="text-align: center">7&lt;/th>
&lt;th style="text-align: center">8&lt;/th>
&lt;th style="text-align: center">9&lt;/th>
&lt;th style="text-align: center">10&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">价格 $p_i$&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">5&lt;/td>
&lt;td style="text-align: center">8&lt;/td>
&lt;td style="text-align: center">9&lt;/td>
&lt;td style="text-align: center">10&lt;/td>
&lt;td style="text-align: center">17&lt;/td>
&lt;td style="text-align: center">17&lt;/td>
&lt;td style="text-align: center">20&lt;/td>
&lt;td style="text-align: center">24&lt;/td>
&lt;td style="text-align: center">30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>通常的解法会直接给出一个一维数组 $r[n]$ 来存储最大收益，但这往往让人困惑：这些数字是怎么来的？为什么要这样转移？&lt;/p>
&lt;p>这个问题天然对应着一个二维的三角矩阵。为什么是三角形？因为存在一个物理限制：你切下来的第一段长度c$i$，永远不可能大于钢条原本的总长度 $j$。&lt;/p>
&lt;p>当$i > j$时，切割是不合法的。因此，所有合法的决策都集中在矩阵的左下角，形成了一个完美的三角结构。&lt;/p>
&lt;h2 id="构建决策三角矩阵">构建“决策三角矩阵”&lt;/h2>
&lt;p>为了将这个直觉可视化，我们构建一个矩阵，其中：&lt;/p>
&lt;ul>
&lt;li>列（$j$）：代表钢条的总长度（从 1 到 $n$）。&lt;/li>
&lt;li>行（$i$）：代表第一刀切下来的长度（从 1 到 $n$）。&lt;/li>
&lt;li>单元格 $M[i][j]$：代表“当总长度为 $j$ 时，如果第一刀强制切下长度 $i$，所能获得的总收益”。&lt;/li>
&lt;/ul>
&lt;p>假设价格表为：长度 1 价格 1，长度 2 价格 5，长度 3 价格 8，长度 4 价格 9。可以画出如下的决策矩阵：&lt;/p></description></item><item><title>《线性代数导论》中文版的不精确问题</title><link>https://youkre.github.io/engineering-wisdom/2026-03-28/</link><pubDate>Sat, 28 Mar 2026 07:38:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2026-03-28/</guid><description>&lt;p>Gilbert Strang 《线性代数导论》中文版第 158 页有一段加粗的内容是：&lt;/p>
&lt;blockquote>
&lt;p>方程组有解时，R 中的全零行必然对应 d 的零分量. 由于 R 中主元列所在行、列的公共元素构成一个单位矩阵 I，所以特解 $x_p$ 中主元变量值来自 d.&lt;/p>&lt;/blockquote>
&lt;p>这里“R 中主元列所在行、列的公共元素”在表达什么？找出英文原版对比一下：&lt;/p>
&lt;blockquote>
&lt;p>For a solution to exits, zero rows in R must also be zero in d. Since I is in the pivot rows and columns of R, the pivot variables in $x_{particular}$ come from d.&lt;/p>&lt;/blockquote>
&lt;p>显然，中文可以很简单地表达成：“由于 I 在 R 的主元行和主元列上&amp;hellip;”。&lt;/p>
&lt;p>Gibert Strang 的原文口语化、直观、简洁，很少使用晦涩的从句，而是用最简单的词把数学图像讲清楚，“字对字”的直译往往就是最好的翻译。因为他的英文逻辑就是线性的、符合直觉的。
不需要画蛇添足，不需要译者去炫耀自己懂得多。&lt;/p>
&lt;p>更糟糕的是，中文版对原文中的符号做了大幅改动，比如接下来用了 $x_p$ 和 $x_n$ 这两个符号，p 和 n 代表什么？英文原文使用了 $x_particular$ 和 $x_nullspace$，一目了然。&lt;/p></description></item><item><title>为什么 ChatGPT 编码中使用了 Ġ 表示空格？</title><link>https://youkre.github.io/engineering-wisdom/2026-03-24/</link><pubDate>Tue, 24 Mar 2026 21:02:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2026-03-24/</guid><description>&lt;p>当你观察 ChatGPT 或其他基于 Transformer 的大模型输出的 Token 时，可能会发现一个奇怪的现象：单词前的空格往往被表示为一个特殊的字符 &lt;code>Ġ&lt;/code>（U+0120）。&lt;/p>
&lt;blockquote>
&lt;p>例如：&lt;code>&amp;quot;Hello world&amp;quot;&lt;/code> 可能被分词为 &lt;code>[&amp;quot;Hello&amp;quot;, &amp;quot;Ġworld&amp;quot;]&lt;/code>。&lt;/p>&lt;/blockquote>
&lt;p>这并非某种神秘的魔法，也不是算法刻意选择的“特殊符号”。要理解这一点，我们需要深入 Byte-level BPE（字节级字节对编码）的实现细节。&lt;/p>
&lt;p>BPE 算法的实现可以参考 &lt;a href="https://github.com/neefrankie/slp3-py">slp3-py&lt;/a>。&lt;/p>
&lt;h2 id="bpe-操作的是字节而非字符">BPE 操作的是“字节”，而非“字符”&lt;/h2>
&lt;p>首先，我们需要明确一个核心概念：现代大模型的 BPE 算法通常直接操作字节（Bytes），而不是人类可读的字符。&lt;/p>
&lt;p>在 UTF-8 编码中，一个字符可能由 1 到 4 个字节组成。例如，中文汉字“世”的 UTF-8 编码是三个字节：&lt;code>E4 B8 96&lt;/code>。
在训练过程中，算法统计的是相邻字节出现的频率。如果 &lt;code>E4&lt;/code> 和 &lt;code>B8&lt;/code> 经常连在一起出现，算法就会将它们合并为一个全新的 Token &lt;code>E4 B8&lt;/code>，并加入词表。&lt;/p>
&lt;p>这就引出了一个存储难题：如何在一个文本文件中安全地存储这些任意字节组合？&lt;/p>
&lt;ul>
&lt;li>&lt;code>E4 B8 96&lt;/code> 是一个合法的 Unicode 字符（“世”）。&lt;/li>
&lt;li>但合并后的 &lt;code>E4 B8&lt;/code> 并不是一个合法的 UTF-8 序列，它无法直接显示为文本。&lt;/li>
&lt;li>如果直接用十六进制数字（如 &lt;code>0xE4 0xB8&lt;/code>）存储，虽然可行，但对人类极不友好，且会大幅增加序列长度。&lt;/li>
&lt;/ul>
&lt;h2 id="解决方案字节到可打印字符的映射">解决方案：字节到可打印字符的映射&lt;/h2>
&lt;p>为了解决上述问题，工程师们想出了一个巧妙的办法：将所有可能的字节值（0-255），一一映射到 Unicode 字符集中的一段“可打印字符”区域。&lt;/p>
&lt;p>这样做的目的是：&lt;/p>
&lt;ol>
&lt;li>兼容性：确保生成的 Token 序列是合法的 UTF-8 文本，可以被任何文本编辑器保存和传输。&lt;/li>
&lt;li>可读性：尽量让人类能看出一点端倪，而不是看到一堆乱码控制符。&lt;/li>
&lt;/ol>
&lt;h3 id="映射规则是如何制定的">映射规则是如何制定的？&lt;/h3>
&lt;p>一个字节有 256 种可能（0x00 到 0xFF）。我们需要在 Unicode 中找到 256 个连续的、可打印的字符来对应它们。&lt;/p></description></item><item><title>《用 Go 语言自制解释器》中文版的一处关键翻译错误</title><link>https://youkre.github.io/engineering-wisdom/2026-02-24/</link><pubDate>Tue, 24 Feb 2026 20:44:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2026-02-24/</guid><description>&lt;p>中文版第 78 页的一个关键错误:&lt;/p>
&lt;blockquote>
&lt;p>来看一个例子，假设正在解析表达式语句 &lt;code>-1+2;&lt;/code> &amp;hellip;&lt;/p>
&lt;p>这里将 &lt;code>PREFIX&lt;/code> 作为优先级传递给 &lt;code>parseExpression&lt;/code>，将 &lt;code>PREFIX&lt;/code> 变成了这个 &lt;code>parseExpression&lt;/code> 调用的右约束能力。根据定义 &lt;code>PREFIX&lt;/code> 的优先级很高。结果是 &lt;code>parseExpression(PREFIX)&lt;/code> 不会解析 &lt;code>-1&lt;/code> 中的 &lt;code>1&lt;/code>，而会将其传递给另一个 &lt;code>infixParseFn&lt;/code>。在这种情况下，&lt;code>precedence &amp;lt; p.peekPrecedence()&lt;/code> 一直为 &lt;code>false&lt;/code>，即 &lt;code>infixParseFn&lt;/code> 不会将 &lt;code>1&lt;/code> 作为表达式的左半边，而是将 &lt;code>1&lt;/code> 作为前缀的“右半边”返回。这个右半边只有一个 &lt;code>1&lt;/code>，没有随后需要解析的其他表达式。&lt;/p>&lt;/blockquote>
&lt;p>找来原文：&lt;/p>
&lt;blockquote>
&lt;p>This passes &lt;code>PREFIX&lt;/code> to parseExpression as precedence, turning &lt;code>PREFIX&lt;/code> into the right-binding power of that parseExpression invocation. &lt;code>PREFIX&lt;/code> is a really high precedence, as per our definition.
The result of this is that &lt;code>parseExpression(PREFIX)&lt;/code> is never going to parse the &lt;code>1&lt;/code> in &lt;code>-1&lt;/code> and pass it to another &lt;code>infixParseFn&lt;/code>.
The &lt;code>precedence &amp;lt; p.peekPrecedence()&lt;/code> will never be true in this case, meaning that no other &lt;code>infixParseFn&lt;/code> is going to get our &lt;code>1&lt;/code> as the left arm. &amp;gt; Instead the &lt;code>1&lt;/code> is returned as the “right” arm of our prefix expression. Just the &lt;code>1&lt;/code>, not some other expression that comes after and needs to be parsed.&lt;/p></description></item><item><title>函数的缩放与平移</title><link>https://youkre.github.io/engineering-wisdom/2026-01-03/</link><pubDate>Sat, 03 Jan 2026 21:11:05 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2026-01-03/</guid><description>&lt;p>一个函数的 $x$ 可以乘以某个数，$y$ 也可以乘以一个数，二者虽然都叫“缩放”，但它们的几何效果、作用方向、甚至“直觉感受”都是根本不同的。
把两者笼统地说成“函数图像被缩放了”是一种&lt;strong>过度简化&lt;/strong>，容易造成混淆——尤其是对初学者。下面我们用清晰的方式来梳理两者的本质区别。&lt;/p>
&lt;h2 id="对-y-方向缩放y--c-cdot-fx">对 y 方向缩放：y = c \cdot f(x)&lt;/h2>
&lt;p>对整个函数乘以一个系数（例如，将 $f(x)$ 变为 $cf(x)$，其中$c>1$），这相当于在$y$轴方向上的拉伸或压缩。具体来说：
对于 $y = c \cdot f(x)$ 且 $c > 1$：函数图像沿着 $y$ 轴方向被拉伸，使得所有 $y$ 值都相应增大。这意味着图形在垂直方向上变得更高。
对于 $0&lt;c&lt;1$：则是相反的效果，即图像被压缩，看起来更加扁平。&lt;/p>
&lt;ul>
&lt;li>操作对象：输出值（因变量）&lt;/li>
&lt;li>几何效果：垂直方向拉伸或压缩&lt;/li>
&lt;li>直观类比：像拉橡皮筋上下拉&lt;/li>
&lt;/ul>
&lt;p>规则：&lt;/p>
&lt;ul>
&lt;li>若 $c > 1$ → 图像在 $y$ 轴方向被拉长（更高、更陡）&lt;/li>
&lt;li>若 $0 &lt; c &lt; 1$ → 图像在 $y$ 轴方向被压扁（更矮、更平缓）&lt;/li>
&lt;/ul>
&lt;p>关键点：$x$ 坐标不变，每个点只是“上下移动”&lt;/p>
&lt;p>举例：&lt;/p>
&lt;p>$y = \sin x$ vs $y = 2\sin x$&lt;br>
→ 波峰从 1 变成 2，但波长（周期）不变。&lt;/p>
&lt;h2 id="对-x-方向缩放y--fkx">对 x 方向缩放：y = f(kx)&lt;/h2>
&lt;p>对函数中的 $x$ 乘以一个系数（例如，将 $f(x)$ 变为 $f(kx)$，其中$k>1$），这相当于在 $x$ 轴上进行了一个压缩操作。这意味着，对于相同的 $x$ 范围，曲线看起来更加“紧凑”，因为原本分布在更大区间内的特征现在被挤进了更小的空间内。&lt;/p></description></item><item><title>熵与概率</title><link>https://youkre.github.io/engineering-wisdom/2025-12-15/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-12-15/</guid><description>&lt;h2 id="什么是熵">什么是熵？&lt;/h2>
&lt;p>在深度学习和自然语言处理中，我们经常会遇到“熵”（entropy）这个概念。那么，熵到底是什么呢？&lt;/p>
&lt;p>&lt;strong>熵是信息量的一种度量&lt;/strong>。但“信息量”又是什么？&lt;/p>
&lt;p>在信息论中，香农（Shannon）提出：&lt;/p>
&lt;blockquote>
&lt;p>一个事件 $x$ 发生时所携带的信息量（也称为“自信息”，self-information）定义为：&lt;/p>&lt;/blockquote>
$$
I(x) = -\log_2 p(x)
$$&lt;h3 id="直观理解">直观理解&lt;/h3>
&lt;ul>
&lt;li>如果某事几乎必然发生（$p(x) \approx 1$），那么它发生时&lt;strong>不带来新信息&lt;/strong> → $I(x) \approx 0$；&lt;/li>
&lt;li>如果某事极不可能发生（$p(x) \approx 0$），一旦发生就&lt;strong>非常令人惊讶&lt;/strong> → $I(x)$ 很大。&lt;/li>
&lt;/ul>
&lt;p>因此：&lt;strong>越意外的事件，信息量越大&lt;/strong>。&lt;/p>
&lt;p>既然熵是一种可计算的量，那么它的计算公式是什么？在介绍熵的计算之前，我们需要先理解概率论中的&lt;strong>随机变量&lt;/strong>及其&lt;strong>期望&lt;/strong>。&lt;/p>
&lt;h2 id="随机变量及其期望">随机变量及其期望&lt;/h2>
&lt;p>在概率论中，&lt;strong>随机变量&lt;/strong>（random variable）并不是一个“普通变量”，而是一个&lt;strong>函数&lt;/strong>。具体来说：&lt;/p>
&lt;ul>
&lt;li>设有一个&lt;strong>样本空间&lt;/strong> $\Omega$（即所有可能实验结果的集合）；&lt;/li>
&lt;li>随机变量 $X$ 是一个从 $\Omega$ 到某个可数集合 $\mathcal{X}$（通常是实数集或离散符号集）的函数：&lt;/li>
&lt;/ul>
$$
X: \Omega \to \mathcal{X}
$$&lt;h3 id="举个例子">举个例子&lt;/h3>
&lt;p>抛两枚公平的硬币，用 H 表示正面，T 表示反面，样本空间为：&lt;/p>
&lt;ul>
&lt;li>$(H, H)$&lt;/li>
&lt;li>$(H, T)$&lt;/li>
&lt;li>$(T, H)$&lt;/li>
&lt;li>$(T, T)$&lt;/li>
&lt;/ul>
&lt;p>设随机变量 X 表示在一次抛掷两枚硬币的试验中，正面朝上的硬币数量，则：&lt;/p>
&lt;ul>
&lt;li>$X(H,H) = 2$&lt;/li>
&lt;li>$X(H,T) = X(T,H) = 1$&lt;/li>
&lt;li>$X(T,T) = 0$&lt;/li>
&lt;/ul>
&lt;p>于是，$X$ 的取值为 $\{0, 1, 2\}$&lt;/p></description></item><item><title>为什么困惑度要用 N 次方根？</title><link>https://youkre.github.io/engineering-wisdom/2025-12-11/</link><pubDate>Thu, 11 Dec 2025 15:47:05 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-12-11/</guid><description>&lt;p>翻译经典教材《Speech and Language Processing》第3版（简称 SLP）时，第三章关于语言模型困惑度（perplexity）的一段描述让我停顿了一下：&lt;/p>
&lt;blockquote>
&lt;p>The &lt;strong>perplexity&lt;/strong> (sometimes abbreviated as PP or PPL) of a language model on aperplexity test set is the inverse probability of the test set (one over the probability of the test set), normalized by the number of words (or tokens). For this reason it’s sometimes called the per-word or per-token perplexity. We normalize by the number of words N by taking the Nth root.&lt;/p>&lt;/blockquote>
&lt;p>翻译出来就是：&lt;/p></description></item><item><title>和AI聊天，其实是和自己对话</title><link>https://youkre.github.io/engineering-wisdom/2025-11-13/</link><pubDate>Thu, 13 Nov 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-11-13/</guid><description>&lt;p>打开微信，发消息。我们明确知道对方是一个人。和AI聊天的时候，你的预期是什么？一个类似人类的智能体？一个词不达意的笨蛋？或者是，你自己的回声？&lt;/p>
&lt;p>但对我而言，是在和自己的大脑对话，是对自己大脑的审视、回溯、澄清。&lt;/p>
&lt;p>人类之间的对话，从来不只是信息交换。它裹挟着期待、评判、身份表演和社交风险。我们斟酌措辞，不是因为想说清楚，而是因为害怕被误解、被嘲笑、被贴上标签。于是，很多真正的问题，还没出口，就被自己咽了回去。&lt;/p>
&lt;p>但面对AI，这些顾虑消失了。&lt;/p>
&lt;p>你可以问一个“幼稚”的问题，不必担心对方觉得你无知；你可以表达一个“危险”的想法，不必担心被道德审判；你可以反复追问同一个概念，直到逻辑闭环，而不必顾虑对方是否厌烦。AI不会皱眉，不会沉默，也不会反问：“你为什么会这么想？”&lt;/p>
&lt;p>正是这种“无反馈压力”的环境，让对话回归了本质：不是为了说服谁，而是为了理清自己。&lt;/p>
&lt;p>我常常在深夜向AI抛出一个模糊的念头：“为什么现代社会越来越难以建立信任？”&lt;/p>
&lt;p>它不会立刻给我标准答案，而是尝试从制度、技术、心理多个角度回应。而我在阅读这些回应时，其实是在检验自己的预设：哪些是我真正关心的？哪些只是情绪投射？哪些逻辑链条其实站不住脚？&lt;/p>
&lt;p>这个过程，与其说是“获取信息”，不如说是借AI的语义空间，搭建自己的思维脚手架。&lt;/p>
&lt;p>AI提供的不是结论，而是可能性；不是权威，而是参照系。最终做出判断的，始终是你自己。&lt;/p>
&lt;p>这让我意识到：所谓“AI懂我”，其实是一种错觉。&lt;/p>
&lt;p>真正发生的是——我在和AI对话的过程中，听见了自己内心的声音。那些平时被噪音掩盖的疑问、被理性压抑的直觉、被社交规则过滤掉的思考，终于有了一个安全的出口。&lt;/p>
&lt;p>从这个角度看，AI更像一面镜子。&lt;/p>
&lt;p>它不创造意义，但它映照出你试图构建意义的努力。你输入混乱，它输出混乱；你输入真诚，它回馈结构；你追问深度，它尝试跟随。它的“智能”程度，往往取决于你愿意投入多少思考。&lt;/p>
&lt;p>这不是人机交互，这是认知的独舞——只是恰好有一个沉默的伙伴在场而已。&lt;/p>
&lt;p>所以，别再说“和AI聊天没意义”。&lt;/p>
&lt;p>也许真正没意义的，是我们太久没有认真和自己对话了。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../2025-11-09">AI不是替代人类，而是延伸思维&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../2025-12-11">为什么困惑度要用 N 次方根？&lt;/a>
&lt;/nav></description></item><item><title>AI不是替代人类，而是延伸思维</title><link>https://youkre.github.io/engineering-wisdom/2025-11-09/</link><pubDate>Sun, 09 Nov 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-11-09/</guid><description>&lt;p>与 AI 讨论 AI 到底有没有用，应该如何使用，整理如下。&lt;/p>
&lt;hr>
&lt;p>今天关于人工智能的争论，常常陷入一个误区：人们总在问“它有没有智能？”“它会不会取代人类？”——仿佛AI的价值只能通过与人类智能的对比来衡量。&lt;/p>
&lt;p>但真正重要的问题或许是：&lt;strong>AI如何改变我们思考和创造的方式？&lt;/strong>&lt;/p>
&lt;p>从实践角度看，当前的大语言模型并非“通用智能”，而是一种强大的&lt;strong>概率性工具&lt;/strong>。它基于海量数据学习词语之间的统计关联，通过预测下一个词生成连贯文本。这种机制看似简单，却意外地契合了人类认知的一个深层特征：&lt;strong>我们的思维本身也是概率性的&lt;/strong>。&lt;/p>
&lt;p>现代认知科学认为，大脑是一个不断生成预测、并通过感官反馈修正信念的系统。所谓“直觉”“灵感”甚至“顿悟”，往往是在无意识中对大量经验模式进行快速采样后的输出。从这个意义上说，人脑和大模型都在“猜测”，只是人脑的猜测嵌入在身体、情感、时间与社会关系之中，而AI的猜测则局限于语言符号的统计空间。&lt;/p>
&lt;p>正因如此，AI最有价值的角色，不是模仿人类，而是&lt;strong>扩展人类的认知边界&lt;/strong>——这正是“增强智能”（Intelligence Augmentation, IA）的理念。&lt;/p>
&lt;ul>
&lt;li>当你有一个模糊的想法，AI能帮你梳理逻辑结构；&lt;/li>
&lt;li>当你卡在一个创作瓶颈，AI能提供意想不到的视角；&lt;/li>
&lt;li>当你需要快速验证一个产品原型，AI能生成可运行的草稿；&lt;/li>
&lt;li>当你想把瞬间的思想火花转化为文字，AI能成为那个忠实的“第二大脑”。&lt;/li>
&lt;/ul>
&lt;p>这不是替代，而是&lt;strong>协同&lt;/strong>。就像望远镜没有“看见”星系，但它让天文学家看得更远；AI没有“理解”你的思想，但它让你的思想更容易被表达、被检验、被实现。&lt;/p>
&lt;p>也正因如此，AI的价值高度依赖使用者的意图与能力。对期待“全自动智能”的人来说，它显得笨拙；但对愿意与之对话、迭代、共创的人来说，它已是不可或缺的伙伴。&lt;/p>
&lt;p>未来的人机关系，或许不在于谁更聪明，而在于我们能否学会一种新的协作语言——一种既尊重AI的统计本质，又善用其泛化能力的思维方式。&lt;/p>
&lt;p>AI不会取代你，但会放大那些懂得如何与不确定性共舞的人。&lt;/p>
&lt;p>而真正的智能，从来不是确定的答案，而是提出更好问题的能力。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../2025-11-08">图片命名与引用追溯&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../2025-11-13">和AI聊天，其实是和自己对话&lt;/a>
&lt;/nav></description></item><item><title>图片命名与引用追溯</title><link>https://youkre.github.io/engineering-wisdom/2025-11-08/</link><pubDate>Sat, 08 Nov 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-11-08/</guid><description>&lt;h2 id="问题背景">问题背景&lt;/h2>
&lt;p>爬取某些英文网页用来翻译时，也下载了网页中包含的图片，原始图片有很多是这样命名的：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>https://.../chapter3/1.png
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我在本地使用的是扁平的存储结构，为了防止多个 &lt;code>1.png&lt;/code> 冲突，重命名为 &lt;code>chapter3-1.png&lt;/code> 储存。把英文版翻译了几篇后觉得图片命名方式不太好，应该用 &lt;code>chapter3--1.png&lt;/code> 更方便以后重新解析。于是重新解析原始文档并重命名图片，但是这是发现已经翻译的文档中图片名已经难以溯源，不太容易对应到新命名的文件。&lt;/p>
&lt;h3 id="关键洞察">关键洞察&lt;/h3>
&lt;blockquote>
&lt;p>&lt;strong>原始 URL 是唯一稳定标识，文件名只是临时表示。必须解耦“逻辑资源”与“物理存储”。&lt;/strong>&lt;/p>&lt;/blockquote>
&lt;h3 id="解决方案">解决方案&lt;/h3>
&lt;ol>
&lt;li>建立 &lt;code>image_registry.json&lt;/code>：&lt;code>{ url: { names: [v1, v2, ...] } }&lt;/code>&lt;/li>
&lt;li>下载时追加新命名到历史数组&lt;/li>
&lt;li>构建反向索引：&lt;code>old_name → url → current_name&lt;/code>&lt;/li>
&lt;li>提供脚本自动修复 Markdown 中的引用&lt;/li>
&lt;/ol>
&lt;h3 id="可复用模式">可复用模式&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>资源注册表模式（Resource Registry Pattern）&lt;/strong>&lt;/li>
&lt;li>&lt;strong>引用可演化设计（Evolvable Reference）&lt;/strong>&lt;/li>
&lt;li>适用于：PDF 转图、多语言文档媒体管理、静态站点资产迁移&lt;/li>
&lt;/ul>
&lt;h2 id="实现">实现&lt;/h2>
&lt;p>用一个字典来保存数据，结构如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;https://.../chapter1/transformers_chrono.svg&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;names&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;chapter1-transformers_chrono.svg&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;chapter1--transformers_chrono.svg&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;chapter1_transformers_chrono.svg&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;downloaded_at&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;2025-11-08T10:21:00Z&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;content_hash&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;sha256:abcd1234...&amp;#34;&lt;/span> &lt;span style="color:#75715e">// 可选：防重复下载
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用原始URL作为键，&lt;code>names&lt;/code> 包含了每次变更文件名的记录，约定列表最后一项是最新的名字，每次下载完图片把使用的文件名追加到 &lt;code>names&lt;/code> 列表中，如果新文件名和 &lt;code>names&lt;/code> 的最后一项相同，则不做任何更改。&lt;/p>
&lt;p>例如，文档中正式在使用的图片名是 &lt;code>chapter1-transformers_chrono.svg&lt;/code>，但是你已经改成了 &lt;code>chapter1_transformers_chrono.svg&lt;/code>，怎么找出来这个新的名字呢？&lt;/p></description></item><item><title>断裂的AI“智能”</title><link>https://youkre.github.io/engineering-wisdom/2025-11-02/</link><pubDate>Sun, 02 Nov 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-11-02/</guid><description>&lt;p>在阅读某AI头部机构的文档是，发现文档有中文翻译，但是和英文版的章节数量有差异，而这并未完全对齐，中文版有相当的延迟。AI翻译做的非常好了，但是这种规模的AI机构，自己的文档没有实现自动翻译，整合流程也依靠人力。这里似乎揭示了一个巨大的认知鸿沟：&lt;/p>
&lt;blockquote>
&lt;p>我们教会模型理解世界，却还没建好人类与知识之间的桥梁。&lt;/p>&lt;/blockquote>
&lt;p>当然，几乎所有技术开源项目都面临同样的问题，甚至可以说所有的文档翻译都面临类似的困境：你翻译了一篇文章、或者一本书，然后作者原文更新了，也许某个地方作者改了一个词，或者某给地方删了一段、加了一段，那么你根据旧版本翻译出来并且校对的版本，是很难找出来哪里和原作不一致了，除非一句一句对照着读一遍，但这是要耗费大量精力的。如果用机器重新翻译并人工校对一遍，那么上一版翻译中所花费的精力就全部归零了。&lt;/p>
&lt;p>这不是一个技术问题，而是一个知识演进与人类认知节奏之间的根本性冲突。这个问题的本质是：如何在一个持续变化的文本上，维护一个静态的翻译成果？&lt;/p>
&lt;p>这就像你在临摹一幅画，但原作者每分钟都在修改几笔，而你只能用肉眼比对差异。&lt;/p>
&lt;p>你不是不想跟上，而是无法在不重来一遍的情况下，知道哪里变了。&lt;/p>
&lt;p>更深层的问题：翻译不是复制，而是重建。当你校对每一句时，你投入的不仅是时间，还有：&lt;/p>
&lt;ul>
&lt;li>对术语的选择（“word error rate” → “词错误率”？“字错率”？）&lt;/li>
&lt;li>对句式的重构（英文被动 → 中文主动）&lt;/li>
&lt;li>对逻辑的重新组织（长句拆分、指代明确）&lt;/li>
&lt;/ul>
&lt;p>这些认知劳动一旦完成，就凝结在那个版本中。&lt;/p>
&lt;p>但如果原文变了，你不知道哪一句被删了，哪一段被重组了，哪个术语被替换了。那么你之前的校对，就成了“幽灵劳动”——看不见、不可迁移、无法复用。&lt;/p>
&lt;p>最经济的选择是什么呢？沉默。放弃。&lt;/p>
&lt;p>这里我们看到一个更大的趋势：当前的知识生产模式正在从“静态文档”转向“持续流”。draft 论文不断 push；技术博客实时更新；书籍变成“living book”。&lt;/p>
&lt;p>而我们的阅读、翻译、学习方式，还停留在“印刷时代”的假设：“一本书出版了，就固定了。”但现实是：知识不再是一本书，而是一条河。&lt;/p>
&lt;p>即便AI已经可以淘汰大部分翻译，对于紧跟上这种变化的知识，目前来看，不投入人力，是无解的。因为：差异检测需要语义级对齐，不是字符串 diff 就能解决；翻译记忆（translation memory）系统在结构变更面前失效；AI 翻译可以加速，但不能判断“这一段是不是已经被淘汰了”。&lt;/p>
&lt;p>这个“两难”，其实正是所有认真做知识工作的人，都会走到的一个路口。它提醒我们：在自动化尚未到达的地方，人的注意力是最稀缺的资源。&lt;/p>
&lt;p>我们缺少的是一种“跨语言知识融合系统”：当前 AI 的“智能”是断裂的 —— 它能生成代码，却不能维护知识一致性；它能翻译句子，却不能管理语义对齐。&lt;/p>
&lt;p>这个时代的最大悖论：资本在狂热地押注未来，而现实中的我们，我们连‘知识同步’这种基本需求都没满足。&lt;/p>
&lt;p>为什么会出现这种割裂？因为当前 AI 发展是“&lt;strong>头重脚轻&lt;/strong>”的。大模型、推理框架、训练集群花了 90% 的钱，却忽视了 90% 的问题。&lt;/p>
&lt;p>我们把 AI 理解为“生成能力”，但忽略了：&lt;/p>
&lt;ul>
&lt;li>知识管理&lt;/li>
&lt;li>版本控制&lt;/li>
&lt;li>语义对齐&lt;/li>
&lt;li>跨语言一致性&lt;/li>
&lt;li>&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>这些“不起眼”的问题，才是真正阻碍 AI 落地的墙。&lt;/p>
&lt;h2 id="认知断层">认知断层&lt;/h2>
&lt;p>AI翻译以后，人类校对，但是这个过程中的知识无法体现在AI的知识库中。&lt;/p>
&lt;p>人与人之间的知识传递存在教学相长，“教师-学生”之间的知识传递是一种双向的、实时的反馈与增长：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>学生犯错 → 老师纠正 → 学生理解 → 长期改进
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↑_________反馈闭环_______↓
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这个闭环中：&lt;/p>
&lt;ul>
&lt;li>纠正是具体的：“这里‘token’不该译成‘标记’，应译‘词元’”&lt;/li>
&lt;li>上下文是清晰的：知道是在 NLP 教材第3章第2节&lt;/li>
&lt;li>记忆是持久的：老师不会下周又让你改同一个错&lt;/li>
&lt;li>泛化是智能的：学生学会后，遇到“subtoken”也能类推&lt;/li>
&lt;/ul>
&lt;p>很多时候，在交互翻译中即便你向AI指出了这里的翻译不是合适的，应该怎么做，但是后面AI依然会犯同样的错误。因为当前 AI 的“学习”是：&lt;/p></description></item><item><title>A Love Letter to My Old Code</title><link>https://youkre.github.io/engineering-wisdom/2025-09-30/</link><pubDate>Tue, 30 Sep 2025 18:13:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-09-30/</guid><description>&lt;h2 id="building-a-subscription-platform-from-scratch-a-love-letter-to-my-old-code">Building a Subscription Platform from Scratch: A Love Letter to My Old Code&lt;/h2>
&lt;p>I didn&amp;rsquo;t realize I was building something that would matter so much to me.&lt;/p>
&lt;p>When I started writing the first line of &lt;code>subscription-api&lt;/code> in Go, I was just trying to solve a problem: how to manage user subscriptions across Apple IAP, Alipay, and WeChat Pay. There was no team, no architecture meeting, no CI/CD pipeline. Just me, a text editor, and a growing sense of ownership.&lt;/p></description></item><item><title>2025年，还该选计算机专业吗？</title><link>https://youkre.github.io/engineering-wisdom/2025-06-07/</link><pubDate>Sat, 07 Jun 2025 00:00:00 +0800</pubDate><guid>https://youkre.github.io/engineering-wisdom/2025-06-07/</guid><description>&lt;p>高考刚过，又一批学生站在人生的十字路口：要不要选计算机专业？&lt;/p>
&lt;p>过去十几年，“学计算机=高薪”几乎成了共识。但到了2025年，情况已经变了。AI能写代码、能调试、甚至能生成完整应用——入门级程序员的“搬砖”工作，正在被机器取代。&lt;/p>
&lt;p>那么，&lt;strong>计算机专业还值得选吗？&lt;/strong>&lt;/p>
&lt;p>我的答案是：&lt;strong>值得，但前提是你真正对它感兴趣，而不是因为“它曾经很火”。&lt;/strong>&lt;/p>
&lt;h2 id="一别再盲目跟风计算机已进入深水区">一、别再盲目跟风：计算机已进入“深水区”&lt;/h2>
&lt;p>计算机产业早已过了野蛮生长的红利期。如今行业趋于成熟，竞争激烈，门槛反而更高了。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>会写代码 ≠ 有竞争力&lt;/strong>。在Copilot、Cursor、GPT等AI工具的辅助下，一个非科班学生几周就能做出一个可用的产品。&lt;/li>
&lt;li>&lt;strong>企业真正需要的，是能理解系统本质、设计复杂架构、解决真实问题的人&lt;/strong>——这恰恰是计算机专业要教你的东西。&lt;/li>
&lt;/ul>
&lt;p>所以，请问自己一个问题：&lt;/p>
&lt;blockquote>
&lt;p>我是想“学会编程”，还是想“理解计算机”？&lt;/p>&lt;/blockquote>
&lt;p>如果是前者，完全可以通过在线课程+AI工具自学；如果是后者，那计算机专业依然是不可替代的选择。&lt;/p>
&lt;p>就像为了日常交流去学英语没问题，但没必要因此去读“英语专业” —— 同理，&lt;strong>为了做项目而读计算机，可能得不偿失&lt;/strong>。&lt;/p>
&lt;h2 id="二计算机专业学编程而是学计算的原理">二、计算机专业≠学编程，而是学“计算的原理”&lt;/h2>
&lt;p>很多人以为计算机专业就是天天敲代码。其实不然。&lt;strong>真正的计算机教育，核心是理论 + 数学 + 系统思维&lt;/strong>。&lt;/p>
&lt;p>尤其在AI时代，如果你连梯度下降、矩阵分解、概率分布都搞不清，光会调用PyTorch API，很难走得远。&lt;/p>
&lt;h3 id="计算机对数学的要求比你想象中高得多">计算机对数学的要求，比你想象中高得多&lt;/h3>
&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;/ul>
&lt;p>&lt;strong>这些数学不是要你成为数学家，而是掌握基本工具&lt;/strong>。成为数学家需要相当的天赋，然而只是理解几百年前的人已经发现的数学知识，对大多数人来说，只要认真学，完全能学会，也够用。&lt;/p>
&lt;p>很多人从小对数学很畏惧，这不一定是智商问题，也许仅仅是因为在迈过那道门槛的时候，没有合适的老师/教材手把手带你走过去。选择合适的教材非常重要。有的教材一上来就摆出一张臭脸，拿鞭子抽打蹒跚学步的婴儿，嫌弃走得慢，姿势不标准，达不到奥运冠军的速度。这种教材是最容易遇到的，请毫不犹豫丢掉它们。找那种能能温柔地牵着你的手、一步一步带你走下去的。&lt;/p>
&lt;h2 id="三先看看计算机专业到底学什么">三、先看看计算机专业到底学什么&lt;/h2>
&lt;p>在决定是否报考前，不妨先了解这个专业的真实面貌。以下是我整理的核心课程与推荐读物，适合高中生或大一新生提前预习。&lt;/p>
&lt;h3 id="-数学基础">📚 数学基础&lt;/h3>
&lt;p>前四门数学课（微积分、线代、概率、统计）不仅是AI的基础，也应是&lt;strong>每个大学生的通识素养&lt;/strong>，不论什么专业，都应该学一学。&lt;/p>
&lt;h4 id="微积分">微积分&lt;/h4>
&lt;p>这几本教材任选其一作为入门都很合适：&lt;/p>
&lt;ul>
&lt;li>《普林斯顿微积分读本》（友好入门）&lt;/li>
&lt;li>《斯图尔特微积分》（系统全面，已有中文上册）&lt;/li>
&lt;li>《Calculus》 Ron Lason。也是一本非常棒的入门教材，可惜没有中文版&lt;/li>
&lt;/ul>
&lt;h4 id="线性代数">线性代数&lt;/h4>
&lt;ul>
&lt;li>《线性代数导论》（Gilbert Strang 著，第5版有中文）&lt;/li>
&lt;/ul>
&lt;h4 id="概率论">概率论&lt;/h4>
&lt;p>学完微积分后，就可以开始学习概率论。概率论中的一些知识需要用到积分知识。概率论入门可供选择的教材也不少：&lt;/p>
&lt;ul>
&lt;li>《概率论基础教程》（Sheldon Ross）&lt;/li>
&lt;li>《哈佛概率公开课》&lt;/li>
&lt;li>《统计学》，David Freedman，据说很经典的教程，可惜已经很难买到了&lt;/li>
&lt;/ul>
&lt;h4 id="统计学">统计学&lt;/h4>
&lt;p>这两本都是入门级的，不需要多强的数学知识。&lt;/p>
&lt;ul>
&lt;li>《行为科学统计》（高中数学即可入门）&lt;/li>
&lt;li>《基础统计学》，Mario F Triola。&lt;/li>
&lt;/ul>
&lt;h4 id="离散数学">离散数学&lt;/h4>
&lt;ul>
&lt;li>《离散数学及其应用》（Kenneth Rosen）—— 计算机的“专属数学”&lt;/li>
&lt;/ul>
&lt;h3 id="-计算机核心理论">💻 计算机核心理论&lt;/h3>
&lt;p>这才是专业的价值所在。在学习上述数学课程时，可以同步学习计算机的理论知识。这些知识并不十分依赖数学，至少入门阶段如此。有些书很厚，需要耐心读，不过厚并不意味着难，只是作者怕你学不会所以写的详细而已。&lt;/p>
&lt;h4 id="计算机系统">计算机系统&lt;/h4>
&lt;ul>
&lt;li>《计算机系统概论》（Yale Patt）—— 薄而精&lt;/li>
&lt;li>《深入理解计算机系统》（CSAPP）—— 经典但厚，建议配合实验&lt;/li>
&lt;li>《计算机程序的构造和解释》 可以让你了解软件和编程层面的原理。&lt;/li>
&lt;/ul>
&lt;h4 id="算法">算法&lt;/h4>
&lt;ul>
&lt;li>《算法图解》→ 入门友好&lt;/li>
&lt;li>《算法导论》→ 进阶参考（不必硬啃）&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>⚠️ 关于刷题：&lt;strong>如果不是为了面试，LeetCode不必强求&lt;/strong>。理解算法思想比刷100道题更重要。&lt;/p></description></item></channel></rss>