LLM 学习笔记 1——Transformer
该研究研究了,早该研究啦。整蛊的地方是我消耗最多 Token 的地方,居然是 SillyTavern……但也算是一个基础了。
LLM 整体架构
LLM 没有真正的魔法——它只是根据现有 token,预测下一个 token 是什么,就像代码的自动补全。它没有智能,它只是预测,但神奇的是,在参数量、数据量达到超大规模时,LLM 就像涌现出了智能,好像就懂了人类的逻辑思考了,连图灵测试都给你通过了。当然,也仅仅是好像而已。
这里的几个重点是:
- 这里没有“理解”,没有“意识”,只有统计——LLM 只是从全互联网的人类文本中总结出了某种黑箱般的模式,虽然我们还无法解释这背后究竟发生了什么
- LLM 根据整个上下文窗口(比如我们常说的 128K 上下文,1M 上下文)去进行预测,且有能力去明确之前的哪些上下文对当前的这次生成更重要(注意力机制)
- 对每个下一个 token,LLM 每次能预测出可能出现的所有 token 以及相关概率,但常通过一定的随机性去保证生成不枯燥(始终选择概率最高的 token 的话会太机械),温度是其中最常用的配置参数,温度越高,输出越灵活
- “涌现”——这种系统规模成长后(量变)突然出现在较小系统中不存在的新能力和行为(质变)称为涌现,它是意外,是黑箱,我们完全无法预测它何时会发生,也无法解释它。
注意力机制和推理流程
注意力机制是 Transformer 的灵魂——对每个 Token 的理解,都同时考虑到(或者说参考?)整个上下文的所有 Token 和这个 Token 的相关性。和这个 Token 相关性越高的 Token 就参与到这里的“理解”更多。
具体的来说,每个 Token 包含三个部分——Query,Key,Value(这里虽然说“包含”,但其实它们三者全是上下文相关的):
- Query:我和什么相关(查询目标)
- Key:什么和我相关(索引)
- Value:我是谁(实际内容)
每个 Token,都由它的 Query 和其他 Token 的 Key,去计算出每个 Token 和它的相关性,而这个 Token 的用于推理的实际表示为所有输入 Token 的以相关性为权重的 Value 集合的加和。推理时,神经网络看到的输入就是这个加和,使用它去预测下一个 Token,然后重新计算相关性,注意力……
但实际使用下来我们知道还有一个所谓的 KV 缓存,它避免每次完全重新计算;KV 缓存的核心是只计算新 Token 的 Q,复用之前所有 Token 的 K 和 V,这个复用证明之前的 Token 的 K 和 V 仅和它及它之前的 Token 相关,后来的 Token 不会改变之前的 Token 的 K,V。
Q 呢?我们注意到,我们其实不需要计算所有 Token 的 Q——我们只需要使用最后一个 Token 的 Q 和其他 Token 的 Key 去得到相关性,再用这个相关性去加权 Value 然后加和去得到注意力,我们完全不需要其他 Token 的 Q。而 Q 的计算……假设我们的 Transformer 是单层的话,它来自于 Token 自己和模型既有的 Query 权重矩阵。
而训练的时候我们需要计算所有 Token 的 Q,但这个就没必要去学习了。
多模态怎么说?
多模态其实没啥特殊的,就是将图像、音频等和文字映射到同一个嵌入向量空间中,让它们能一起丢给 AI 让它去推理。
但多模态 AI 一般来说仅用于理解多模态,而不用于生成多模态(那是另一套东西)。实际上就没有相应的解码器存在。这是设计如此。
为何 LLM 采取对话的形式?
对话最为自然,谁都能用,过去的对话自然而然就是上下文(而且事实上正是对话才让它能够“表现为”智能……不然纯粹拿来写小说吗?),这是产品化的结果,在背后,对话的上下文仍旧会被转化为 Token 序列。
Role,File,Tool,思维链等是怎么引入的?
而要实现对话式,训练时需要进行特殊的处理,需要特殊的训练数据,比如使用特定的掩码去标识 System,Assistant,User 的对话首尾,System 消息被加权,以及 AI 仅预测 Assistant 回复而非去预测所有 Token。而 File,Tool,思维链等,也全是在训练时需要进行特殊的处理,需要特殊的训练数据。
为什么 LLM 会输出 Markdown?因为训练数据就长这样——训练数据被格式化为 Markdown。
关于幻觉(hallucination)
LLM 的背后归根结底是统计学,这会导致它会一本正经地胡说八道,写出一些看似合理但实则错误的内容以及前后不一致,而这是当前 LLM 架构必然带来的结构性的问题。我们希望 AI 说“我不知道”,但 AI 并未被训练地如此。
使用 RAG,联网搜索等可以一定程度上避免幻觉。
OpenAI Chat Completion API 参数
带着上面的理解,看看对话补全API的常用参数:
- model:使用的模型,不同的模型对应不同的参数量,训练数据,上下文长度……
- messages:对话消息,包含role信息,将被转换为token序列去作为输入
- temperature:温度,温度用于调整下一个Token的概率分布,为1时表示保持训练时的原始分布,为0时贪心总是选择概率最高的
- top_p:只从前 XX% 概率的Token中采样(将可选Token按概率降序排序,从前往后选择直到概率的和超过这个数,如
0.4, 0.3, 0.2, 0.05, 0.03, 0.02这样有6个可选Token,0.9 的top_p会只选择0.4, 0.3, 0.2三个 token 作为候选(显然这里应该是先走top_p再走temperature,但一般只改 temperature,top_p锁定为1) - max_tokens:助手回复的最大长度(但设置这个可能会导致 AI 的回复被直接截断)
- frequency_penalty: 惩罚整个上下文中出现次数多的Token的出现(出现越多惩罚越大,减少高频词)
- presence_penalty: 惩罚整个上下文中已经出现的Token的出现(只要存在就有惩罚,鼓励使用全新词汇)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议 ,转载请注明出处!