AI开发者的大语言模型原理课

在学习大语言模型的基本原理的时候,发现遇到了很多问题,比如一个个单词是怎么转换为向量的,是提前得到的还是训练过程中得到?Transformer的输出向量又是怎么转化为自然语言的?Finetune的时候不是只需要输入和输出吗,为什么FineTune的脚本做了那么多的处理?找了很多资料发现基本都是在讲Transformer的原理,缺乏顶层视角的原理,最后不得已阅读了一下HuggingFace上关于LLaMA的代码才得到答案。
就像程序员也需要知道计算机硬件的基本原理一样,一个AI开发者也需要知道大语言模型的基本原理。本文主要是从AI开发者需要知道的角度来写,所以本文不会去涉及太底层的数学逻辑。下面一起来探讨一下。

整体架构

整体架构

整体框架分为两部分

  1. 分词器(Tokenizer) :将自然语言转化为TokenID的形式,大体可以理解为每个单词对应一个数字。(实际中稍有差异不过不影响理解,后面会详细说明)
  2. 模型:输入是TokenID,输出也是TokenID。大名鼎鼎的Transformer是这里面的一部分,当然了是最核心的部分。

为了便于理解,我们看一下用huggingface的transformers库来写代码是什么样的,做一下对比理解。

python
复制代码
from transformers import AutoTokenizer, LlamaForCausalLM

# 加载模型
model = LlamaForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")

#加载分词器
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")

prompt = "Who is LogicBit?"

#对输入的自然语言进行分词,转化为list[TokenID]
inputs = tokenizer(prompt, return_tensors="pt")

# 模型推理,得到list[TokenID]
generate_ids = model.generate(inputs.input_ids, max_length=30)

# 将模型的输出list[TokenID]转化为自然语言
tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]

从上面可以看出基本是和上面画的整体架构是一致的。使用接口上也是分为了分词器和模型。下面依次看一下具体的细节。

Tokenizer

