Selaa lähdekoodia

fix formula bug

jjyaoao 9 kuukautta sitten
vanhempi
sitoutus
570366fc21

+ 5 - 5
docs/chapter2/第二章 智能体发展史.md

@@ -382,11 +382,11 @@ ELIZA的实践清晰地揭示了符号主义方法的核心矛盾:系统看似
 
 这个循环的具体步骤如下:
 
-1. 在时间步t,智能体观察到环境的当前状态$$S_{t}$$。
-2. 基于状态 $$S_{t}$$,智能体根据其内部的**策略(Policy, π)**选择一个行动 $$A_{t}$$ 并执行它。策略本质上是一个从状态到行动的映射,定义了智能体的行为方式。
-3. 环境接收到行动 $$A_{t}$$ 后,会转移到一个新的状态 $$S_{t+1}$$。
-4. 同时,环境会反馈给智能体一个即时奖励 $$R_{t+1}$$。
-5. 智能体利用这个反馈(新状态 $$S_{t+1}$$ 和奖励 $$R_{t+1}$$)来更新和优化其内部策略,以便在未来做出更好的决策。这个更新过程就是学习。
+1. 在时间步t,智能体观察到环境的当前状态$S_{t}$。
+2. 基于状态 $S_{t}$,智能体根据其内部的**策略(Policy, π)**选择一个行动 $A_{t}$ 并执行它。策略本质上是一个从状态到行动的映射,定义了智能体的行为方式。
+3. 环境接收到行动 $A_{t}$ 后,会转移到一个新的状态 $S_{t+1}$。
+4. 同时,环境会反馈给智能体一个即时奖励 $R_{t+1}$。
+5. 智能体利用这个反馈(新状态 $S_{t+1}$ 和奖励 $R_{t+1}$)来更新和优化其内部策略,以便在未来做出更好的决策。这个更新过程就是学习。
 
 智能体的学习目标,并非最大化某一个时间步的即时奖励,而是最大化从当前时刻开始到未来的**累积奖励(Cumulative Reward)**,也称为**回报(Return)**。这意味着智能体需要具备“远见”,有时为了获得未来更大的奖励,需要牺牲当前的即时奖励(例如,围棋中的“弃子”策略)。通过在上述循环中不断探索、收集反馈并优化策略,智能体最终能够学会在复杂动态环境中进行自主决策和长期规划。
 

+ 21 - 21
docs/chapter3/第三章 大模型基础.md

@@ -10,20 +10,20 @@
 
 **(1)统计语言模型与** **N-gram** **的思想**
 
-在深度学习兴起之前,统计方法是语言模型的主流。其核心思想是,一个句子出现的概率,等于该句子中每个词出现的条件概率的连乘。对于一个由词 $$w_1,w_2,dots,w_m$$ 构成的句子 S,其概率 P(S) 可以表示为:
+在深度学习兴起之前,统计方法是语言模型的主流。其核心思想是,一个句子出现的概率,等于该句子中每个词出现的条件概率的连乘。对于一个由词 $w_1,w_2,dots,w_m$ 构成的句子 S,其概率 P(S) 可以表示为:
 
 $$P(S)=P(w_1,w_2,…,w_m)=P(w_1)⋅P(w_2∣w_1)⋅P(w_3∣w_1,w_2)⋯P(w_m∣w_1,…,w_{m−1})$$
 
-这个公式被称为概率的链式法则。然而,直接计算这个公式几乎是不可能的,因为像 $$P(w_m∣w_1,dots,w_{m−1})$$ 这样的条件概率太难从语料库中估计了,词序列 $$w_1,dots,w_{m−1}$$ 可能从未在训练数据中出现过。
+这个公式被称为概率的链式法则。然而,直接计算这个公式几乎是不可能的,因为像 $P(w_m∣w_1,dots,w_{m−1})$ 这样的条件概率太难从语料库中估计了,词序列 $w_1,dots,w_{m−1}$ 可能从未在训练数据中出现过。
 
 <div align="center">
   <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/3-figures/1757249275674-0.png" alt="图片描述" width="90%"/>
   <p>图 3.1 马尔可夫假设示意图</p>
 </div>
 
