您现在的位置是:网站首页> AI人工智能
AI人工智能的基础知识
- AI人工智能
- 2026-04-01
- 1875人已阅读
AI人工智能的基础知识
大模型根本没有 “第一个输出 token” 这种东西。它永远是:给一段上文 → 预测下一个。
*本地模型部署工具部署模型,用Agent框架调用部署工具接口实现调用模型*
*LangChain Agent框架支持Python与.NET*

客户端将MCP工具列表和用户问题-》大语言模型-》需要调用MCP的信息返回给调用模型的客户端,客户端调用指定MCP->客户端获得MCP结果-》大语言模型-》返回给最终客户
LangChain.NET如何调用Ollama制作知识库和调用MCP服务
AI模型的格式有哪些文件后缀分别是啥及各种格式模型的使用方法
人工智能与机器人|常用的数据集格式人工智能与机器人|常用的数据集格式
实际用Python调用OpenAI开发聊天程序,每次给OpenAI多少轮的对话最合理
AI基本流程与原理
自回归大语言模型:
自己训练一个专业领域词表(代码 / 医疗 / 法律),如何优化词表让 token 更少
大模型Embedding 层(把数字变向量),具体啥意思用途
Embedding 为什么能表示语义、为什么近义词会靠近、为什么能做加减法
那么大模型第一个输出token如何确定的后续才有下个字的概率啊
图片模型:
分词器-》词表
分词器(Tokenization):基于预训练的词表 + 贪心 / 动态规划算法,把任意文本切分成模型能识别的最小语义单元(Token)
词表:所有模型训练前都会先构建固定大小的词表(比如 GPT-3 是 50257 个、BERT 中文是 21128 个),词表是模型 “认识的所有字 / 词 / 片段”,所有算法的目标一致:在词表范围内,把文本切分成「语义完整 + 数量最少」的 Token 序列
词表(Vocab/Vocabulary)就是模型 “认识的所有字 / 词 / 片段的字典”,是一个固定的、预定义的字符串 - 数字映射表,也是分词和模型理解文本的核心基础。
简单说:词表是模型的 “识字库”,里面没有的内容,模型会拆成最小单位再识别,且全程只认词表对应的数字索引。
词表唯一性:不同模型有专属词表,同一文本在 GPT/Kimi/DeepSeek 上的切分结果 / Token 数均不同
模型判断分词片段有意义 / 无意义,核心不是靠 “理解语义”,而是基于预训练词表的「统计有效性」+ 算法的「最长匹配规则」,本质是工程层面的预设规则,而非真正的语义理解,简单说:词表中存在的片段 = 有意义,词表外的 = 无意义(会被拆成最小单位)。
极简总结
跨模型:词表完全不兼容,索引不可复用,必须单独分词;
同系列:词表向下兼容,索引可复用,分词结果通用。
Q:Tokenization可以使用不同的词表吗?
A:...
完全可以,而且在实际开发里经常这么干。
但有一个铁律:
Tokenizer 用什么词表,模型就必须用对应词表训练出来的权重,否则直接乱码。
Tokenizer 只是一个编码 / 解码工具,它不关心模型长什么样。
你完全可以:
1.给同一个句子,用 GPT 词表 分词
2.再用 BERT 词表 分词
3.再用 你自己造的词表 分词
只要你加载对应的 vocab 文件,就能切出完全不同的 token。
Tokenizer ≠ 模型
Tokenizer 只是个 “字符串→数字” 的转换器。
模型只能认自己训练时用的那套词表
不同词表代码:
pip install transformers
from transformers import AutoTokenizer
# 待分词文本
text = "大模型的上下文是靠拼接历史实现的"
# 1. GPT2 词表(英文为主,对中文不友好)
tokenizer_gpt2 = AutoTokenizer.from_pretrained("gpt2")
tokens_gpt2 = tokenizer_gpt2.tokenize(text)
print("=== GPT2 词表 ===")
print(f"Token 数量: {len(tokens_gpt2)}")
print(tokens_gpt2)
print()
# 2. 中文 BERT 词表(字级别为主)
tokenizer_bert = AutoTokenizer.from_pretrained("bert-base-chinese")
tokens_bert = tokenizer_bert.tokenize(text)
print("=== BERT 中文词表 ===")
print(f"Token 数量: {len(tokens_bert)}")
print(tokens_bert)
print()
# 3. Qwen 词表(阿里,对中文优化很好)
tokenizer_qwen = AutoTokenizer.from_pretrained("Qwen/Qwen2-1.5B")
tokens_qwen = tokenizer_qwen.tokenize(text)
print("=== Qwen 词表 ===")
print(f"Token 数量: {len(tokens_qwen)}")
print(tokens_qwen)
Q:词表如何生成
A:...
一句话总结
词表 = 从海量文本里,统计高频组合 → 合并成最短、最语义化的片段集合。
最主流算法叫 BPE(Byte Pair Encoding)字节对编码。
一、BPE 词表生成的 4 步(超级简单)
假设你有一堆文本:
大模型 大模型 模型 上下文 上下文
步骤 1:拆成最小单位
中文拆成单字,英文拆成字母
plaintext
大,模,型,大,模,型,模,型,上,下,文,上,下,文
步骤 2:统计相邻两个组合的频率
plaintext
大+模:2次
模+型:3次
上+下:2次
下+文:2次
步骤 3:把频率最高的合并成新词
最高频是 模 + 型 → 合并成 模型
词表新增:模型
文本变成:
plaintext
大,模型,大,模型,模型,上,下,文,上,下,文
步骤 4:重复合并,直到词表够大
再统计:
plaintext
大+模型:2次
上+下:2次
下+文:2次
合并 大 + 模型 → 大模型
合并 下 + 文 → 下文
合并 上 + 下文 → 上下文
最终词表就有:
plaintext
大,模,型,模型,大模型,上,下,文,下文,上下文
最终效果
“大模型的上下文”
不再切成:大 模 型 的 上 下 文
而是切成:大模型 的 上下文
→ 更少 token、更快、更省成本
二、真实模型词表怎么来?
1.用 TB 级文本(网页、书籍、代码)
2.跑 BPE 算法
3.生成固定大小词表(5 万~13 万不等)
4.绑定模型一起训练
这就是为什么:
不同模型词表不一样 → 分词不一样 → token 数不一样
一段 10 行代码:自己生成词表
# 极简 BPE 词表生成(手动实现)
import collections
def build_vocab(text, merges=5):
# 1. 拆成单字
tokens = list(text.replace(" ", ""))
print("原始拆分:", tokens)
for i in range(merges):
# 2. 统计相邻频率
pairs = collections.Counter(zip(tokens, tokens[1:]))
if not pairs: break
# 3. 找最高频对
best_pair = max(pairs, key=pairs.get)
new_token = ''.join(best_pair)
print(f"合并 #{i+1}: {best_pair} → {new_token}")
# 4. 替换合并
new_tokens = []
skip = False
for j in range(len(tokens)):
if skip:
skip = False
continue
if j < len(tokens)-1 and (tokens[j], tokens[j+1]) == best_pair:
new_tokens.append(new_token)
skip = True
else:
new_tokens.append(tokens[j])
tokens = new_tokens
return tokens
# 测试
text = "大模型大模型模型上下文上下文"
vocab = build_vocab(text, merges=5)
print("\n最终词表片段:", vocab)
运行后你会亲眼看到:
单字 → 合并 → 变成有意义的词
这就是所有大模型词表的生成原理
终极结论(程序员版)
1.词表不是人工写的
2.是 BPE 算法自动统计 + 合并出来的
3.高频 = 保留成整词
4.低频 = 拆成最小单位
5.每个模型词表独立 → 不兼容
词表文件的后缀
现代开源大模型:vocab.json + merges.txt
老派 BERT:vocab.txt
多语言一体:.spm / sentencepiece.model
如果你手上有 .json / .txt / .spm 结尾的小文件,基本就是词表
Q:自己训练一个专业领域词表(代码 / 医疗 / 法律),如何优化词表让 token 更少
A:...
一、专业领域词表(代码 / 医疗 / 法律)怎么训练?
核心思路
1.收集领域专属文本(代码文件 / 医疗文献 / 法律条文)
2.用 BPE / SentencePiece 训练专属词表
3.把新词表合并到原有模型词表(不破坏原模型)
4.微调模型 Embedding 层(让模型认识新词)
最推荐工具(简单、快、工业级)
SentencePiece(谷歌,最强)
或 HuggingFace Tokenizers(最易用)
我给你直接能用的训练代码(1 分钟跑出自定义词表)
二、训练专业词表:100% 可运行代码
安装工具
bash
运行
pip install tokenizers
训练代码(代码 / 医疗 / 法律都能用)
python
运行
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace
# 1. 创建空白 BPE 分词器
tokenizer = Tokenizer(BPE())
tokenizer.pre_tokenizer = Whitespace()
# 2. 训练配置(决定你的专业词表)
trainer = BpeTrainer(
vocab_size=30000, # 词表大小
min_frequency=5, # 至少出现5次才合并
special_tokens=["<pad>", "<s>", "</s>", "<unk>"]
)
# 3. 训练(把你的专业语料丢进去)
# 支持:代码文件、医疗txt、法律文本、一行一个文件
files = [
"your_code_corpus.txt",
"your_medical_corpus.txt",
"your_law_corpus.txt"
]
tokenizer.train(files=files, trainer=trainer)
# 4. 保存专业词表
tokenizer.save("domain_tokenizer.json")
跑完你会得到:
domain_tokenizer.json
这就是你的专业领域词表。
三、训练出来的词表好在哪里?
以代码领域为例:
普通词表会切成:
plaintext
def get_user_info → 6 个 token
你的专业词表会直接变成:
plaintext
def get_user_info → 2 个 token
医疗 / 法律同理:专业长词变成 1 个 token
→ Token 数量直接减少 30%~60%
→ 上下文更长、成本更低、速度更快
四、如何优化词表让 Token 更少?(核心技巧)
1. 用领域专属语料训练(最有效)
通用词表不认识专业术语
领域词表认识 → 合并成大 token → 数量暴减
2. 提高 min_frequency
python
运行
min_frequency=10
只保留高频词,减少碎片分词
3. 适当增大词表大小
python
运行
vocab_size=50000 ~ 65000
能装更多长语义单元 → 更少拆分
4. 优先合并长语义串
代码:函数名、类名、关键字
医疗:病名、药名、术语
法律:法条、条款、固定表述
5. 去掉无用空格 / 符号
减少无意义 token
6. 与原模型词表合并(不破坏模型)
把专业词表合并进原有模型
→ 原有能力不变 + 领域更强 + token 更少
五、最终效果(真实对比)
普通词表(GPT 通用)
plaintext
“患者因急性心肌梗死入院,行PCI治疗”
→ 18 token
你的医疗专业词表
plaintext
“患者因急性心肌梗死入院,行PCI治疗”
→ 9 token
直接少一半!
代码领域更夸张,能少 60% Token。
Q:如何合并词表
A:...
合并词表(最实用、程序员版)
我直接给你最简单、最安全、工业级可用的词表合并方法,专门用于:
把你的专业词表(代码 / 医疗 / 法律)合并到原有模型词表
全程不破坏原模型、不冲突、可直接用。
核心原则(必须记住)
1.保留原模型词表不动(保证模型正常运行)
2.把新词表中 “原有词表没有的词” 追加到后面
3.新 token ID 必须从原词表最大 ID +1 开始
4.最后 resize 模型 embedding 层
一、最简单可运行代码:合并两个词表
python
运行
import json
# ----------------------
# 1. 加载两个词表
# ----------------------
# 原模型词表(例如 Qwen / LLaMA / DeepSeek)
with open("original_vocab.json", "r", encoding="utf-8") as f:
original_vocab = json.load(f)
# 你的专业领域词表(代码/医疗/法律)
with open("domain_vocab.json", "r", encoding="utf-8") as f:
domain_vocab = json.load(f)
# ----------------------
# 2. 开始合并(只加新词)
# ----------------------
merged_vocab = original_vocab.copy()
next_id = len(original_vocab) # 新ID从这里开始
# 只追加原词表里没有的token
for token, _ in domain_vocab.items():
if token not in merged_vocab:
merged_vocab[token] = next_id
next_id += 1
# ----------------------
# 3. 保存合并后的新词表
# ----------------------
with open("merged_vocab.json", "w", encoding="utf-8") as f:
json.dump(merged_vocab, f, ensure_ascii=False, indent=2)
print(f"原词表大小: {len(original_vocab)}")
print(f"领域词表大小: {len(domain_vocab)}")
print(f"合并后总大小: {len(merged_vocab)}")
print(f"新增专业词汇: {len(merged_vocab) - len(original_vocab)}")
运行后你会得到:merged_vocab.json
这就是原模型 + 专业领域的超级词表。
二、如果是 BPE 模型(含 merges.txt)怎么合并?
大部分现代模型(GPT、LLaMA、Qwen、DeepSeek)都是:
1.vocab.json = 词表
2.merges.txt = 合并规则
完整合并代码(支持 BPE)
python
运行
from tokenizers import Tokenizer
# 加载原分词器
base_tokenizer = Tokenizer.from_pretrained("Qwen/Qwen2-1.5B")
# 加载你的专业分词器
domain_tokenizer = Tokenizer.from_file("domain_tokenizer.json")
# 合并(自动去重、保留原有)
base_tokenizer.add_tokens(
[token for token in domain_tokenizer.get_vocab() if not base_tokenizer.token_to_id(token)]
)
# 保存合并后的完整分词器
base_tokenizer.save("merged_tokenizer.json")
print("合并完成!文件:merged_tokenizer.json")
这是最推荐、最安全的方法。
三、合并完必须做的最后一步(非常重要)
词表变大了,模型的 embedding 层必须同步扩大,否则报错。
python
运行
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("你的模型路径")
tokenizer = AutoTokenizer.from_pretrained("你的分词器路径")
# 自动 resize 模型权重
model.resize_token_embeddings(len(tokenizer))
# 保存
model.save_pretrained("merged_model")
tokenizer.save_pretrained("merged_model")
✅ 完成!
现在模型既能正常对话,又能识别专业词汇,token 大幅减少。
四、合并词表的好处(直观效果)
原通用词表:
plaintext
def getUserInfo → 5 个 token
急性心肌梗死 → 6 个 token
中华人民共和国刑法 → 7 个 token
合并专业词表后:
plaintext
def getUserInfo → 1~2 个 token
急性心肌梗死 → 1~2 个 token
中华人民共和国刑法 → 1~2 个 token
Token 数量减少 30%~70%
上下文更长、速度更快、成本更低。
五、你要我帮你直接生成?
你告诉我:
你用的模型(LLaMA / Qwen / DeepSeek / 其他)
领域(代码 / 医疗 / 法律)
有没有自己的语料
我可以直接给你:
一键训练专业词表 + 一键合并到模型 + 一键可运行
Q:分词后大模型如何使用
A:...
分词 → Token ID → 大模型到底怎么用?
全程不绕弯、不搞玄学,一步一步讲透。
0. 一句话终极总结
分词 = 把文字 → 数字(Token ID)
大模型只吃数字,不吃文字。
输出 → 再把数字转回文字。
1. 分词后,模型拿到的是什么?
假设你输入:
我是程序员
分词器会输出两样东西:
1.1Tokens(片段):我, 是, 程序员
1.2IDs(数字):123, 45, 9876
模型只看 IDs,完全不看文字!
2. 模型第一步:Embedding 层(把数字变向量)
模型里有一个超大查询表,叫 Embedding 层。
它的作用:
每个 ID → 变成一组高维向量(比如 4096 维数字)
例子:
plaintext
123 → [0.32, 0.56, -0.12, 0.89, ...]
45 → [0.11, 0.93, 0.42, -0.21, ...]
9876 → [0.76, -0.34, 0.51, 0.23, ...]
这一步叫:
把离散 ID → 连续语义向量
3. 模型真正干活:Transformer 推理
模型拿到一串向量后,开始做核心操作:
核心做 3 件事:
3.1注意力机制:看每个词和其他词的关系
3.2前馈网络:理解语义
3.3归一化 / 残差:稳定输出
最终得到一组新的输出向量。
4. 最后一步:LM Head → 预测下一个词
模型最后一层是 LM Head(语言模型头)
它做一件事:
把输出向量 → 映射回词表 → 算出下一个词的概率
比如:
输入:我是程序员
模型预测:
plaintext
我 → 是
是 → 程
程 → 序
序 → 员
员 → ,(概率最高)
模型一次只输出一个 token!
然后把输出的 token 拼回输入,继续生成下一个。
这就是自回归生成。
5. 完整流程(程序员一眼看懂)
plaintext
用户输入:我是程序员
↓ 分词
Tokens:我、是、程序员
↓ 转ID
IDs:[123, 45, 9876]
↓ Embedding 查表
向量序列:[...], [...], [...]
↓ Transformer 推理
输出向量
↓ LM Head 预测概率
下一个 token ID:82(,)
↓ 循环生成
直到输出 <|endoftext|>
↓ 解码回文字
最终输出:我是程序员,...
6. 最关键的 3 个知识点(必须懂)
① 模型没有记忆!
每一次对话都是全新输入
上下文 = 把历史全部转成 IDs 再塞进去
② 词表 = 模型的字典
ID 必须在词表里,否则变成 <unk>(未知)
③ 生成是概率性的
模型不是 “知道答案”
而是计算下一个 token 概率最高的是什么
7. 超简 Python 代码演示(真实流程)
python
运行
from transformers import AutoTokenizer, AutoModelForCausalLM
# 加载模型 & 分词器
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-1.5B")
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-1.5B")
# 输入文本
text = "我是程序员"
# ========== 1. 分词(文字→ID)==========
inputs = tokenizer(text, return_tensors="pt")
print("Token IDs:", inputs["input_ids"])
# ========== 2. 模型推理(只吃ID)==========
outputs = model.generate(**inputs, max_length=20)
# ========== 3. 解码(ID→文字)==========
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
print("最终输出:", result)
运行结果:
plaintext
Token IDs:tensor([[103, 456, 9876]])
最终输出:我是程序员,喜欢写代码。
8. 最终极简总结
分词 = 文字转数字
模型 = 只处理数字
生成 = 预测下一个数字
解码 = 数字转回文字
#####
Q:把输出向量 → 映射回词表 → 算出下一个词的概率详细介绍
A:...
纯程序员视角、不带玄学、一步一步公式 + 流程,把输出向量 → 映射回词表 → 算出下一个词概率
这一步彻底讲透。
这一层在大模型里统一叫:
LM Head / Language Model Head / 语言模型头
0. 前置结论(先放这,防止迷路)
0.1模型最后输出的不是文字,是高维向量(比如 4096 维)
0.2LM Head 是一个线性层:[hidden_dim → vocab_size]
0.3做完线性变换,得到词表长度的 logits 向量
0.4再做 softmax,把 logits 变成 0~1 之间的概率
0.5概率最大的 token ID → 就是模型要输出的下一个词
1. 模型最后给你的是什么?
假设模型:
隐藏层维度 hidden_size = 4096
词表大小 vocab_size = 50257(GPT 类似)
经过整个 Transformer 最后一步,你会拿到一个向量:
plaintext
hidden_out = [4096] # 对应最后一个位置的输出
它不对应任何词,只是一段语义特征。
2. LM Head:线性层投影(核心步骤)
LM Head 就是一个可训练的权重矩阵:
plaintext
W = [4096, 50257]
b = [50257]
计算:
plaintext
logits = hidden_out @ W + b
结果:
plaintext
logits.shape = [50257]
这 50257 个数字,每一位对应词表里一个 token!
第 0 位 → <|endoftext|>
第 100 位 → 我
第 9876 位 → 程序员
...
第 50256 位 → 某个生僻符号
这一步叫:
把语义特征 → 投射到词表空间
3. logits 是什么?(不是概率!)
logits 有几个特点:
可正可负
可大可小
越大 → 这个词越 “可能”
但不是概率,因为总和≠1
比如:
plaintext
logits[100] = 2.34 → 我
logits[9876] = 5.67 → 程序员
logits[200] = -1.23 → 学
只看大小能排序,但不能当概率用。
4. Softmax:把 logits → 真正概率
公式(对整个词表做):
plaintext
prob_i = exp(logits_i) / Σ(exp(logits_j)) # j 遍历整个词表
效果:
所有值被压到 0 ~ 1
全部加起来 = 1
越大的 logits → 越大的概率
例子(简化):
plaintext
prob[100] = 0.0342 → 我
prob[9876] = 0.9645 → 程序员 👈 最大
prob[200] = 0.0009 → 学
这就是模型 “认为” 下一个词的真实概率。
5. 如何选出最终输出的 token?
三种常用策略:
① Greedy Search(贪心,默认)
直接选 概率最大 的 token
plaintext
next_id = argmax(probs)
快、确定性高,但容易重复、呆板。
② Top-K Sampling
从概率最高的 K 个里随机抽一个更自然、有创造力。
③ Top-p (Nucleus) Sampling
选累计概率 ≥ p 的最小集合,再随机抽最常用,最自然。
6. 完整数据流(程序员版)
plaintext
输入文本 → Token IDs → Embedding → Transformer 层层计算
↓
最后一层输出 hidden: [batch, seq_len, hidden_size]
↓
取最后一个位置的向量: [hidden_size]
↓
LM Head 线性层: hidden @ W + b → [vocab_size] → logits
↓
Softmax → [vocab_size] → 概率分布
↓
采样/argmax → next_token_id
↓
把 id 塞回输入,继续生成下一个
7. 超精简代码演示(真实逻辑)
python
运行
import torch
import torch.nn.functional as F
# 假设这是模型最后输出的 hidden 向量
hidden_out = torch.randn(4096) # 4096 维
# LM Head 权重
vocab_size = 50257
W = torch.randn(4096, vocab_size)
b = torch.randn(vocab_size)
# 1. 投影到词表空间
logits = hidden_out @ W + b
# 2. 转概率
probs = F.softmax(logits, dim=-1)
# 3. 选概率最大的 token
next_token_id = torch.argmax(probs).item()
print("下一个 Token ID:", next_token_id)
这就是大模型每生成一个字都在干的事。
8. 关键点总结(非常重要)
8.1LM Head 就是一个线性层,没有魔法
8.2logits = 原始分数,不是概率
8.3softmax 之后才是概率
8.4词表越大,这一步越耗计算
8.5专业词表之所以好:
专业词一次到位
logits 更容易集中在正确词上
生成更快、更准
#####
Q:大模型Embedding 层(把数字变向量),具体啥意思用途
A:...
最直白、程序员能秒懂的方式,一次性把 Embedding 层到底是什么、干什么、为什么必须存在 讲透。
一句话核心
Token ID 只是编号,没有语义;
Embedding 就是一张 “查询表”,把每个编号,变成一段有语义含义的高维向量。
模型只看得懂向量,看不懂编号。
1. 先看问题:模型为什么不能直接用 ID?
你分词后得到的是:我 → 100是 → 101程 → 102序 → 103员 → 104
这些 100、101、102… 只是数字编号,和语义毫无关系:
1.1 数字大小不代表含义强弱
1.2 100 和 101 相邻,但 “我” 和 “是” 语义不一定近
1.3 模型无法通过纯数字理解 “程序员” 是一个职业
纯数字 = 无意义 = 模型无法学习
所以必须加一层:Embedding
2. Embedding 本质是什么?
就是一个 巨大的查询表(矩阵)
结构:
plaintext
shape = [词表大小, 向量维度]
比如 GPT 类模型:
词表大小:50257
向量维度:4096
那么 Embedding 层就是一张表:
plaintext
ID=0 → [0.12, -0.34, 0.56, ..., 0.89] (4096个数字)
ID=1 → [0.33, 0.55, -0.22, ..., 0.11]
ID=2 → [...]
...
ID=100 → 对应“我”的向量
ID=101 → 对应“是”的向量
...
ID=50256 → [...]
输入一个 ID,直接查表取出一行向量。
这就叫:token ID → word embedding(词向量)
3. 这个向量里到底存了什么?
不是人工写的,是模型训练出来的。
向量里的每一组数字,会自动编码:
3.1.1语义(近义词向量距离近)
3.1.2词性(名词、动词、副词)
3.1.3情感(正面 / 负面)
3.1.4语法关系(主谓宾)
3.1.5上下文关联
比如训练好后:
3.2.1 程序员 向量 ≈ 工程师 向量(距离近)
3.2.2快乐 向量 ≈ 开心 向量
3.2.3悲伤 向量远离它们
3.2.4 模型就是通过这些向量,理解语言的。
4. 用途:它解决了 3 个核心问题
① 把无意义编号 → 有意义语义
ID 只是索引,向量才是知识。
② 把离散符号 → 连续空间
让模型可以做加减乘除、计算相似度、注意力权重。
③ 统一输入格式
不管是字、词、标点、代码符号,全部变成 固定长度的向量 输入 Transformer。
5. 模型真正的输入长这样
你以为模型输入是:
plaintext
[100, 101, 9876]
实际模型吃的是:
plaintext
[
[0.12, -0.34, ...], # 我
[0.55, 0.21, ...], # 是
[0.89, -0.11, ...] # 程序员
]
Transformer 所有计算:注意力、前馈、残差…
全部都是在对这些向量做运算。
6. 超简单代码演示(一看就懂)
python
运行
import torch
# 词表大小 10000,向量维度 16
embedding = torch.nn.Embedding(num_embeddings=10000, embedding_dim=16)
# 输入 Token ID
token_ids = torch.tensor([100, 101, 9876])
# 查表 → 变成向量
vectors = embedding(token_ids)
print(vectors.shape) # torch.Size([3, 16])
print(vectors)
输出:
plaintext
tensor([[ 0.23, -0.45, 0.11, ... ],
[ 0.56, 0.12, -0.39, ... ],
[-0.78, 0.32, 0.51, ... ]])
这就是模型真正的 “输入文字”。
7. 为什么专业词表 + 合并 Embedding 会更强?
因为:
7.1通用词表把急性心肌梗死切成很多小向量,语义散掉
7.2专业词表把它变成一个向量,语义更集中
7.3模型更容易理解、计算更快、token 更少
Embedding 就是模型的 “语义基因”。
8. 终极极简总结
8.1Token ID = 书名号
8.2Embedding = 书里的内容
8.3模型只看内容,不看书名号
Embedding 层 = 把编号翻译成模型能懂的语言。
如果你想,我可以下一步讲:为什么 Embedding 训练完后,近义词会靠在一起、为什么能做语义加减法(国王 - 男人 + 女人 = 女王)
Q:Embedding 为什么能表示语义、为什么近义词会靠近、为什么能做加减法
A:...
把 Embedding 为什么能表示语义、为什么近义词会靠近、为什么能做加减法 一次性讲透,还是程序员视角,不搞玄学。
一句话前置结论
Embedding 的本质,是把词语 “塞进” 一个高维坐标系里。
意思越像,坐标离得越近。
模型训练的过程,就是在不断调整每个词的坐标。
1. 先理解:Embedding 是一个「高维空间坐标」
你可以把 embedding 向量理解成:
1.1.1 二维空间:(x, y)
1.1.2 三维空间:(x, y, z)
1.1.3 大模型里:4096 维超级空间
每个 token 对应空间里一个点。
训练完之后会出现一个神奇现象:
语义相似的词,空间距离非常近
比如:
1.2.1 苹果、梨、香蕉 → 挤在一起
1.2.2 程序员、工程师、开发者 → 挤在一起
1.2.3 开心、快乐、高兴 → 挤在一起
1.2.4 悲伤、难过、痛苦 → 挤在一起
模型根本不需要 “理解中文”,
它只需要知道:
这两个点离得近 → 意思差不多
2. 为什么近义词会自动靠近?(核心原理)
来自训练目标:
通过上下文,预测下一个词
举个超级简单的例子:
句子 1:我今天吃了一个苹果。
句子 2:我今天吃了一个梨。
句子 3:我今天吃了一个香蕉。
在训练时:
2.1.1“苹果”“梨”“香蕉” 前面的上下文几乎一样
2.1.2 模型为了能正确预测下一个词
2.1.3 会把它们的向量调成非常相似
2.1.4 这样不管输入哪个,模型都能输出相似的后续概率
这就叫:
相似上下文 → 相似向量 → 语义相近
完全是数据统计 + 梯度下降逼出来的,不是人工设计的。
3. 为什么能做语义加减法?
国王 - 男人 + 女人 = 女王这个经典例子到底为什么成立?
原理一句话:向量里的每一维,都在编码某种 “语义特征”
比如某几个维度专门编码:
维度 1:是否皇室
维度 2:性别
维度 3:年龄
维度 4:职业
...
那么:
国王 = 皇室 (强) + 男人 (强) + ...
男人 = 男人 (强)
女人 = 女人 (强)
计算:国王 - 男人 + 女人
= 皇室 + 男人 - 男人 + 女人
= 皇室 + 女人
= 女王
模型根本不懂 “皇室”“性别”,
但它通过海量文本,自动把这些抽象概念编码到不同维度上了。
4. Transformer 到底用 Embedding 干什么?
你要记住一个核心:
Transformer 里所有操作,只认向量,不认字。
它主要干 3 件事:
① 计算注意力(谁和谁相关)
Attention 本质是:计算两个向量的相似度
比如句子:“程序员喜欢写代码”
模型通过向量相似度发现:
喜欢 ↔ 程序员(很近)
喜欢 ↔ 代码(很近)
程序员 ↔ 代码(很近)
于是知道:
程序员喜欢代码
② 做语义组合
把多个词向量,融合成整句语义。
比如:
向量 (大) + 向量 (模型)
→ 融合成向量 (大模型)
③ 传递信息到下一层
每一层 Transformer 都会微调向量,
让语义越来越清晰、完整。
最后输出的向量,
就是整段话的语义浓缩。
5. 为什么专业词表能让 Embedding 更强?
这里非常关键,直接关系到你之前关心的:
代码 / 医疗 / 法律词表优化
普通通用词表:
“急性心肌梗死”
→ 切成 5~6 个 token
→ 5~6 个零散向量
→ 语义被拆碎,模型要自己拼
专业领域词表:
“急性心肌梗死”
→ 1 个 token
→ 1 个完整、紧凑、精准的向量
→ 语义高度集中
→ 注意力计算更快更准
→ 生成时 logits 更集中,不容易胡说
一个完整语义向量 > N 个碎向量拼起来
6. 极简代码:直观看向量相似度
我给你一段能直接跑的代码,
让你亲眼看到:
近义词向量余弦相似度极高,无关词很低
python
运行
import torch
import torch.nn.functional as F
# 随便模拟几个训练好的 Embedding(真实模型也是这种数值分布)
emb = torch.nn.Embedding(10, 8)
# 定义几个ID
id_apple = torch.tensor([0])
id_pear = torch.tensor([1])
id_cat = torch.tensor([2])
# 取出向量
v_apple = emb(id_apple)
v_pear = emb(id_pear)
v_cat = emb(id_cat)
# 计算相似度(越接近1越像)
sim_app_pear = F.cosine_similarity(v_apple, v_pear)
sim_app_cat = F.cosine_similarity(v_apple, v_cat)
print("苹果 ↔ 梨:", sim_app_pear.item())
print("苹果 ↔ 猫:", sim_app_cat.item())
正常训练好的模型输出会接近:
plaintext
苹果 ↔ 梨: 0.85
苹果 ↔ 猫: 0.12
这就是语义空间。
7. 终极总结(程序员版)
7.1 Embedding = 词在高维空间的坐标
7.2 坐标近 = 意思像
7.3 模型靠向量相似度理解上下文关系
7.4 训练就是在调整每个词的坐标
7.5 专业词表 = 让专业术语拥有独立、完整、精准的坐标
7.6 Transformer 所有魔法,都建立在这些向量之上
####
Q:embedding后输出的向量表又如何使用呢?
A:...
这一步就是大模型真正 “思考” 的起点。
我用最干净、程序员能直接对应代码的方式讲:
Embedding 输出的向量序列,接下来只做三件事:进 Transformer → 算注意力 → 输出特征向量
全程没有玄学,全是矩阵运算。
0. 先明确:embedding 输出是什么?
输入一句话 → 分词成 token ID → embedding 查表
得到的是一个序列向量:
plaintext
shape = [批次, 序列长度, 隐藏维度]
例如:[1, 10, 4096]
意思:
1 句话
10 个 token
每个 token 变成 4096 维向量
这就是模型真正的输入。
后面所有操作,都在这堆向量上折腾。
1. 第一步:加上位置信息(Position Embedding)
词向量本身没有顺序。
我吃饭 和 饭吃我 的向量是一样的。
所以必须加:
位置编码 Position Embedding
plaintext
最终输入 = 词向量 + 位置向量
让模型知道:
第 1 个词是啥
第 2 个词是啥
谁在前谁在后
这一步做完,才正式进入 Transformer。
2. 核心:进 Transformer 层(真正干活)
Transformer 只做一件事:
对这一串向量做 “信息融合”,让每个词都吸收上下文其他词的信息。
内部流程超级清晰:
① 多头注意力 Multi-Head Attention
对每一对向量计算相关性(注意力分数)
比如句子:程序员[0] 喜欢[1] 写[2] 代码[3]
注意力会算出:
2.1.1程序员 ↔ 喜欢:强相关
2.1.2喜欢 ↔ 代码:强相关
2.1.3程序员 ↔ 代码:强相关
然后:
每个词向量 = 自己 + 其他相关词的信息
结果:每个向量都变成了带上下文语义的向量。
② 前馈网络 Feed Forward
对每个向量独立做一次非线性变换:
plaintext
向量 → 线性 → 激活 → 线性 → 新向量
作用是强化语义、抽象特征。
③ 重复 N 层
GPT 通常 30~100 层。
每一层都让语义更抽象、更完整。
3. 最终输出:还是一串向量
经过几十层 Transformer 后,输出仍然是:
plaintext
shape = [批次, 序列长度, 隐藏维度]
和 embedding 输出形状完全一样!
区别是:
embedding 输出:孤立的词义
Transformer 输出:融合了整段上下文的语义
4. 然后怎么用?分两种任务
任务 A:对话 / 续写 / 生成(你最关心的)
只需要最后一个位置的向量,
因为它吸收了整段话的全部信息。
plaintext
last_hidden = hidden_states[:, -1, :] # [1, 4096]
然后送给 LM Head:
plaintext
logits = last_hidden @ W + b # → [1, 词表大小]
probs = softmax(logits)
next_token_id = argmax(probs)
这就是:
根据上文,预测下一个字
任务 B:语义检索 / 分类 / 匹配
取 第一个 token 向量 或 整段平均作为整段话的语义向量,
用来:
4.1 搜索相似文本
4.2 做 RAG 检索
4.3 分类、意图识别
5. 超直观数据流(一行看懂)
plaintext
文本
↓ 分词
token IDs [1,6,9,10]
↓ embedding 查表
向量序列 [seq_len, hidden]
↓ + position
带顺序的向量
↓ N层 transformer
融合上下文后的向量序列
↓ 取最后一个
整句语义向量 [hidden]
↓ LM Head 投影
logits [vocab_size]
↓ softmax
下一个词概率
↓ 采样
输出一个字
6. 极简代码版(真实逻辑)
python
运行
# embedding
x = embedding(token_ids) # [1, seq_len, 4096]
# + position
x = x + pos_emb
# N 层 transformer
for layer in layers:
x = layer(x) # 形状永远不变
# 取最后一个词
last = x[:, -1, :] # [1, 4096]
# 投影到词表
logits = last @ lm_head_weight
probs = softmax(logits)
next_id = argmax(probs)
7. 一句话终极总结
embedding 给出 “词义”
transformer 算出 “上下文语义”
最后一个向量代表 “整句话意思”
再投影回词表,得到下一个字的概率
#####
Q: 大模型如何控制预测结束呢
A:...
大模型怎么知道什么时候该停嘴、结束生成。
一句话总结
模型本身不会自动 “想完了”,
它是靠 特殊结束符号 + 长度上限 + 停止词 这三样东西强制结束的。
1. 最核心:结束 Token <|endoftext|> / <eos>
所有大模型词表里,一定有一个特殊 token,叫:
<|endoftext|>
或 <eos>
或 </s>
它的作用只有一个:
表示 “文本到此结束”
生成过程是这样:
1.1.1 模型每次输出一个 token
1.1.2 解码器检查是不是结束符
1.1.3 如果是 → 立刻停止,不再生成
1.1.4 如果不是 → 继续
也就是说:
模型自己会 “预测出结束符”,
这是最自然、最标准的结束方式。
2. 长度上限 max_new_tokens(强制保险)
怕模型无限说下去,所以一定会加一个强制上限:
python
运行
model.generate(..., max_new_tokens=2048)
意思:
最多只让你生成 2048 个 token,到点立刻停。
这是工程上的安全锁,防止死循环、爆显存、爆成本。
3. 停止词 stop_words(自定义停止)
你可以指定:只要模型输出了某串字符,就停。
例如:
3.1 "\n" 遇到换行就停
3.2 "答案:" 之后停
3.3 "。" 遇到句号停
3.4 "用户:" 遇到对话切换标记停
python
运行
model.generate(..., stop=["\n", "。", "谢谢"])
这在对话、结构化输出里非常常用。
4. 真实完整生成逻辑(伪代码,一看就懂)
python
运行
# 初始输入
prompt_ids = [101, 202, 303]
while True:
# 1. 预测下一个 token
next_id = model(prompt_ids)
# 2. 检查是不是结束符 <eos>
if next_id == EOS_TOKEN_ID:
break
# 3. 检查是否超过最大长度
if len(prompt_ids) >= max_length:
break
# 4. 检查是否命中停止词
next_word = id2word(next_id)
if next_word in stop_words:
break
# 5. 否则继续
prompt_ids.append(next_id)
这就是所有大模型生成的真实逻辑。
5. 模型自己 “想结束” 是怎么做到的?
不是玄学,是训练出来的。
训练语料里,每篇文章末尾都有结束符:
plaintext
文章1内容<|endoftext|>
文章2内容<|endoftext|>
...
模型学会了:
话说完了,下一个就该输出 <eos>
所以它会自然收尾,而不是被强行掐断。
6. 三种结束方式对比
表格
方式 触发 优点 缺点
结束符 EOS 模型自己输出 自然、流畅 有时不想停它也停
最大长度 达到 token 数 安全、可控 可能生硬切断
停止词 输出指定字符串 灵活、结构化 要精准匹配
7. 终极极简总结
7.1 模型不会自己 “思考完”
7.2 靠 <eos> 结束符 自然停止
7.3 靠 max_length 强制防止无限生成
7.4 靠 stop_words 做结构化截断
7.5 生成循环内部不断检查,满足任一条件就停
Q:图片模型到底怎么工作?(极简原理)
A:...
主流就两大类:
A. 扩散模型(Stable Diffusion、Flux、SDXL)
1.从完全随机噪点图开始
2.模型一点点去噪
3.每一步去掉一点噪点,图像慢慢变清晰
4.固定走 N 步(比如 20~50 步)
5.步数走完,图像就完成了
→ 没有 “预测结束”,步数到了就停
B. 自回归图像模型(像 PixelDT、早期部分模型)
把图片切成很小的 patch 或 token
像文字一样一个个生成
这种才会有 “结束逻辑”,但现在几乎不用了
那图片模型的 “文本提示” 怎么用
只有文字编码部分和语言模型有点像:
1.提示词 → 用 CLIP 文本编码器 → 变成文本特征向量
2.这个向量控制扩散模型画什么
3.模型只负责:把噪点 → 变成符合描述的图像
Q:详细介绍下图片模型的原理及实现步骤方法
A:...
程序员能完全看懂、不玄学、不堆砌名词的方式,从头到尾讲清楚:
主流图片生成模型(Stable Diffusion 类扩散模型)的完整原理 + 实现步骤。
你之前理解的语言模型那套(token、自回归、下一个词概率)全部不适用,图片是另一套体系。
一、先一句话定调
Stable Diffusion / SDXL / Flux 这类图片模型,本质是:
从一张完全随机的噪点图,一步步 “去噪”,直到变成清晰图片。不是逐像素画,不是顺序生成,没有结束符,步数跑完就出图。
二、核心思想:扩散模型(Diffusion Model)
它分两个阶段:
1. 训练阶段(模型学习怎么 “还原图片”)
人为地给清晰图片一步步加噪,直到完全变成噪点。
然后训练模型:输入带噪图片 → 预测出刚才加的那层噪声。
模型学会了:
任何噪点 → 都能推出噪声是啥 → 减去噪声就变清晰
2. 推理生成阶段(画图)
2.1 从纯随机噪点开始
2.2 模型预测噪声
2.3 从图里减去预测的噪声
2.4 重复 N 步(20~50 步)
2.5 最后一步得到清晰图片
三、完整原理(极简但完整)
1. 文本提示怎么变成图的控制信号?
你输入:一只可爱的橘猫
步骤:
1.1 文本 → CLIP 文本编码器
1.2 输出一段 77×768 或 77×1280 文本特征向量
1.3 这个向量会在 UNet 每一层里引导去噪方向
→ 模型知道:要往 “橘猫” 的方向去噪,而不是别的
2. 随机噪声(起点)
生成一张完全随机的图:
(batch, channels, height, width)
比如 (1, 4, 64, 64) 这种隐空间图(不是像素图)
3. UNet 主干(核心大脑)
每一步做:
输入:
当前带噪隐向量 z_t
步数信息 t
文本特征 text_emb
输出:
预测的噪声 ε`
然后更新隐向量:zt−1=zt−ε×系数
图片每一步都更清晰一点点。
4. VAE 解码器(最后变图片)
跑完所有去噪步后,得到的是隐空间特征图,不是像素图。
送入 VAE decoder 解码:
隐向量→RGB 图片(0∼255)
这就是你最终看到的图。
四、完整生成流程(标准步骤,1:1 对应代码)
步骤 1:准备文本提示
plaintext
prompt = "a cute cat, photorealistic"
negative_prompt = "blurry, ugly, disfigured"
步骤 2:文本编码(CLIP)
把提示变成文本特征:
plaintext
text_embeddings = clip_tokenizer.encode(prompt)
步骤 3:初始化随机隐空间噪声
plaintext
z = torch.randn(1, 4, latent_h, latent_w)
步骤 4:循环去噪(核心循环)
python运行
for t in reversed(timesteps):
# 1. UNet 预测噪声
noise_pred = unet(z, t, text_embeddings)
# 2. 用预测噪声更新隐空间
z = scheduler.step(z, noise_pred, t)
步数跑完,z 就是高质量隐图。
步骤 5:VAE 解码成像素图
python运行
image = vae.decode(z)
image = (image / 2 + 0.5).clamp(0, 1)
步骤 6:保存输出
转成 PIL / 保存为 PNG。
五、三大核心模块作用(超级清晰)
1. CLIP 文本编码器
只干一件事:
把文字 → 语义向量
让模型知道画什么。
2. UNet
整个模型的大脑
输入:噪点 + 文本 + 步数
输出:应该减掉多少噪声
3. VAE
两个作用:
3.1 训练时:把图片压缩到小隐空间(快)
3.2 生成时:把隐空间还原为高清图
六、和语言模型的本质区别(一定要记住)
表格项目大语言模型(GPT/LLaMA)图像扩散模型(SD/SDXL/Flux)生成方式自回归,逐 token 生成并行去噪,固定步数结束输出单位字 /token整张图的隐空间特征结束方式eos token / 长度限制固定步数跑完就结束概率分布词表概率无词表,预测噪声顺序性强依赖前文全局并行,无顺序Embedding词 ID→向量文本→向量,图像不走 emb
语言模型是写字;图片模型是 “修图”,从马赛克修成高清。
七、如果你想,我可以继续讲
最简化可运行 SD 代码(100 行以内)
Latent Space 到底是什么,为什么要压缩图片
Classifier-Free Guidance 怎么做(提示词强度)
LoRA 原理、训练、合并
图生图、局部重绘、ControlNet 机制
CUDA的安装
CUDA(Compute Unified Device Architecture)是由NVIDIA公司开发的一种并行计算平台和编程模型,主要应用于该公司生产的GPU(图形处理器)。它允许开发者使用支持CUDA的编程语言(如C、C++、Fortran等)来编写在GPU上运行的程序,以利用GPU强大的并行计算能力。
CUDA的主要特点和优势包括:
并行计算: CUDA允许在GPU上进行大规模并行计算,可以大幅提高某些类型任务(如科学计算、机器学习等)的运行速度。
易用性: CUDA提供了一组扩展的编程语言(如CUDA C/C++),使得开发人员可以较容易地编写和优化GPU程序。
可扩展性: CUDA程序可以在不同规模和性能的NVIDIA GPU上运行,具有良好的可扩展性。
生态系统: NVIDIA提供了丰富的CUDA工具和库(如cuBLAS、cuDNN等),加速了GPU程序的开发。
广泛应用: CUDA已被广泛应用于科学计算、机器学习、图像处理、视频编码等领域,尤其在深度学习领域发挥了重要作用。
总之,CUDA通过利用GPU的并行计算架构,为开发者提供了一种开发高性能应用程序的强大工具,极大地推动了GPU计算的发展和应用。它已成为许多领域不可或缺的加速计算平台。
CUDA实际上包含了SDK(Software Development Kit)和API(Application Programming Interface)两个部分。
CUDA SDK:CUDA SDK是一套完整的开发工具包,包括编译器、调试器、性能分析工具、数学库等。它允许开发者在支持CUDA的硬件上开发、调试和优化基于GPU的应用程序。CUDA SDK提供了一个集成的开发环境,使开发人员能够更高效地开发CUDA应用程序。
CUDA API:CUDA API是一组用于与GPU交互的编程接口。它包括一组扩展的编程语言(如CUDA C/C++)和函数库,允许开发者在GPU上分配内存、传输数据、启动内核函数等。CUDA API提供了对GPU硬件的抽象,使开发人员能够专注于并行算法的实现,而不必过多关注底层硬件细节。
因此,从开发者的角度来看,CUDA主要是一个SDK,因为它提供了一整套开发GPU应用程序所需的工具和组件。同时,从编程的角度来看,CUDA也提供了一组API,允许开发者在其应用程序中与GPU进行交互和数据传输。
总之,CUDA作为一个并行计算平台,包含了SDK和API两个紧密相关的部分,共同为GPU编程提供了强大的支持。
CUDNN(CUDA Deep Neural Network library)是NVIDIA提供的一个用于深度神经网络的GPU加速库。它是CUDA工具包的一部分,旨在提高深度学习应用程序的性能。CUDNN提供了一组经过优化的深度学习基元,如卷积、池化、归一化和激活函数等,可以显著加快深度神经网络的训练和推理速度。
CUDNN的主要特点和优势包括:
高性能: CUDNN提供了经过优化的深度学习基元实现,充分利用了GPU的并行计算能力,可以显著提高深度神经网络的运行速度。
易用性: CUDNN提供了简单易用的API接口,可以方便地集成到现有的深度学习框架中,如TensorFlow、PyTorch、Caffe等。
多种神经网络支持: CUDNN支持各种类型的深度神经网络,包括卷积神经网络(CNN)、递归神经网络(RNN)、长短期记忆网络(LSTM)等。
自动优化: CUDNN可以根据硬件配置和网络结构自动选择最优的算法和参数,简化了性能优化的过程。
持续更新: NVIDIA会持续更新CUDNN,提供新的功能和性能改进,以跟上深度学习技术的发展。
CUDNN的工作原理是将深度学习基元的实现从深度学习框架中抽离出来,并提供了经过优化的GPU实现。当深度学习框架调用这些基元时,实际上是在调用CUDNN库提供的高度优化的GPU实现,从而获得显著的性能提升。
总之,CUDNN作为一个专用于深度学习的GPU加速库,通过提供经过优化的深度学习基元实现,显著提高了深度神经网络的性能。它已成为加速深度学习应用程序的重要工具,被广泛应用于学术研究和工业界。
关于NLP里tokens的解释
在自然语言处理(NLP)领域,特别是在基于 Transformer 架构的语言模型中,"tokens"(标记)通常是指构成输入序列的基本单元。它可以是一个字、一个词、一个子词或者一个字符,具体取决于所使用的分词方法。
在传统的 NLP 任务中,"token"通常指的是单个的词。例如,句子"I love AI"包含三个 tokens:"I"、"love"和"AI"。
当我们说"模型支持 8k tokens 上下文"时,这意味着:
假设你正在读一本书,现在你读到了第100页。为了真正理解第100页的内容,仅仅读这一页可能是不够的,你可能需要回顾前面的几页,甚至是前面的几章,以便更好地理解当前页面的内容。这些你需要回顾的前面的内容,就是所谓的"上下文"。
现在,假设你有一个超强的记忆力,你可以在读第100页时,同时考虑前面99页的内容。这意味着你有100页的"上下文"来帮助你理解第100页。显然,与只记得前面10页或20页相比,记住前面99页可以让你对第100页有更深入、更全面的理解。
将这个例子与语言模型联系起来:
每一页可以看作是一个"token"(假设每页只有一个词)。
你正在读的第100页就是模型当前要处理的 token。
你的"超强记忆力"就相当于模型的上下文长度。
因此,当我们说"模型支持 8k tokens 上下文"时,这就像说你在读第8000页时,可以同时记住并考虑前面的7999页。这是一个非常大的"记忆力",可以帮助模型更好地理解和生成文本。
当然,在实际应用中,模型处理的是更细粒度的 tokens(通常是词或子词),而不是整页的内容。但无论如何,更长的上下文意味着模型可以考虑更多的信息,从而做出更准确、更连贯的预测或生成。
关于tokens的计费
在大多数提供 AI 语言模型服务的平台中,按 tokens 计费通常包括用户的输入和 AI 的输出,也就是说,两者都会被计入费用。
人工智能书推荐
TensorFlow VS PyTorch
安装和配置
TensorFlow和PyTorch的安装和配置过程都相对简单。它们都支持多个操作系统,包括Windows、Linux和macOS。TensorFlow支持Python、C++、Java和Go等编程语言,而PyTorch主要使用Python。两个框架的文档和社区资源非常丰富,可以帮助用户解决安装和配置过程中遇到的问题。
模型定义和训练
TensorFlow和PyTorch在模型定义和训练方面有一些不同。在TensorFlow中,模型的定义和计算图建立在静态图的基础上,用户需要显式地定义图中的节点和操作。这种方式的好处是可以对图进行高级优化和部署。而在PyTorch中,模型的定义和计算图是动态的,用户可以根据需要灵活地定义和修改计算图。这种动态图的方式使得PyTorch更容易进行调试和实验。
在训练过程中,TensorFlow使用会话(Session)来管理计算图和变量。用户需要明确地指定变量的初始化、损失函数、优化器等。PyTorch则使用动态图来追踪变量和操作的计算过程,用户只需简单地定义前向传播过程,然后通过调用反向传播函数即可进行梯度计算和参数更新。
灵活性和可扩展性
在灵活性和可扩展性方面,PyTorch表现更加出色。PyTorch的设计理念强调易用性和灵活性,用户可以方便地对模型进行修改和扩展。PyTorch还提供了更多的高级特性,如动态图、自动微分和自定义操作等,使得用户可以更好地控制模型的计算过程。
TensorFlow虽然在初始学习成本上可能相对高一些,但它在大规模分布式训练和部署等方面表现出更高的可扩展性。TensorFlow的静态图设计使得其能够对计算图进行高效优化和分布式运算。此外,TensorFlow还提供了一系列用于大规模训练和部署的工具和库。
社区支持
TensorFlow和PyTorch都有庞大的用户社区和丰富的文档资源,这使得学习和使用这两个框架变得更加容易。TensorFlow在推出之初就受到了很多大公司的青睐,并得到了广泛应用。PyTorch则是由Facebook AI Research开发并开源的,近年来也得到了越来越多学术界和工业界的支持。两个框架都拥有活跃的社区,用户可以在社区中寻求帮助、交流经验和分享代码。此外,两个框架都有很多开源项目和示例代码可供学习和参考。
何为AI模型
AI模型是一种计算机程序,它通过学习和分析大量的数据,尤其是输入和输出的对应关系,来模拟人类的智能行为。它可以用于各种任务,如图像识别、语音识别、自然语言处理等。
简单来说,AI模型就像是一个智能工具,它可以通过大量的训练数据学习并理解事物的规律和模式。类似于我们人类学习新知识的过程,AI模型会通过观察和分析数据来提取特征,并建立一个能够预测和推理的模型。这个模型在训练完成后就可以被用来处理新的数据,并作出类似人类的决策或回答问题。
举个例子,如果我们想让AI模型学会识别猫的图片,我们可以给它展示大量的猫的图片,并告诉它这些图片都是猫。AI模型会通过分析这些图片的特征,比如猫的耳朵、眼睛、鼻子等,来学会辨别猫的图片。然后,当我们给它一张新的图片时,AI模型可以根据之前学到的知识判断这张图片是否是猫。
总的来说,AI模型就是一个能够通过学习数据来模拟人类智能行为的程序,它可以帮助我们解决各种复杂的问题,并提供智能化的服务。
学习AI模型开发需要掌握以下基础知识
1. 编程语言:首先,你需要熟悉至少一种编程语言,比如Python或Java。这些语言在AI开发中广泛使用,因为它们具有丰富的库和工具,可以简化开发过程。
2. 数据处理和分析:了解数据处理和分析的基本概念是非常重要的。你需要学会如何清洗、转换和准备数据,以便用于训练和评估AI模型。
3. 数学和统计学:AI模型的许多算法和技术都基于数学和统计学原理。掌握线性代数、微积分、概率论和统计学等基础数学概念对于理解和实现AI模型是必要的。
4. 机器学习算法:学习机器学习算法是开发AI模型的关键。你需要了解常见的机器学习算法,如线性回归、逻辑回归、决策树、支持向量机和神经网络等。掌握这些算法的原理、应用场景和实现方式将帮助你构建和训练AI模型。
5. 深度学习:深度学习是一种特殊的机器学习方法,它使用神经网络模型来处理复杂的任务。学习深度学习需要了解神经网络的基本原理、常见的深度学习架构(如卷积神经网络、循环神经网络)以及深度学习框架(如TensorFlow、PyTorch)的使用。
6. 数据集和训练:了解如何准备和使用数据集进行模型训练是至关重要的。你需要学习如何选择、标记和划分数据集,以及如何进行训练和验证。
7. 模型评估和优化:了解如何评估和优化AI模型的性能也是必不可少的。你需要学习如何选择合适的评估指标,如准确率、精确率、召回率等,并掌握调整模型参数、处理过拟合和欠拟合等常见问题的技巧。
除了上述基础知识,还可以学习一些特定领域的知识,如计算机视觉、自然语言处理或增强学习等,以应用AI模型于具体的应用场景中。
学习AI模型开发是一个不断深入和不断学习的过程。建议从基础知识开始,逐步深入学习和实践,通过阅读书籍、参与在线课程、实践项目等方式提升自己的技能。
AI模型的训练
AI模型训练是一个迭代的过程,其目的是通过给定的输入数据(也称为训练数据)来调整模型的参数,使其能够对未知数据做出准确的预测或执行特定任务。
训练过程可以分为以下几个步骤:
1.数据收集和准备:首先,我们需要收集与目标任务相关的训练数据。这些数据可以是图像、文本、音频等形式。然后,我们对数据进行预处理和清洗,以确保数据质量和一致性。
2.模型选择和设计:根据任务的特点,我们选择适合的模型架构。不同的任务可能需要不同类型的模型,例如卷积神经网络(CNN)用于图像处理,循环神经网络(RNN)用于序列数据处理等。在选择模型后,我们设计模型的结构,包括层数、节点数量等。
3.参数初始化:模型中的参数是在训练过程中需要学习和调整的。在开始训练之前,我们需要对模型的参数进行初始化,可以使用随机初始化的方法。
4.前向传播:在训练过程中,我们将训练数据输入到模型中,通过前向传播的过程,模型根据当前的参数计算输出结果。
5.计算损失:通过比较模型的输出结果和训练数据中的真实标签,我们可以计算出模型的损失值。损失值表示模型预测的输出与真实标签之间的差异。
6.反向传播:在反向传播过程中,我们使用损失值来计算模型中每个参数对损失的贡献度,然后根据贡献度的方向调整参数的值。这个过程通过梯度下降算法来更新参数,使得模型的预测结果逐步接近真实标签。
7.参数更新:根据反向传播计算得到的梯度信息,我们更新模型中的参数值,使其朝着降低损失的方向移动。
8.重复迭代:重复进行前向传播、计算损失、反向传播和参数更新的过程,直到模型收敛或达到预设的停止条件(如训练轮数、损失阈值等)。
训练的目的是通过不断调整模型的参数,使得模型能够在未见过的数据上做出准确的预测或执行任务。通过大量的训练数据和迭代优化的过程,模型可以学习到输入数据的特征和模式,从而具备泛化能力,能够对新的数据进行准确的预测或执行任务。
设计AI模型
设计AI模型的过程可以分为以下几个关键步骤,以便程序员能够理解:
1. 确定任务:首先,明确你要解决的具体任务。这可能是图像分类、目标检测、文本生成等。确保清楚地定义任务的输入和期望输出。
2. 收集和准备数据:收集适用于任务的训练数据。这些数据应该涵盖各种情况和场景,以确保模型的泛化能力。对数据进行预处理,包括标准化、归一化、去噪等,以提高模型的训练效果。
3. 选择模型架构:根据任务的特点和数据的特征,选择适当的模型架构。常见的模型架构包括卷积神经网络(CNN)、循环神经网络(RNN)、变压器模型(Transformer)等。了解不同模型架构的原理和适用场景,选择最适合任务的模型。
4. 设计模型结构:在选择模型架构后,设计模型的具体结构。这包括确定模型的层数、每层的节点数量、激活函数的选择等。合理的模型结构应该能够有效地提取输入数据中的特征,并产生准确的输出。
5. 初始化参数:在训练模型之前,需要对模型的参数进行初始化。可以使用随机初始化的方法,为模型的权重和偏置等参数赋予初始值。
6. 定义损失函数:选择适当的损失函数来度量模型的预测结果与实际标签之间的差异。常见的损失函数包括均方误差(MSE)、交叉熵损失等。确保选择与任务和数据类型相匹配的损失函数。
7. 选择优化算法:为了训练模型并调整参数,需要选择适当的优化算法。常见的优化算法包括随机梯度下降(SGD)、Adam、RMSProp等。了解这些算法的原理和特点,选择最适合模型训练的优化算法。
8. 训练和评估模型:使用准备好的训练数据对模型进行训练。通过将输入数据传递给模型,计算模型的输出,并将其与实际标签进行比较,计算损失并更新模型参数。重复这个过程,直到模型收敛或达到预设的停止条件。在训练过程中,使用验证数据集对模型进行评估,并监控模型的性能。
9. 调优和改进:根据训练和评估的结果,根据需要对模型进行调优和改进。可以尝试调整模型的结构、超参数的选择,或者增加更多的训练数据等,以提高模型的性能和泛化能力。
10. 测试和部署:在训练完成后,使用独立的测试数据集对模型进行最终评估。确保模型在未见过的数据上表现良好。最后,将训练好的模型部署到实际应用中,用于实际的预测或任务执行。
通过以上步骤,你可以设计和训练一个AI模型,以解决特定的任务,并实现准确的预测或执行。根据不同的任务和应用领域,设计AI模型的具体细节和技术会有所不同。因此,不断学习和实践,积累经验是提高AI模型设计和训练的关键。
Transformers 和PyTorch的关系
Transformers和PyTorch是两个不同但相关的概念。
Transformers是一种模型架构,用于处理序列数据,特别是在自然语言处理(NLP)任务中表现出色。它最早由Vaswani等人于2017年提出,并在2018年的论文《Attention Is All You Need》中引入了注意力机制。Transformers模型的核心是自注意力机制,通过对输入序列中的不同位置进行注意力计算,从而捕捉全局上下文信息。
PyTorch是一个深度学习框架,提供了用于构建、训练和部署神经网络模型的工具和接口。它由Facebook的研究团队开发,并在深度学习社区中广泛应用。PyTorch提供了丰富的API和工具,使得开发者可以方便地定义神经网络结构、处理数据、进行模型训练和推理等。
在实践中,Transformers模型通常是使用PyTorch等深度学习框架进行实现和训练的。PyTorch提供了强大的张量操作和自动求导功能,使得实现和训练复杂的Transformers模型变得更加容易。此外,PyTorch还提供了许多与深度学习相关的库和工具,如PyTorch Lightning和TorchText,可以进一步简化模型开发和训练的过程。
因此,可以说Transformers是一种模型架构,而PyTorch是一个用于实现和训练Transformers模型的深度学习框架。PyTorch为开发者提供了构建和训练Transformers模型所需的工具和环境,使得使用Transformers模型变得更加便捷和高效。
AI人工智能产品缺陷检测
要使用Python进行产品缺陷检测,可以利用计算机视觉和机器学习技术。以下是一个基本的思路和步骤:
收集并准备缺陷和非缺陷的产品样本图像数据集。这些图像应包含不同类型和程度的产品缺陷,以及正常的产品图像作为对比。
使用图像处理技术,例如调整大小、灰度化、增强对比度等,对图像进行预处理,以便更好地提取特征。
提取图像特征。可以使用传统的计算机视觉方法,例如边缘检测、角点检测、纹理特征提取等,或使用深度学习模型进行特征提取。
图像的特征提取是计算机视觉中的一个重要任务,它可以帮助我们捕捉图像中的关键信息和表征。以下是一些常用的图像特征提取方式:
1.颜色特征:提取图像的颜色信息,例如直方图、颜色矩、颜色梯度等。
2.纹理特征:捕捉图像的纹理信息,例如灰度共生矩阵(GLCM)、局部二值模式(LBP)、Gabor滤波器等。
3.形状特征:描述图像中的形状和边界信息,例如边缘检测、轮廓特征、形状描述子(如Hu矩、Zernike矩)等。
4.角点特征:检测图像中的关键点和角点,例如Harris角点检测、Shi-Tomasi角点检测、FAST角点检测等。
5.尺度不变特征变换(SIFT):通过检测图像中的局部特征点,并计算其描述子,从而实现对尺度、旋转、光照变化等的不变性。
6.领域知识特征:利用特定领域的先验知识,设计和提取与特定任务相关的特征,例如医学图像中的肿瘤形态学特征。
7.深度学习特征:使用深度卷积神经网络(CNN)等深度学习模型,通过从大规模数据集中进行端到端训练,自动学习图像的高级特征表示。
以上仅列举了一些常见的图像特征提取方式,实际上还有很多其他方法和技术可供选择。特征的选择应该根据具体任务和数据集的特点来确定,有时也可以结合多种特征进行综合表示。此外,特征提取往往是图像处理和计算机视觉任务的前置步骤,后续的任务可以基于提取的特征进行分类、检测、定位等操作。
构建分类模型。使用准备好的样本数据集,训练一个分类模型,例如卷积神经网络(CNN)或支持向量机(SVM),来区分缺陷和非缺陷的产品。
在Python中,可以使用深度学习框架如TensorFlow、Keras、PyTorch等来构建和训练分类模型。这些框架提供了丰富的工具和API,以简化模型的构建、训练和评估过程。
对新的产品图像进行预测。使用训练好的模型,对新的产品图像进行预测,判断其是否存在缺陷。
根据预测结果进行处理。根据预测结果,可以自动化地处理有缺陷的产品,例如标记、分类、拒绝等。
定期评估和优化模型性能。对模型进行评估,根据反馈信息进行优化和改进,以提高缺陷检测的准确性和鲁棒性。
需要注意的是,以上步骤仅提供了一个基本的思路。实际应用中,可能需要根据具体情况进行调整和改进。例如,如果缺陷种类较多或样本不平衡,可能需要采用更复杂的模型或进行数据增强等处理。此外,还可以结合其他技术,如目标检测、图像分割等,来更精确地定位和识别产品缺陷。
综上所述,产品缺陷检测是一个复杂的任务,需要综合运用计算机视觉和机器学习技术。在实际应用中,可能需要进行多轮迭代和调优,以获得最佳的缺陷检测效果。
PyTorch深度学习快速入门教程
B站强推!2023公认最通俗易懂的【PyTorch】教程
人工智能与机器人|常用的数据集格式
AI模型的格式有哪些文件后缀分别是啥及各种格式模型的使用方法
格式选择与应用场景
研究与微调:PyTorch 的.pt/.pth或 Hugging Face 的 Safetensors,灵活性高且生态丰富。
跨平台部署:ONNX 或 GGUF,兼容多框架和硬件,适合边缘计算和云服务。
硬件优化推理:昇腾 OM、TensorRT 或 Core ML,针对特定芯片架构提升性能。
移动端与低资源设备:TFLite、GGUF(量化版)或 Core ML,平衡速度与精度。
安全共享与协作:Safetensors 或 ONNX,避免安全漏洞并支持跨语言协作。
AI模型可以有多种不同的文件格式,每种格式都有自己的文件后缀和使用方法。以下是一些常见的AI模型格式及其文件后缀和使用方法:
TensorFlow模型:
文件后缀:.pb(Protocol Buffer格式)、.h5(HDF5格式)
使用方法:使用TensorFlow框架的API加载和使用模型。可以使用tf.saved_model.loader.load()函数加载.pb文件,使用tf.keras.models.load_model()函数加载.h5文件。
PyTorch模型:
文件后缀:.pt、.pth
使用方法:使用PyTorch框架的API加载和使用模型。可以使用torch.load()函数加载.pt或.pth文件。
pytorch使用pt模型
步骤1:导入必要的库和模块
在这一步中,我们需要导入PyTorch和其他必要的库和模块。通常,我们需要导入以下库和模块:
import torch
import torchvision
步骤2:加载.pt模型文件
在这一步中,我们将加载.pt模型文件。我们可以使用torch.load函数来加载.pt模型文件,并将其保存为一个变量。
model = torch.load('model.pt')
这里,model.pt表示.pt模型文件的路径。请确保.pt模型文件位于当前工作目录中,或者提供正确的文件路径。
步骤3:使用模型进行推理或训练
在这一步中,我们可以使用加载的模型进行推理或训练。根据具体的任务,我们可能需要做一些预处理或后处理的操作。
output = model(input)
这里,input表示输入数据。请根据具体的任务和模型的要求提供正确的输入。
步骤4:保存模型(可选)
在这一步中,我们可以选择将训练好的模型保存为.pt文件,以备将来使用。
torch.save(model, 'model.pt')
这里,model表示要保存的模型对象,model.pt表示保存的.pt文件的路径。请确保提供正确的文件路径。
一、做法
1.*.pt文件
.pt文件保存的是模型的全部,在加载时可以直接赋值给新变量model = torch.load("filename.pt")。
具体操作:
(1). 模型的保存
torch.save(model,"Path/文件名.pt")
这里的Path为你想将模型保存的位置,写完Path后加一个"/"表示进入目录内部,最后给出文件名.pt.
(2). 模型的加载
model = torch.load("文件名.pt")
注意:torch.load()的参数使用字符串参数。
2. .pth文件
.pth保存的是模型参数,通过字符字典进行保存,在加载该类文件时应该先实例化一个具体的模型,然后对新建立的空模型,进行参数赋予。
具体操作:
(1). 模型的保存
torch.save(model.state_dict(), PATH)
(2). 模型的加载
model = torch.nn.Module() # 这里要先实例化模型
model.load_state_dict(torch.load("xxx.pth"))
二 、操作实例
这里先定义一个模型作为例子
# Define model
class TheModelClass(nn.Module):
# 类的初始化
def __init__(self):
# 继承父类 nn.Module 的属性和方法
super(TheModelClass, self).__init__()
# Inputs_channel, Outputs_channel, kernel_size
self.conv1 = nn.Conv2d(3, 6, 5)
# 最大池化层,池化核的大小
self.pool = nn.MaxPool2d(2, 2)
# 卷积层,池化层,卷积层
self.conv2 = nn.Conv2d(6, 16, 5)
# 最后接一个线性全连接层
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# 卷积作用后,使用relu进行非线性化,最后使用池化操作进行特征个数,参数量的降低
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# Initialize model
model = TheModelClass()
# Initialize optimizer
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
# Print model's state_dict
print("Model's state_dict:")
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
# Print optimizer's state_dict
print("Optimizer's state_dict:")
for var_name in optimizer.state_dict():
print(var_name, "\t", optimizer.state_dict()[var_name])
2. 现在开始进行模型的保存与加载
PATH = "E:/深度学习/model"
# ######################### 第一种模型保存和加载方式
torch.save(model.state_dict(), PATH+"/TheModuleClass.pth")
model = TheModelClass()
model.load_state_dict(torch.load("E:/深度学习/model/TheModuleClass.pth"))
for param_tensor in model.state_dict():
print(f"{param_tensor}<<<{model.state_dict()[param_tensor].size()}")
print(model)
# ####### 输出结果
'''
conv1.weight<<<torch.Size([6, 3, 5, 5])
conv1.bias<<<torch.Size([6])
conv2.weight<<<torch.Size([16, 6, 5, 5])
conv2.bias<<<torch.Size([16])
fc1.weight<<<torch.Size([120, 400])
fc1.bias<<<torch.Size([120])
fc2.weight<<<torch.Size([84, 120])
fc2.bias<<<torch.Size([84])
fc3.weight<<<torch.Size([10, 84])
fc3.bias<<<torch.Size([10])
TheModelClass(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
'''
# ########################### 第二种模型保存和加载方式
torch.save(model, PATH + "/the_module_class.pt")
model = torch.load(PATH + "/the_module_class.pt")
for param_tensor in model.state_dict():
print(f"{param_tensor} <<< {model.state_dict()[param_tensor].size()}")
print(model)
# ####### 输出结果
'''
conv1.weight<<<torch.Size([6, 3, 5, 5])
conv1.bias<<<torch.Size([6])
conv2.weight<<<torch.Size([16, 6, 5, 5])
conv2.bias<<<torch.Size([16])
fc1.weight<<<torch.Size([120, 400])
fc1.bias<<<torch.Size([120])
fc2.weight<<<torch.Size([84, 120])
fc2.bias<<<torch.Size([84])
fc3.weight<<<torch.Size([10, 84])
fc3.bias<<<torch.Size([10])
TheModelClass(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
'''
总结
这里推荐使用第二种方法,因为保存和加载文件简单,而且生成的二进制文件区分程度高。
torch.save() 保存模型的参数,为以后模型推理核模型恢复提供了更加方便更加灵活的方法。
一定要在模型评估时, 关闭批量规范化和丢弃法, 仅仅在模型训练时有用,模型推理时一定要关闭(所谓模型推理,指是使用模型进行的实际应用)
加载.pth 要先实例化,再进行参数的承接。
ONNX模型:
文件后缀:.onnx
使用方法:使用ONNX框架或支持ONNX的其他框架加载和使用模型。可以使用onnxruntime库加载和执行ONNX模型。
Keras模型:
文件后缀:.h5
使用方法:使用Keras框架的API加载和使用模型。可以使用keras.models.load_model()函数加载.h5文件。
Caffe模型:
文件后缀:.caffemodel、.prototxt
使用方法:使用Caffe框架的API加载和使用模型。可以使用caffe.Net()函数加载.caffemodel和.prototxt文件。
GGUF(GPT-Generated Unified Format)格式:
文件后缀:.gguf
由 Georgi Gerganov(著名开源项目llama.cpp的创始人)定义发布的一种大模型文件格式。GGUF 继承自其前身 GGML,但 GGML 格式有一些缺点,已被完全弃用并被 GGUF 格式取代。GGUF 是一种二进制格式文件的规范,原始的大模型预训练结果经过转换后变成 GGUF 格式可以更快地被载入使用,也会消耗更低的资源。原因在于 GGUF 采用了多种技术来保存大模型预训练结果,包括采用紧凑的二进制编码格式、优化的数据结构、内存映射等。
GGUF 具有如下特性:
单文件部署:它们可以轻松分发和加载,并且不需要任何外部文件来获取附加信息。
可扩展性:可以将新特征添加到基于 GGML 的执行器中/可以将新信息添加到 GGUF 模型中,而不会破坏与现有模型的兼容性。
mmap兼容性:可以使用mmap加载模型,以实现快速地加载和保存。
易于使用:无论使用何种语言,都可以使用少量代码轻松加载和保存模型,无需外部库。
信息完整:加载模型所需的所有信息都包含在模型文件中,用户不需要提供任何额外的信息。这大大简化了模型部署和共享的流程。
safetensors更侧重于安全性和效率,适合快速部署和对安全性有较高要求的场景,特别是在HuggingFace生态中。而gguf格式则是一种为大模型设计的二进制文件格式,优化了模型的加载速度和资源消耗,适合需要频繁加载不同模型的场景。
在大型深度学习模型的上下文中,.safetensors、.bin 和 .pth ckpt 文件的用途和区别如下:
.safetensors 文件:
这是由 Hugging Face 推出的一种新型安全模型存储格式,特别关注模型安全性、隐私保护和快速加载。
它仅包含模型的权重参数,而不包括执行代码,这样可以减少模型文件大小,提高加载速度。
加载方式:使用 Hugging Face 提供的相关API来加载 .safetensors 文件,例如 safetensors.torch.load_file() 函数。
ckpt文件:
ckpt 文件是 PyTorch Lightning 框架采用的模型存储格式,它不仅包含了模型参数,还包括优化器状态以及可能的训练元数据信息,使得用户可以无缝地恢复训练或执行推理。
.bin 文件:
通常是一种通用的二进制格式文件,它可以用来存储任意类型的数据。
在机器学习领域,.bin 文件有时用于存储模型权重或其他二进制数据,但并不特指PyTorch的官方标准格式。
对于PyTorch而言,如果用户自己选择将模型权重以二进制格式保存,可能会使用 .bin 扩展名,加载时需要自定义逻辑读取和应用这些权重到模型结构中。
.pth 文件:
是 PyTorch 中用于保存模型状态的标准格式。
主要用于保存模型的 state_dict,包含了模型的所有可学习参数,或者整个模型(包括结构和参数)。
加载方式:使用 PyTorch 的 torch.load() 函数直接加载 .pth 文件,并通过调用 model.load_state_dict() 将加载的字典应用于模型实例。
总结起来:
.safetensors 侧重于安全性和效率,适合于那些希望快速部署且对安全有较高要求的场景,尤其在Hugging Face生态中。
.ckpt 文件是 PyTorch Lightning 框架采用的模型存储格式,它不仅包含了模型参数,还包括优化器状态以及可能的训练元数据信息,使得用户可以无缝地恢复训练或执行推理。
.bin 文件不是标准化的模型保存格式,但在某些情况下可用于存储原始二进制权重数据,加载时需额外处理。
.pth 是PyTorch的标准模型保存格式,方便模型的持久化和复用,支持完整模型结构和参数的保存与恢复。
加载以及保存
- 加载.safetensors文件:
# 用SDXL举例
import torch
from diffusers import StableDiffusionXLPipeline, UNet2DConditionModel, EulerDiscreteScheduler
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
base = "stabilityai/stable-diffusion-xl-base-1.0"
repo = "ByteDance/SDXL-Lightning"
ckpt = "/home/bino/svul/models/sdxl/sdxl_lightning_2step_unet.safetensors" # Use the correct ckpt for your step setting!
# Load model.
unet = UNet2DConditionModel.from_config(base, subfolder="unet").to("cuda", torch.float16)
unet.load_state_dict(load_file(ckpt, device="cuda"))
# unet.load_state_dict(load_file(hf_hub_download(repo, ckpt), device="cuda"))
pipe = StableDiffusionXLPipeline.from_pretrained(base, unet=unet, torch_dtype=torch.float16, variant="fp16").to("cuda")
# Ensure sampler uses "trailing" timesteps.
pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config, timestep_spacing="trailing")
# Ensure using the same inference steps as the loaded model and CFG set to 0.
pipe("A girl smiling", num_inference_steps=4, guidance_scale=0).images[0].save("output.png")
- 保存/加载.pth文件:
# 保存模型状态字典
torch.save(model.state_dict(), "model.pth")
# 加载模型状态字典到已有模型结构中
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load("model.pth"))
# 或者保存整个模型,包括结构
torch.save(model, "model.pth")
# 加载整个模型
model = torch.load("model.pth", map_location=device)
- 保存/加载.ckpt文件:
import pytorch_lightning as pl
# 定义一个 PyTorch Lightning 训练模块
class MyLightningModel(pl.LightningModule):
def __init__(self):
super().__init__()
self.linear_layer = nn.Linear(10, 1)
self.loss_function = nn.MSELoss()
def forward(self, inputs):
return self.linear_layer(inputs)
def training_step(self, batch, batch_idx):
features, targets = batch
predictions = self(features)
loss = self.loss_function(predictions, targets)
self.log('train_loss', loss)
return loss
# 初始化 PyTorch Lightning 模型
lightning_model = MyLightningModel()
# 配置 ModelCheckpoint 回调以定期保存最佳模型至 .ckpt 文件
checkpoint_callback = pl.callbacks.ModelCheckpoint(
monitor='val_loss',
filename='best-model-{epoch:02d}-{val_loss:.2f}',
save_top_k=3,
mode='min'
)
# 创建训练器并启动模型训练
trainer = pl.Trainer(
callbacks=[checkpoint_callback],
max_epochs=10
)
trainer.fit(lightning_model)
# 从 .ckpt 文件加载最优模型权重
best_model = MyLightningModel.load_from_checkpoint(checkpoint_path='best-model.ckpt')
# 使用加载的 .ckpt 文件中的模型进行预测
sample_input = torch.randn(1, 10)
predicted_output = best_model(sample_input)
print(predicted_output)
在此示例中,我们首先定义了一个 PyTorch Lightning 模块,该模块集成了模型训练的逻辑。然后,我们配置了 ModelCheckpoint 回调函数,在训练过程中按照验证损失自动保存最佳模型至 .ckpt 文件。接着,我们展示了如何加载 .ckpt 文件中的最优模型权重,并利用加载后的模型对随机输入数据进行预测,同样输出预测结果。值得注意的是,由于 .ckpt 文件完整记录了训练状态,它在实际应用中常被用于模型微调和进一步训练。
- 处理.bin文件:
如果.bin文件是纯二进制权重文件,加载时需要知道模型结构并且手动将权重加载到对应的层中,例如:
# 假设已经从.bin文件中读取到了模型权重数据
weights_data = load_binary_weights("weights.bin")
# 手动初始化模型并加载权重
model = TheModelClass(*args, **kwargs)
for name, param in model.named_parameters():
if name in weights_mapping: # 需要预先知道权重映射关系
param.data.copy_(weights_data[weights_mapping[name]])
模型之间的互相转换
pytorch-lightning 和 pytorch
由于 PyTorch Lightning 模型本身就是 PyTorch 模型,因此不存在严格意义上的转换过程。你可以直接通过 LightningModule 中定义的神经网络层来进行保存和加载,就像普通的 PyTorch 模型一样:
# 假设 model 是一个 PyTorch Lightning 模型实例
model = MyLightningModel()
# 保存模型权重
torch.save(model.state_dict(), 'lightning_model.pth')
# 加载到一个新的 PyTorch 模型实例
new_model = MyLightningModel()
new_model.load_state_dict(torch.load('lightning_model.pth'))
# 或者加载到一个普通的 PyTorch Module 实例(假设结构一致)
plain_pytorch_model = MyPlainPytorchModel()
plain_pytorch_model.load_state_dict(torch.load('lightning_model.pth'))
ckpt和safetensors
转换后的模型在stable-diffussion-webui中使用过没有问题,不知道有没有错误,或者没转换成功
import torch
import os
import safetensors
from typing import Dict, List, Optional, Set, Tuple
from safetensors.torch import _find_shared_tensors, _is_complete, load_file, save_file
def ckpt2safetensors():
loaded = torch.load('v1-5-pruned-emaonly.ckpt')
if "state_dict" in loaded:
loaded = loaded["state_dict"]
safetensors.torch.save_file(loaded, 'v1-5-pruned-emaonly.safetensors')
def st2ckpt():
# 加载 .safetensors 文件
data = safetensors.torch.load_file('v1-5-pruned-emaonly.safetensors.bk')
data["state_dict"] = data
# 将数据保存为 .ckpt 文件
torch.save(data, os.path.splitext('v1-5-pruned-emaonly.safetensors')[0] + '.ckpt')
AI模型格式转换
模型格式互转的核心是:以通用格式(如 ONNX)为桥梁,结合框架 / 硬件专属工具链实现转换。简单模型可直接通过脚本完成,复杂模型需针对性处理算子和维度问题。实际操作中,建议先查阅目标格式的官方文档,确保算子支持度满足需求。
手里有一个AI大模型只知道扩展名,如何调用呢
####【豆包】
Q:手里有一个AI大模型只知道扩展名,如何调用呢
A:...
Q:如何调用它的训练和推理呢
A:...
核心结论:推理调用可直接按模型格式匹配工具链实现,训练调用仅支持原始权重格式(.pt/.pth、safetensors 等),量化 / 部署格式(GGUF、TensorRT 等)需先转回原始格式才能训练。
一、推理调用(最常用,步骤简单)
推理是加载模型后执行预测任务(文本生成、图像识别等),不同格式的核心调用逻辑的是 “格式→工具链→执行推理”,以下是高频格式的实操方法:
1. 原始权重格式(.pt/.pth、safetensors)
工具链:PyTorch + Hugging Face Transformers(大模型首选)
文本模型(如 Llama、Qwen)调用示例:
from transformers import AutoModelForCausalLM, AutoTokenizer
# 加载模型和Tokenizer(safetensors格式直接替换路径即可,无需改代码)
model = AutoModelForCausalLM.from_pretrained("模型文件夹路径", device_map="auto") # auto自动用GPU/CPU
tokenizer = AutoTokenizer.from_pretrained("模型文件夹路径")
# 推理(文本生成)
prompt = "请介绍AI大模型的应用场景"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
2. GGUF 格式(量化模型,适合低资源设备)
工具链:llama.cpp(命令行 / Python)或 ollama(服务化)
命令行快速推理(CPU/GPU 通用):
bash
# 下载llama.cpp后,执行以下命令(-ngl 32 表示用32层GPU加速,0则纯CPU)
./llama.cpp/main -m 模型.gguf -p "请介绍AI大模型的应用场景" -ngl 32 -n 200
Python API 调用:
from llama_cpp import Llama
llm = Llama(model_path="模型.gguf", n_ctx=2048, n_gpu_layers=32) # n_ctx是上下文长度
output = llm.create_completion(prompt="请介绍AI大模型的应用场景", max_tokens=200)
print(output["choices"][0]["text"])
3. ONNX 格式(跨框架通用)
工具链:ONNX Runtime
文本模型推理示例:
import onnxruntime as ort
import tokenizer # 需对应模型的Tokenizer(如transformers的AutoTokenizer)
# 加载ONNX模型和Tokenizer
session = ort.InferenceSession("模型.onnx", providers=["CUDAExecutionProvider"]) # GPU加速
tokenizer = AutoTokenizer.from_pretrained("模型文件夹路径")
# 预处理输入
prompt = "请介绍AI大模型的应用场景"
inputs = tokenizer(prompt, return_tensors="np") # ONNX Runtime默认用numpy数组
# 执行推理
output_names = [output.name for output in session.get_outputs()]
outputs = session.run(output_names, dict(inputs))
generated_ids = outputs[0].argmax(axis=-1)
print(tokenizer.decode(generated_ids[0], skip_special_tokens=True))
4. 部署格式(TensorRT/.trt、TFLite/.tflite)
仅用于推理,不支持训练,调用依赖硬件工具链:
TensorRT(NVIDIA GPU):用 TensorRT Python/C++ API 加载引擎,输入预处理后执行推理。
TFLite(移动端 / 边缘设备):用 TensorFlow Lite Interpreter,适合手机、嵌入式设备。
二、训练调用(需原始格式,步骤更复杂)
训练是更新模型权重(微调、全量训练),仅支持原始权重格式(.pt/.pth、safetensors),量化格式(GGUF)、部署格式(TensorRT、ONNX)需先转回原始格式才能训练。
1. 前提条件
模型格式:必须是含完整结构的原始权重(仅.pt文件可能需额外模型定义代码)。
环境:PyTorch/TensorFlow 框架、足够显存(微调需 16GB+ GPU,全量训练需 32GB+)。
数据:按模型任务准备数据集(如文本生成用 JSON 格式,每行含 "prompt" 和 "response")。
2. 微调训练示例(Hugging Face Transformers)
以文本模型微调为例,用 LoRA(低资源高效微调)方法:
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model # LoRA依赖peft库
# 1. 加载原始模型和Tokenizer
model = AutoModelForCausalLM.from_pretrained("模型文件夹路径", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("模型文件夹路径")
tokenizer.pad_token = tokenizer.eos_token # 补全pad token(部分模型需手动设置)
# 2. 配置LoRA参数(减少显存占用)
lora_config = LoraConfig(
r=8, lora_alpha=32, target_modules=["q_proj", "v_proj"], lora_dropout=0.05
)
model = get_peft_model(model, lora_config)
# 3. 准备训练数据(示例:简单文本对)
train_data = [
{"prompt": "介绍AI", "response": "AI是人工智能的简称,用于模拟人类智能行为"},
{"prompt": "AI的应用", "response": "AI可用于医疗诊断、自动驾驶、智能客服等场景"}
]
# 数据预处理(tokenize)
def process_data(examples):
inputs = tokenizer(examples["prompt"], truncation=True, max_length=512)
outputs = tokenizer(examples["response"], truncation=True, max_length=512)
inputs["labels"] = outputs["input_ids"]
return inputs
processed_data = process_data({"prompt": [d["prompt"] for d in train_data], "response": [d["response"] for d in train_data]})
# 4. 配置训练参数
training_args = TrainingArguments(
output_dir="./train_output", # 训练输出目录
per_device_train_batch_size=2, # 批次大小(根据显存调整)
num_train_epochs=3, # 训练轮次
logging_steps=10, # 日志输出间隔
learning_rate=2e-4 # 学习率
)
# 5. 启动训练
trainer = Trainer(model=model, args=training_args, train_dataset=processed_data)
trainer.train()
# 6. 保存微调后的模型(LoRA权重,体积小)
model.save_pretrained("./lora_finetuned_model")
3. 关键注意事项
3.1量化格式无法直接训练:若模型是 GGUF 格式,需先用llama.cpp的反向转换脚本转回 PyTorch 格式(仅部分模型支持)。
3.2.存不足解决方案:用 LoRA、QLoRA(量化 LoRA)微调,或降低批次大小、启用梯度检查点(model.gradient_checkpointing_enable())。
3.3模型结构依赖:若仅有权重文件(.pt),需手动编写模型结构代码(如 Transformer 类),否则无法加载训练。
三、特殊场景处理
1.仅有权重文件,无模型结构:
优先用 Hugging Face AutoModel加载,自动匹配结构(需模型是标准架构,如 Llama、BERT)。
若失败,需查找模型原始发布地址,获取对应的模型定义代码。
2.训练后模型格式转换:
微调后的 PyTorch 模型可转成 safetensors(安全)、GGUF(量化部署)、ONNX(跨框架),参考之前的格式转换方法。
要不要我根据你手里的模型扩展名(比如.pt、gguf 等),生成一份专属的推理 + 训练(若支持)调用脚本,直接复制就能运行?
何为JSONL 文件
JSONL (JSON Lines) 是一种文本文件格式,其中每一行都是一个独立的 JSON 对象。它与传统的 JSON 文件不同,传统的 JSON 文件将所有数据存储在一个单一的对象或数组中。
JSONL 的优点:
易于解析: 每行都是独立的 JSON 对象,解析器可以逐行处理文件,而无需将整个文件加载到内存中。
流式处理: JSONL 文件非常适合处理流数据,因为数据可以逐行写入和读取。
易于追加: 可以轻松地将新的 JSON 对象追加到现有 JSONL 文件的末尾。
JSONL 的缺点:
可读性较差: 与格式化的 JSON 文件相比,JSONL 文件的可读性较差。
不适合嵌套数据: JSONL 文件不太适合存储高度嵌套的数据结构。
JSONL 文件样本
以下是一个包含用户信息的 JSONL 文件样本:
{"id": 1, "name": "John Doe", "age": 30, "city": "New York"}
{"id": 2, "name": "Jane Doe", "age": 25, "city": "Los Angeles"}
{"id": 3, "name": "Peter Pan", "age": 20, "city": "London"}
说明:
文件中的每一行代表一个用户。
每一行都是一个有效的 JSON 对象,包含用户的 ID、姓名、年龄和城市信息。
实际用Python调用OpenAI开发聊天程序,每次给OpenAI多少轮的对话最合理
在使用 Python 调用 OpenAI 开发聊天程序时,每次给 OpenAI 多少轮对话没有一个固定的 “最合理” 数量,因为这会受到多种因素的影响,以下是详细分析及相关建议:
影响因素
模型上下文窗口:不同模型的上下文窗口大小不同,如gpt - 3.5 - turbo是 4096 个 token,gpt - 3.5 - turbo - 16k是 16384 个 token。在决定传递多少轮对话时,需要确保总 token 数不超过模型的上下文窗口限制,否则请求会失败。
对话内容复杂度:如果每轮对话内容简短、信息密度低,能传递的轮数就相对较多;反之,如果每轮对话都是长篇大论、包含大量专业术语或复杂描述,能传递的轮数就会减少。
任务需求:如果聊天程序是用于简单的问答场景,可能只需保留最近几轮对话就能满足需求;但如果是用于复杂的故事续写、文档分析等场景,可能需要传递更多轮对话以提供足够的上下文。
不同场景下的建议
简单问答场景
对于日常简单的问答,如查询天气、询问常识等,通常保留最近 3 - 5 轮对话即可。这样既能让模型了解当前对话的上下文,又不会占用过多的上下文窗口资源。例如:
python
import openai
openai.api_key = "your_api_key"
# 初始化对话历史
conversation_history = [
{"role": "system", "content": "你是一个简单问答助手。"}
]
# 模拟3轮对话
for _ in range(3):
user_input = input("你: ")
conversation_history.append({"role": "user", "content": user_input})
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=conversation_history
)
assistant_reply = response.choices[0].message.content
conversation_history.append({"role": "assistant", "content": assistant_reply})
print(f"助手: {assistant_reply}")
# 只保留最近5轮对话
if len(conversation_history) > 5:
conversation_history = conversation_history[-5:]
复杂交互场景
在进行故事续写、多步骤问题解决等复杂交互时,可能需要保留 10 - 20 轮对话甚至更多。不过要密切关注 token 数量,避免超出模型的上下文窗口。可以使用tiktoken库来监控 token 数,示例如下:
python
import openai
import tiktoken
openai.api_key = "your_api_key"
encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
# 初始化对话历史
conversation_history = [
{"role": "system", "content": "你是一个故事续写助手。"}
]
# 模拟15轮对话
for _ in range(15):
user_input = input("你: ")
conversation_history.append({"role": "user", "content": user_input})
# 计算当前对话历史的总token数
total_tokens = 0
for message in conversation_history:
total_tokens += len(encoding.encode(message["content"]))
# 若接近上下文窗口限制,适当缩减对话历史
while total_tokens > 3500: # 预留一定空间
conversation_history.pop(1) # 移除较早的用户消息
total_tokens = 0
for message in conversation_history:
total_tokens += len(encoding.encode(message["content"]))
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=conversation_history
)
assistant_reply = response.choices[0].message.content
conversation_history.append({"role": "assistant", "content": assistant_reply})
print(f"助手: {assistant_reply}")
总之,要根据具体的应用场景和模型的上下文窗口大小,灵活调整传递给 OpenAI 的对话轮数,以达到最佳的对话效果。
####
Q:那么大模型第一个输出token如何确定的后续才有下个字的概率啊
A:...
这一问问到最根部了:
模型明明要 “上文” 才预测下文,那第一个 token 是怎么来的?
我用最直白、最硬核、程序员一听就懂的方式讲清楚。
一句话结论
大模型根本没有 “第一个输出 token” 这种东西。
它永远是:给一段上文 → 预测下一个。
你看到的 “第一句话”,上文其实是 <bos> + 你的提示词。
1. 模型从诞生起,就只会做一件事
P (下一个 token | 前面所有 token)
它不会从头开始创作,
它只会接着你给的东西往下写。
你输入:
plaintext
你好
模型看到的不是 “凭空开始”,而是:
plaintext
<bos> 你 好
然后预测:
plaintext
下一个token = ?
这就是第一个输出字的来源。
2. 超清晰流程(你问的 “第一个输出 token 怎么来”)
步骤 0:你输入提示
为什么天空是蓝色的?
步骤 1:分词 → ID 序列
[101, 200, 305, 678, ... ](一共 10 个 ID)
步骤 2:送入模型
模型立刻计算最后一个位置的输出向量
→ 投影词表
→ 得到第一个输出 token 的概率
步骤 3:选出第一个输出字
比如模型选出:因
这就是你看到的第一个字。
3. 关键真相
第一个输出 token = 提示词最后一个字的下一个预测
不是凭空生成。
结构是这样:
plaintext
[提示词全部token]
↓
模型预测下一个
↓
第一个输出token
4. 然后才是 “后续不断生成”
第一个字出来后,把它拼到原文后面,变成新上文:
plaintext
[提示词] + [第一个输出字]
↓
模型再预测下一个
↓
第二个输出字
不断循环,直到结束。
5. 用最简单代码模拟(完全真实逻辑)
python
运行
# 初始输入(你的提示)
prompt_ids = [101, 200, 305, 678]
for i in range(20): # 生成20个字
# 1. 模型只做一件事:根据当前所有token,预测下一个
next_id = model(prompt_ids)
# 2. 输出第一个token
print("第%d个字: %s" % (i+1, token_to_word(next_id)))
# 3. 拼回去,变成新上文
prompt_ids.append(next_id)
第一次循环输出的,就是你看到的 “第一个字”。
6. 终极总结(最关键)
6.1 模型永远不会 “从零开始生成”
6.2 永远是:上文 → 下一个
6.3 你看到的第一个输出字 = 提示词末尾的下一个预测
6.4 之后每一个字 = 前面所有内容的下一个预测
所以:
不存在 “第一个输出字怎么来” 的玄学,
它就是提示词的下一个字。
上一篇:AI视觉技术应用与开发收集
下一篇:玩转AI开源项目经验收集