目的:在计算的时候只能使用数字来进行表示,所以需要将自然语言转化为数字。
编码: 输入一个句子(str),输出:对应的TokenID的列表(List[TokenID]
解码:编码的逆向操作。
基本原理:基于训练样本,通过某种算法得到一个词汇表,然后针对每个词汇进行编号就得到单词与TokenID(也就是编号)的对应关系。

举个例子

假如我的训练样本只有who is LogicBit这句话,那么我的算法就可以直接是每个单词对应一个ID。由于在英文里面空格就是区分两个单词的,所以空格我们就可以不要了。去掉空格相当于只有三个单词。

python
复制代码
#注意一下以下的代码是一个逻辑上的意思,无法运行。
#按单词出现的顺序进行编号
tokenID['who'] = 1
tokenID['is'] = 2
tokenID['LogicBit'] = 3

#编码
tokenizer.encode('who is LogicBit') = [1, 2, 3]
#解码
tokenizer.decode([1, 2, 3]) = 'who is LogicBit'

#Too Simple, right?
扩展一下

实际使用中,其实没有上面这么简单,训练的算法是比较复杂的。因为这里面有很多的考量。比如为了提高表示效率,一个单词可能对应多个TokenID。
举个例子,look这个单词就有很多状态的词汇,现在进行时looking,过去分词looked,而watch也同样有watchedwatching。如果按照一个词汇对应一个ID,我们的词汇表就有6个['looking', 'looked', 'looking', 'watch', 'watched', 'watching'],但是如果按照词根来的话就可以表示为[look, watch, ed, ing],只需要4个即可表示。这个时候比如说looking就会对应两个TokenID, ['look', 'ing']。下面具体来看个实际的例子。

python
复制代码
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")

tokenizer.encode("who is LogicBit?")
#output:[1, 1058, 338, 4522, 293, 21591, 29973]
# 1 是llama词汇表中一个句子的起始字符,对应'<s>',每个句子都会有,自动加上去的。
# who      -> 1058
# is       -> 338
# LogicBit -> [4522, 293, 21591] ,这里就出现了一个单词对应多个tokenid的情况。
# ?        -> 29973

模型

image.png

模型整体的输入输出:输入也就是上面分词器得到的List[TokenID],输出也是List[TokenID]Embedding模块: 将每个tokenID转化为一个向量,向量的维度是模型定义的(看模型大小)。 Transformer:输入一排向量,输出另一排向量(向量的个数是一样的,向量的维度可能不一样) Output Translation:将Transformer的输出转为TokenID。

Embedding模块

image.png

  1. TokenID转化为向量

由于一个数字无法有效的衡量一个单词的含义,比如['who', 'error']对应[1058, 1059],但是你不能说whoerror是很像的东西吧,只能说毫无关系。由于一开始不知道哪个关系更近,所以就用一个向量来表示。先假设各个单词之间没有关系,然后在训练中学习。

python
复制代码
## 还是前面的例子
tokenID['who'] = 1
tokenID['is'] = 2
tokenID['LogicBit'] = 3

#假设三个单词没有关系,由于词汇表容量是3,就可以用一个三维的向量来表示。
Vector['who'] = [1, 0, 0]
Vector['is'] = [0, 1, 0]
Vector['LogicBit'] = [0, 0, 1]

为什么要用这种方式? 因为这种表示方法在数学上是正交的,模型在计算相关度的时候一般用cosincosincosin的方式来做,这样子各个单词相关度都为0.

  1. Embedding

前面假设各个单词是没有关系,现实里面却是有关系的,所以我们还是需要学习这个关系。

Embedding=W∗VtokenEmbedding = W*V_{token}Embedding=W∗Vtoken​

VtokenV_{token}Vtoken​即为上面的tokenID转化后的向量。W为需要学习的参数矩阵,[DoutDim,DvocSize][D_{outDim},D_{vocSize}][DoutDim​,DvocSize​],DoutDimD_{outDim}DoutDim​是由Transformer定义的向量维度,像LLaMA就是768维,DvocSizeD_{vocSize}DvocSize​就是词汇表的大小。

Transformer

由于我们主要是讲LLM的顶层原理,所以Transformer的原理不是我们的重点,我们这里主要讲一下Transformer给我们提供的能力。(感兴趣的可以自己可以看下李宏毅老师的视频,讲得非常清楚)

transformer

我们这里只画了Decoder,是因为现在大部分生成式的模型都是用的Decoder。
输入输出:都是一排向量。

Output Translation

由于transformer的输出是每个token对应一个向量,但是我们需要的是tokenID,才能转化为自然语言。

输出转换

输出是一个tokenID,其实是一个分类问题,只不过我们这里的类别比较多,和词汇表的大小一致。如何将一个向量转换为一个类别,机器学习里面有一个通用的做法,就是把这个向量的每个维度看成是一个类别,值代表概率。

  1. 线性转换:由于Transformer的输出的向量维度一般和词汇表的大小不一致,所以需要先转化为词汇表的大小维度,这个有点像是前面embedding的反向操作。经过转换后得到维度为词汇表大小的向量。

output=w∗zoutput = w*zoutput=w∗z

其中w的维度为(Dimvoc,DimT)(Dim_{voc},Dim_{T})(Dimvoc​,DimT​),z为transformer的输出,维度为(DimT,1)(Dim_T,1)(DimT​,1).

  1. Softmax:将各个维度进行一次计算得到每个维度的概率。其实也可以不做这个操作,只是原来的数值加起来可能大于1,或者小于1,不方便后续算法的处理而已。

假设输出向量x=[x1x2…xn]假设输出向量 x= \begin{bmatrix} x_1\x_2\…\x_n \end{bmatrix}假设输出向量x=​x1​x2​…xn​​​

那么第i个类别的概率p(i)=exi∑k=1nexk那么第i个类别的概率 p(i) = \frac{e{x_i}}{\sum_{k=1}ne^{x_k}}那么第i个类别的概率p(i)=∑k=1n​exk​exi​​

  1. 选择:选择概率最高的作为输出的值即可。(注意一下,实际上大语言模型在生成答案的时候会加入随机性,并不一定选择概率最高的,只不过概率最高的被选中的几率更大)

预训练

给定上文,预测下文。简单来说就是预测下一个词是什么?举个例子,假设样本里面有一句话['I', 'am', 'happy'],针对这句话的任务如下:

输入I,预期输出am
输入I am,预期输出 happy
:上面只是为了方便理解,实际上并不是真的将一句话拆分成多次预测任务,而是并行计算,也就是输入I am happy, 输出 I am happy,然后算法在计算某个位置的输出的时候不会考虑后面的结果是什么,也就达到了基于上文去预测的效果。

收集大量的句子按照如上进行训练。

Finetune

给定一个输入输出对的数据集,基于这个数据集在预训练的模型上面做微调。举个例子来说明一下:

输入:who are you? 输出:I am a llm.
之前一直认为就是直接按照这个输入输出进行微调的。
其实并不是,这个看上面的预训练就可以理解了,在预训练的时候llm的输入输出是一样,所以在微调的时候输入输出应该也是一样的(不然transformer的attention计算会出问题,这个留给各位思考一下为什么? )。所以需要将上面两句话合并,也就是输入输出都是who are you? I am a llm.一般Finetune的脚本都会做这个处理。
这里可能又会产生一个疑问?如果是这样子的话,那大语言模型的输出不是会把我们的问题带上吗,但是使用像chatgpt的时候,输出并没有包括输入的问题。这个是因为在对话的时候会做特殊处理,输出的内容会将问题过滤掉。但是原始的输出是会包括输入的内容的。

python
复制代码
#使用huggingface的generate没有做处理的时候,就可以看到输出是带了输入的。
model.generate()

如何系统的去学习大模型LLM ?

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的 AI大模型资料 包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

在这里插入图片描述

AI大模型系统学习路线图

在这里插入图片描述

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。
  • 内容
    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
      - L1.4.1 知识大模型
      - L1.4.2 生产大模型
      - L1.4.3 模型工程方法论
      - L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。
  • 内容
    • L2.1 API接口
      - L2.1.1 OpenAI API接口
      - L2.1.2 Python接口接入
      - L2.1.3 BOT工具类框架
      - L2.1.4 代码示例
    • L2.2 Prompt框架
      - L2.2.1 什么是Prompt
      - L2.2.2 Prompt框架应用现状
      - L2.2.3 基于GPTAS的Prompt框架
      - L2.2.4 Prompt框架与Thought
      - L2.2.5 Prompt框架与提示词
    • L2.3 流水线工程
      - L2.3.1 流水线工程的概念
      - L2.3.2 流水线工程的优点
      - L2.3.3 流水线工程的应用
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。
  • 内容
    • L3.1 Agent模型框架
      - L3.1.1 Agent模型框架的设计理念
      - L3.1.2 Agent模型框架的核心组件
      - L3.1.3 Agent模型框架的实现细节
    • L3.2 MetaGPT
      - L3.2.1 MetaGPT的基本概念
      - L3.2.2 MetaGPT的工作原理
      - L3.2.3 MetaGPT的应用场景
    • L3.3 ChatGLM
      - L3.3.1 ChatGLM的特点
      - L3.3.2 ChatGLM的开发环境
      - L3.3.3 ChatGLM的使用示例
    • L3.4 LLAMA
      - L3.4.1 LLAMA的特点
      - L3.4.2 LLAMA的开发环境
      - L3.4.3 LLAMA的使用示例
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。
  • 内容
    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

辅助学习书籍PDF资源:

在这里插入图片描述
在这里插入图片描述

学习计划:

  • 阶段1:1-2个月,建立AI大模型的基础知识体系。
  • 阶段2:2-3个月,专注于API应用开发能力的提升。
  • 阶段3:3-4个月,深入实践AI大模型的应用架构和私有化部署。
  • 阶段4:4-5个月,专注于高级模型的应用和部署。
    请根据您的个人进度和时间安排,适当调整学习计划。记得在学习过程中,理论与实践相结合,不断进行项目实践和反思,以加深理解和技能的掌握。

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

😝有需要的小伙伴,可以Vx扫描下方二维码免费领取🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值