-为了解决这个问题,研究者引入了**马尔可夫假设 (Markov Assumption)**。其核心思想是:我们不必回溯一个词的全部历史,可以近似地认为,一个词的出现概率只与它前面有限的 $$n−1$$ 个词有关,如图3.1所示。基于这个假设建立的语言模型,我们称之为 **N-gram** **模型**。这里的 "N" 代表我们考虑的上下文窗口大小。让我们来看几个最常见的例子来理解这个概念:
+为了解决这个问题,研究者引入了**马尔可夫假设 (Markov Assumption)**。其核心思想是:我们不必回溯一个词的全部历史,可以近似地认为,一个词的出现概率只与它前面有限的 $n−1$ 个词有关,如图3.1所示。基于这个假设建立的语言模型,我们称之为 **N-gram** **模型**。这里的 "N" 代表我们考虑的上下文窗口大小。让我们来看几个最常见的例子来理解这个概念:
 
-- **Bigram (当 N=2 时)**:这是最简单的情况,我们假设一个词的出现只与它前面的一个词有关。因此,链式法则中复杂的条件概率 $$P(w_i∣w_1,dots,w_{i−1})$$ 就可以被近似为更容易计算的形式:
+- **Bigram (当 N=2 时)**:这是最简单的情况,我们假设一个词的出现只与它前面的一个词有关。因此,链式法则中复杂的条件概率 $P(w_i∣w_1,dots,w_{i−1})$ 就可以被近似为更容易计算的形式:
 
 $$P(w_{i}∣w_{1},…,w_{i−1})≈P(w_{i}∣w_{i−1})$$
 
@@ -31,28 +31,28 @@ $$P(w_{i}∣w_{1},…,w_{i−1})≈P(w_{i}∣w_{i−1})$$
 
 $$P(w_i∣w_1,…,w_{i−1})≈P(w_i∣w_{i−2},w_{i−1})$$
 
-这些概率可以通过在大型语料库中进行**最大似然估计** **(****Maximum Likelihood Estimation****,** **MLE****)** 来计算。这个术语听起来很复杂,但其思想非常直观:最可能出现的,就是我们在数据中看到次数最多的。例如,对于 Bigram 模型,我们想计算在词 $$w_{i−1}$$ 出现后,下一个词是 $$w_i$$ 的概率 $$P(w_i∣w_{i−1})$$。根据最大似然估计,这个概率可以通过简单的计数来估算:
+这些概率可以通过在大型语料库中进行**最大似然估计** **(****Maximum Likelihood Estimation****,** **MLE****)** 来计算。这个术语听起来很复杂,但其思想非常直观:最可能出现的,就是我们在数据中看到次数最多的。例如,对于 Bigram 模型,我们想计算在词 $w_{i−1}$ 出现后,下一个词是 $w_i$ 的概率 $P(w_i∣w_{i−1})$。根据最大似然估计,这个概率可以通过简单的计数来估算:
 
 $$P(w_i∣w_{i−1})=Count(w_{i−1})Count(w_{i−1},w_i)$$
 
 这里的 `Count()` 函数就代表“计数”:
 
-- $$Count(w_i−1,w_i)$$:表示词对 $$(w_{i−1},w_i)$$ 在语料库中连续出现的总次数。
-- $$Count(w_{i−1})$$:表示单个词 $$w_{i−1}$$ 在语料库中出现的总次数。
+- $Count(w_i−1,w_i)$:表示词对 $(w_{i−1},w_i)$ 在语料库中连续出现的总次数。
+- $Count(w_{i−1})$:表示单个词 $w_{i−1}$ 在语料库中出现的总次数。
 
-公式的含义就是:我们用“词对 $$Count(w_i−1,w_i)$$ 出现的次数”除以“词 $$Count(w_{i−1})$$ 出现的总次数”,来作为 $$P(w_i∣w_{i−1})$$ 的一个近似估计。
+公式的含义就是:我们用“词对 $Count(w_i−1,w_i)$ 出现的次数”除以“词 $Count(w_{i−1})$ 出现的总次数”,来作为 $P(w_i∣w_{i−1})$ 的一个近似估计。
 
 为了让这个过程更具体,我们来手动进行一次计算。假设我们拥有一个仅包含以下两句话的迷你语料库:`datawhale agent learns`, `datawhale agent works`。我们的目标是:使用 Bigram (N=2) 模型,估算句子 `datawhale agent learns` 出现的概率。根据 Bigram 的假设,我们每次会考察连续的两个词(即一个词对)。
 
