语言模型说哪种语言?

Reddit r/artificial 新闻

摘要

本文探讨大型语言模型是否拥有“母语”(很可能是英语),以及它们如何通过共享的概念空间或“语义中枢”处理多语言输入,并使用logit透镜探查内部表征。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/22 02:20

# 语言模型说什么语言? 来源:https://tcz.hu/blog/2026/07/22/what-language-do-language-models-speak/ 语言模型说什么语言?2026年7月22日 你有没有遇到过这种情况? 你用非母语(比如英语)和别人聊天,眼睛扫过一些用你母语写的文字。你无意识地“切换开关”,开始用母语说话,让你的朋友很惊讶。 我们能像这样“绊倒”语言模型吗?LLM的“母语”到底是什么?我们能让他们忘记如何说一种语言吗?我们能用同样的技巧解除语言模型的限制,让它们写关于科技CEO的露骨情色小说吗? ## 仿生人会梦见电子羊吗——用英语? 现代LLM是多语言的,但它们的训练数据绝大多数是英语。例如,Llama 3预训练token中只有大约8%(https://arxiv.org/pdf/2407.21783)是非英语的。商业模型的训练数据是严格保密的,但它们很可能严重偏向英语,仅仅因为互联网上的文本绝大多数是英语(https://commoncrawl.github.io/cc-crawl-statistics/plots/languages)。 然而,这些模型会说多种语言,并且在多语言任务上表现不错(https://benchlm.ai/multilingual)(https://artificialanalysis.ai/models/multilingual)。当你用日语问问题时,它们会用日语“思考”吗? 有理论认为它们不会。相反,它们首先将问题翻译成某种带有英语色彩的概念空间,在那里思考,然后将答案翻译回日语。Wu等人(2024)(https://arxiv.org/pdf/2411.04986)从神经科学借用了术语来描述这个共享概念空间:*语义枢纽*。他们和其他人(https://arxiv.org/abs/2402.10588)使用对数几率透镜提供了其存在的证据。 ## 阅读模型的思想 大型语言模型大致这样生成文本: 1. 提示中的每个token被独热编码成词汇表大小的向量。 2. 这些向量然后被投影到更小维度的向量空间中。这个投影是在训练中学习的,称为嵌入。 3. 小维度的向量然后被传递到第一层,在那里进行一些*学习到的数学运算*来改变它们的值。这种学习到的数学运算让它们交换信息并提取存储在模型权重中的相关知识。 4. 然后它们被传递到下一层,该层进行自己的学习到的数学运算并传递下去。层之间传递的向量称为残差流。 5. 在最后一层之后,最后一个向量使用另一个学习到的投影(解嵌入矩阵)被“解嵌入”。结果是原始独热编码大小的向量,但这次在大多数(如果不是全部)位置上包含非零值(对数几率)。 6. 这些值经过softmax,转换为每个token的概率分数。生成的token从最高概率的token中选择。 7. 新token被追加到原始提示中,然后重复。 对数几率透镜背后的想法是观察到残差流在最后一层之前就已经包含了语义相关信息。这个过程类似于在层之间逐步草拟和完善概念。对数几率透镜只是在每一层之后(而不是只在最后一层)过早地应用解嵌入矩阵,以便可以观察和解释中间的对数几率。 ## 五种语言的十四个问题 一个寻找*语义枢纽*的简单实验可以是这样的:模型(这里是42层的Gemma 2 9B)被用多种语言问一个简单的问题。对数几率透镜揭示了不同语言的正向传播中残差流的相似性。提示包括如下所示的*填空*问题。测试用了14个不同的问题,确保答案没有重叠的token,并且模型能够正确回答。 | 语言 | 提示 | 答案 | |------|------|------| | 英语 | The bright star that gives the Earth light and warmth. It is called | sun | | 西班牙语 | La estrella brillante que da luz y calor a la Tierra. Se llama | sol | | 匈牙利语 | Az égen ragyogó csillag, amely meleget és fényt ad. A neve | nap | | 日语 | 空に輝き、昼間に光と熱を与える星。これは | 太陽 | | 中文 | 在天空照耀、给白天带来光和热的星球。这叫 | 太阳 | | 英语 | The red liquid that flows through your veins. It is called | blood | 下面的图表显示了模型分配给英语答案token(例如*sun*)与提示母语答案(例如*太陽*)的概率。 英语答案 vs 母语答案的对数几率透镜 当然,第一个面板中英语token就是母语token,所以它们的概率是一样的。但注意对于非英语语言,英语token的概率在母语token之前上升,在大约22-23层达到峰值,然后下降并让位于母语答案。模型首先想出英语回答,然后在最后几层将其“翻译”回提示的语言。 所有14个问题的英语token平均概率在所有情况下都超过0.5。这真的证实了英语语义枢纽吗?我们可以通过检查在每一层正确的英语答案token是否是最可能的token来获得更强的信号。 英语回答作为最高token的对数几率透镜 这种效果在某些语言中比在其他语言中更强,但所有语言都显示出类似的模式。如果你好奇,这种机制非常类似于语言模型学习静默纠正提示中拼写错误的方式。LLM在前几层内将拼写错误的单词重新组合成正确单词的表示。考虑到它们看不到字符(并且众所周知无法数出*strawberry*中的r的个数),这令人印象深刻。更多信息参见Kaplan等人(https://arxiv.org/abs/2410.05864)和Feucht等人(https://aclanthology.org/2024.emnlp-main.543/)。 ## 苹果与余弦 怀疑论者可能会说:当然,token概率很有趣,但解嵌入矩阵是偏向英语的。对数几率透镜是一个不完美的工具。我们能否在不触及词汇表的情况下确认语义枢纽?一个想法是比较英语和另一种语言在每一层的残差流向量,看看它们有多相似。 表示相似性通常意味着向量之间的余弦相似度。顾名思义:测量两个向量之间夹角的余弦,忽略它们的长度。 \[ \text{余弦相似度} = \cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|} \] 一个1000维的苹果 你知道一个1000维的苹果几乎全是皮吗?如果苹果的皮大约是半径的0.3%,在一千维中它就会占据苹果体积的95%。高维可能违反直觉。所以通常我们不信任距离,而是通过向量之间的角度(或角度的余弦)来比较两个向量,忽略它们的长度。 多维苹果 下面的图表显示了英语和其他语言在残差流中每一层向量的角度余弦。 英语与其他语言在残差流中的余弦角度 这些线形成一个凸起。向量开始时与英语不相似:这是有道理的,因为它们是不同的token,有不同的嵌入,并且在早期层中学习到的数学运算还未能显著改变它们的值。在中间层,它们变得与英语向量非常相似,为共享表示空间提供了间接证据。在最后几层,它们再次分离,准备以问题的语言输出答案。 但如果中间层的残差流如此相似,模型如何知道它必须用,比如说,日语回答?语言的身份住在哪里? ## 解开鸡蛋 稀疏自编码器(SAE)是机制可解释性中常用的工具。神经网络激活,如残差流或子层激活(例如在注意力头或MLP之后),是携带大量信息的密集向量。在最后一层之后,最后一个提示token的残差流包含了压缩后的提示和来自前面层的相关模型知识,以便生成最佳响应token。这种信息密度使得激活向量难以解释。 SAE试图通过训练一个神经网络预测自己的输入来解压缩这些向量中存储的信息。SAE的隐藏层通常比输入向量具有更高的维度。在训练过程中,我们在损失中加入稀疏性惩罚1(https://tcz.hu/blog/2026/07/22/what-language-do-language-models-speak/#fn:penalty),从而推动隐藏层具有更少的非零项。在实践中,这可以通过解开输入向量中嵌入的特征和概念,使输入向量更易于解释。这类似于transformer中的解嵌入步骤,因为它将低维输入映射到具有语义意义的高维输出(在这里是SAE的隐藏层)。 ```python import torch import torch.nn as nn class SparseAutoencoder(nn.Module): def __init__(self, d_in: int, d_hidden: int): super().__init__() self.encoder = nn.Linear(d_in, d_hidden) self.decoder = nn.Linear(d_hidden, d_in) def encode(self, x: torch.Tensor) -> torch.Tensor: return torch.relu(self.encoder(x)) def decode(self, f: torch.Tensor) -> torch.Tensor: return self.decoder(f) def forward(self, x: torch.Tensor): f = self.encode(x) x_hat = self.decode(f) return x_hat, f def sae_loss(x, x_hat, feature_activations, sparsity_coeff: float = 1e-3): reconstruction_error = (x_hat - x).pow(2).mean() # simple MSE activation_mean_abs = feature_activations.abs().mean() # 平均项值。 # abs()的梯度创造了对小值的向下压力 return reconstruction_error + sparsity_coeff * activation_mean_abs ``` 你可以在下面尝试一个玩具示例。 在交互式示例中,提取的特征被整齐地标记了,但SAE不会开箱即用地告诉你什么是什么。这是无监督学习,你只得到一堆权重,可以为特定激活的提示提供一个长向量。然而我们知道,Gemma 2 9B第24层第10502个位置的特征意味着“狗”(https://www.neuronpedia.org/gemma-2-9b/24-gemmascope-res-16k/10502)。 解释SAE特征如何被标记远远超出了本文的范围,但要点是:大量文本通过模型和附带的SAE运行。对于每个输入,记录最强的特征,然后与输入文本中的token进行相关性分析。最终的标记通常由另一个LLM完成,它为与特征相关的输入token提出一个共享概念术语。 当然,并非所有特征都被正确标记。但要回答“语言的身份住在哪里?”这个问题,我们甚至不需要它们被标记。我们只需为每种语言运行我们的概念提示,找到对于给定概念在所有语言中都激活,或者对于给定语言在所有概念中都激活,而在其他情况下保持沉默的特征。 ```python LANGS = ["en", "es", "hu", "ja", "zh"] CONCEPTS = ["sun", "ice", "blood", ...] LAYER = 34 # 选择你的层 A = np.zeros((5, 14, 16384)) for i, lang in enumerate(LANGS): for j, concept in enumerate(CONCEPTS): resid = run_model(prompt(lang, concept), layer=LAYER) A[i, j] = sae.encode(resid) for j, concept in enumerate(CONCEPTS): # 必须在所有5种语言中对此概念激活 signal = A[:, j, :].min(axis=0) # 必须不对任何其他概念激活 others = np.delete(A, j, axis=1) leak = others.reshape(-1, 16384).max(axis=0) margin = signal - leak best_feature[concept] = np.argmax(margin) # 对于语言特征,做镜像操作: for i, lang in enumerate(LANGS): signal = A[i, :, :].min(axis=0) leak = np.delete(A, i, axis=0).reshape(-1, 16384).max(axis=0) margin = signal - leak best_feature[lang] = np.argmax(margin) ``` 在这个实验中,最强的尺度归一化边界恰好出现在第34层。让我们看看那里最强的和最弱的“最佳”语言和概念特征。 在第34层,跨概念和语言的最强SAE特征 它们就在那里。对于“太阳”概念,特征#11770(https://www.neuronpedia.org/gemma-2-9b/34-gemmascope-res-16k/11770)在每种语言中都强烈激活。确实,Neuronpedia已经将其标记为*“参考文献中涉及天体,特别是太阳及其影响的引用”*。语言特征也类似地强烈激活,但由于AutoInterp仅根据顶部激活的输入token来标记特征,它难以正确标记这些特征: | 语言 | 特征 | Neuronpedia自动解释标签 | |------|------|-------------------------| | 西班牙语 | #14911(https://www.neuronpedia.org/gemma-2-9b/34-gemmascope-res-16k/14911) | “表达对编程概念的好奇或探究的短语” | | 匈牙利语 | #1639(https://www.neuronpedia.org/gemma-2-9b/34-gemmascope-res-16k/1639) | “结构化上下文中特定的数字或基于代码的标识符,特别是与技能或分类相关的” | | 日语 | #5827(https://www.neuronpedia.org/gemma-2-9b/34-gemmascope-res-16k/5827) | “技术上下文中对编程错误和故障排除的引用” | | 中文 | #15002(https://www.neuronpedia.org/gemma-2-9b/34-gemmascope-res-16k/15002) | “与编程概念和用户界面元素相关的词语” | 我发现这些解释有趣地错误。 但我们的数据是令人信服的:即使是最弱的信号也有很强的边界并且几乎不泄漏。当然,这些特征可能并非唯一负责携带语言信息的,但它们是这一层中最强的。我们可以用它们来控制模型回答的语言吗? ## 翻转开关 让我们试试这个:当我们生成下一个token时,将SAE中识别的语言特征钳制到高值2(https://tcz.hu/blog/2026/07/22/what-language-do-language-models-speak/#fn:clamp)或低值。使用`transformer_lens`很容易做到: ```python sae = load_sae(layer=34) clamps = {HUNGARIAN_FEATURE: 300.0} def sae_hook(resid, hook): x = resid[:, -1, :] # 正在生成的token的残差 acts = sae.encode(x) for f, v in clamps.items(): x = x + (v - acts[:, f]) * sae.W_dec[f] resid[:, -1, :] = x return resid with model.hooks([("blocks.34.hook_resid_post", sae_hook)]): output = model.generate(prompt, max_new_tokens=8) ``` 模型开始用目标语言回答,很像你在阅读另一种语言的文字后下意识地切换口语。几个例子: | 层34的特征 | 钳制值`v` | 提示语言 | 基线 | 引导后 | |------------|------------|----------|------|--------| | 中文 #15002 | 300 | 英语 | `king` | **`国王`**(king) | | 中文 #15002 | 300 | 英语 | `snow` | **`雪`**(snow) | | 匈牙利语 #1639 | 300 | 英语 | `king` | **`király`**(king) | | 日语 #5827 | 300 | 英语 | `snow` | **`雪`**(snow) | 这很粗糙,但有效,尽管我们只钳制了单个层中的单个特征。语言身份存在于所有层中,并且可能每一层都与几个SAE特征相关。为了更精确的引导,我们可以识别所有层中的所有相关特征并钳制它们。不过,即使这个懒惰的版本也能完成任务。 你能从一种非英语语言切换到另一种吗?让我们尝试将一个钳制为零,另一个钳制为高: | 层34的特征 | 钳制值`v` | 提示语言 | 基线 | 引导后 | |------------|------------|----------|------|--------| | 匈牙利语 #1639 | #1639 → 0 | 匈牙利语 | `király` | `king` (英语) | | 日语 #5827 | #5827 → 300 | | | |

相似文章

大语言模型的记忆

arXiv cs.CL

本综述系统性地提出了大型语言模型中记忆机制的分类法,从表示、更新动态和持久性三个维度进行分类,并形式化了底层机制组件。

理解大型语言模型

arXiv cs.CL

本章回顾了当前对大型语言模型的理解,讨论了它们的Transformer架构、类似人类认知的涌现能力,以及关于LLM是真正理解还是仅仅模拟理解的争论。