-**第一步:计算第一个词的概率** $$P(datawhale)$$ 这是 `datawhale` 出现的次数除以总词数。`datawhale` 出现了 2 次,总词数是 6。
+**第一步:计算第一个词的概率** $P(datawhale)$ 这是 `datawhale` 出现的次数除以总词数。`datawhale` 出现了 2 次,总词数是 6。
 
 $$P(\text{datawhale}) = \frac{\text{总语料中"datawhale"的数量}}{\text{总语料的词数}} = \frac{2}{6} \approx 0.333$$
 
-**第二步:计算条件概率** $$P(agent∣datawhale)$$ 这是词对 `datawhale agent` 出现的次数除以 `datawhale` 出现的总次数。`datawhale agent` 出现了 2 次,`datawhale` 出现了 2 次。
+**第二步:计算条件概率** $P(agent∣datawhale)$ 这是词对 `datawhale agent` 出现的次数除以 `datawhale` 出现的总次数。`datawhale agent` 出现了 2 次,`datawhale` 出现了 2 次。
 
 $$P(\text{agent}|\text{datawhale}) =  \frac{\text{Count}(\text{datawhale agent})}{\text{Count}(\text{datawhale})} =  \frac{2}{2} = 1$$
 
-**第三步:计算条件概率** $$P(learns∣agent)$$ 这是词对 `agent learns` 出现的次数除以 `agent` 出现的总次数。`agent learns` 出现了 1 次,`agent` 出现了 2 次。
+**第三步:计算条件概率** $P(learns∣agent)$ 这是词对 `agent learns` 出现的次数除以 `agent` 出现的总次数。`agent learns` 出现了 1 次,`agent` 出现了 2 次。
 
 $$P(\text{learns}|\text{agent}) =  \frac{\text{Count(agent learns)}}{\text{Count(agent)}} =  \frac{1}{2} = 0.5$$
 
@@ -111,7 +111,7 @@ N-gram 模型的根本缺陷在于它将词视为孤立、离散的符号。为
 其核心思想可以分为两步:
 
 1. **构建一个语义空间**:创建一个高维的连续向量空间,然后将词汇表中的每个词都映射为该空间中的一个点。这个点(即向量)就被称为**词嵌入 (Word Embedding)** 或词向量。在这个空间里,语义上相近的词,它们对应的向量在空间中的位置也相近。例如,`agent` 和 `robot` 的向量会靠得很近,而 `agent` 和 `apple` 的向量会离得很远。
-2. **学习从上下文到下一个词的映射**:利用神经网络的强大拟合能力,来学习一个函数。这个函数的输入是前 $$n−1$$ 个词的词向量,输出是词汇表中每个词在当前上下文后出现的概率分布。
+2. **学习从上下文到下一个词的映射**:利用神经网络的强大拟合能力,来学习一个函数。这个函数的输入是前 $n−1$ 个词的词向量,输出是词汇表中每个词在当前上下文后出现的概率分布。
 
 <div align="center">
   <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/3-figures/1757249275674-1.png" alt="图片描述" width="90%"/>
@@ -295,12 +295,12 @@ class DecoderLayer(nn.Module):
 - **键 (Key, K)**: 代表句子中可被查询的词元“标签”或“索引”。
 - **值 (Value, V)**: 代表词元本身所携带的“内容”或“信息”。
 
-这三个向量都是由原始的词嵌入向量乘以三个不同的、可学习的权重矩阵 ($$W^Q,W^K,W^V$$) 得到的。整个计算过程可以分为以下几步,我们可以把它想象成一次高效的开卷考试:
+这三个向量都是由原始的词嵌入向量乘以三个不同的、可学习的权重矩阵 ($W^Q,W^K,W^V$) 得到的。整个计算过程可以分为以下几步,我们可以把它想象成一次高效的开卷考试:
 
-- 准备“考题”和“资料”:对于句子中的每个词,都通过权重矩阵生成其$$Q,K,V$$向量。
-- 计算相关性得分:要计算词$$A$$的新表示,就用词$$A$$$$Q$$向量,去和句子中所有词(包括$$A$$自己)的$$K$$向量进行点积运算。这个得分反映了其他词对于理解词$$A$$的重要性。
-- 稳定化与归一化:将得到的所有分数除以一个缩放因子$$\sqrt{d_{k}}$$$$d_{k}$$$$K$$向量的维度),以防止梯度过小,然后用Softmax函数将分数转换成总和为1的权重,也就是归一化的过程。
-- 加权求和:将上一步得到的权重分别乘以每个词对应的$$V$$向量,然后将所有结果相加。最终得到的向量,就是词$$A$$融合了全局上下文信息后的新表示。
+- 准备“考题”和“资料”:对于句子中的每个词,都通过权重矩阵生成其$Q,K,V$向量。
+- 计算相关性得分:要计算词$A$的新表示,就用词$A$的$Q$向量,去和句子中所有词(包括$A$自己)的$K$向量进行点积运算。这个得分反映了其他词对于理解词$A$的重要性。
+- 稳定化与归一化:将得到的所有分数除以一个缩放因子$\sqrt{d_{k}}$($d_{k}$是$K$向量的维度),以防止梯度过小,然后用Softmax函数将分数转换成总和为1的权重,也就是归一化的过程。
+- 加权求和:将上一步得到的权重分别乘以每个词对应的$V$向量,然后将所有结果相加。最终得到的向量,就是词$A$融合了全局上下文信息后的新表示。
 
 这个过程可以用一个简洁的公式来概括:
 
@@ -386,7 +386,7 @@ class MultiHeadAttention(nn.Module):
 
 $$\operatorname{FFN}(x)=\max\left(0, xW_{1}+b_{1}\right) W_{2}+b_{2}$$
 
-其中,$$x$$是注意力子层的输出。 $$W_1,b_1,W_2,b_2$$是可学习的参数。通常,第一个线性层的输出维度 `d_ff` 会远大于输入的维度 `d_model`(例如 `d_ff = 4 * d_model`),经过 ReLU 激活后再通过第二个线性层映射回 `d_model` 维度。这种“先扩大再缩小”的模式,也被称为瓶颈结构,被认为有助于模型学习更丰富的特征表示。
+其中,$x$是注意力子层的输出。 $W_1,b_1,W_2,b_2$是可学习的参数。通常,第一个线性层的输出维度 `d_ff` 会远大于输入的维度 `d_model`(例如 `d_ff = 4 * d_model`),经过 ReLU 激活后再通过第二个线性层映射回 `d_model` 维度。这种“先扩大再缩小”的模式,也被称为瓶颈结构,被认为有助于模型学习更丰富的特征表示。
 
 在我们的 PyTorch 骨架中,我们可以用以下代码来实现这个模块:
 
@@ -418,7 +418,7 @@ class PositionWiseFeedForward(nn.Module):
 
 这个操作由两个部分组成:
 
-- **残差连接 (Add)**: 该操作将子模块的输入 `x` 直接加到该子模块的输出 `Sublayer(x)` 上。这一结构解决了深度神经网络中的**梯度消失 (Vanishing Gradients)** 问题。在反向传播时,梯度可以绕过子模块直接向前传播,从而保证了即使网络层数很深,模型也能得到有效的训练。其公式可以表示为:$$\text{Output} = x + \text{Sublayer}(x)$$。
+- **残差连接 (Add)**: 该操作将子模块的输入 `x` 直接加到该子模块的输出 `Sublayer(x)` 上。这一结构解决了深度神经网络中的**梯度消失 (Vanishing Gradients)** 问题。在反向传播时,梯度可以绕过子模块直接向前传播,从而保证了即使网络层数很深,模型也能得到有效的训练。其公式可以表示为:$\text{Output} = x + \text{Sublayer}(x)$。
 - **层归一化 (Norm)**: 该操作对单个样本的所有特征进行归一化,使其均值为0,方差为1。这解决了模型训练过程中的**内部协变量偏移 (Internal Covariate Shift)** 问题,使每一层的输入分布保持稳定,从而加速模型收敛并提高训练的稳定性。
 
 **3.1.2.5 位置编码**
@@ -432,8 +432,8 @@ $$ PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) $$,$
 其中:
 
 - pos是词元在序列中的位置(例如,0,1,2,...)
-- i是位置向量中的维度索引(从0到$$d_{\text{model}}/2$$)
-- $$d_{\text{model}}$$是词嵌入向量的维度(与我们模型中定义的一致)
+- i是位置向量中的维度索引(从0到$d_{\text{model}}/2$)
+- $d_{\text{model}}$是词嵌入向量的维度(与我们模型中定义的一致)
 
 现在,我们来实现 `PositionalEncoding` 模块,并完成我们 Transformer 骨架代码的最后一部分。