Skip to content

Commit 6263e46

Browse files
📝 更新文档,优化OpenCV与Transformer示例
- 在OpenCV文档中新增了边缘与轮廓部分,提供了边缘检测的相关信息。 - 在Transformer文档中精简了内容,删除了冗余的示例,增强了文档的清晰度与实用性。 - 增加了注意力机制的相关描述,提升了对Transformer模型的理解。
1 parent d0fe37c commit 6263e46

File tree

3 files changed

+16
-128
lines changed

3 files changed

+16
-128
lines changed

docs/docs/深度学习/Transformer.mdx

Lines changed: 10 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,14 @@ $$
8383

8484
</details>
8585

86-
{/*
87-
88-
学习Transformer的原理,使用PyTorch实现一个简单的Transformer模型,对模型进行训练和推理。通过分布式训练,提升模型训练效率。
89-
90-
这个配置预计显存占用:约 70GB+(使用 A100 GPU)。 且需要1-2周的训练时间,你才能拥有一个属于你自己的大模型(从随机权重开始预训练到基本连贯性)。
9186

92-
如果你的显存不够,刚好也可以通过文档中计算公式,调整模型配置,降低显存占用。这算是一个实践调参练习。
9387

9488
## Embedding
9589

9690
提前准备:训练好的词表
9791

9892
- 文本 通过提前训练好的词表拆分为 Token(分词)
99-
- Token 通过提前训练好的词表转化为 Token ID(独热编码)
93+
- Token 通过提前训练好的词表转化为 Token ID
10094
- Token ID 通过提前训练好的词表转化为 Token Embedding(词嵌入)
10195
- 将位置信息 转化为 位置编码(位置编码)
10296
- 将 Token Embedding 和 位置编码 相加 得到 最终的输入向量
@@ -121,127 +115,6 @@ $$
121115

122116
词嵌入的过程是分割好的词从【嵌入矩阵】中获取自己向量的过程,假设【嵌入矩阵】维度为4(GPT2选用768维)如下:
123117

124-
| 词汇/Token | 维度1 | 维度2 | 维度3 | 维度4 |
125-
| ---------- | ----- | ----- | ----- | ----- |
126-
| \<PAD\> | 0.00 | 0.00 | 0.00 | 0.00 |
127-
| \<UNK\> | 0.12 | -0.51 | 0.32 | 0.89 |
128-
| 我 | 0.87 | 0.42 | -0.26 | 0.35 |
129-
| 机器 | 0.32 | 0.52 | 0.75 | 0.22 |
130-
| 学习 | 0.45 | 0.68 | 0.21 | 0.37 |
131-
| 爱 | 0.65 | 0.71 | 0.38 | -0.15 |
132-
133-
当输入一个句子"我爱学习机器学习"时,会被分词为["我", "爱", "学习", "机器", "学习"],然后每个词在嵌入矩阵中查找对应的向量,得到一系列向量表示:
134-
135-
- "我" → [0.87, 0.42, -0.26, 0.35]
136-
- "爱" → [0.65, 0.71, 0.38, -0.15]
137-
- "学习" → [0.45, 0.68, 0.21, 0.37]
138-
- "机器" → [0.32, 0.52, 0.75, 0.22]
139-
- "学习" → [0.45, 0.68, 0.21, 0.37]
140-
141-
这样,原本的文本序列就被转换为向量序列,这个过程人可以通过肉眼直接看到,机器如何完成?你可以使用for循环加判断,但是有更简单快速的方式:独热编码
142-
143-
独热编码(One-Hot Encoding)是一种将每个词表示为一个向量,该向量的长度等于词表大小,只有对应词的位置为1,其余位置为0的编码方式:
144-
145-
```python
146-
import numpy as np
147-
148-
# 假设我们有一个词表和嵌入矩阵
149-
# 词 : token_id
150-
vocab = {"<PAD>": 0,
151-
"<UNK>": 1,
152-
"我": 2,
153-
"爱": 3,
154-
"学习": 4,
155-
#..........
156-
"机器": 5000,
157-
}
158-
embedding_matrix = np.array([
159-
# 假设为N个维度,N列,这里具象化为4列
160-
[0.00, 0.00, 0.00, 0.00], # <PAD>
161-
[0.12, -0.51, 0.32, 0.89], # <UNK>
162-
[0.87, 0.42, -0.26, 0.35], # 我
163-
[0.65, 0.71, 0.38, -0.15], # 爱
164-
[0.45, 0.68, 0.21, 0.37], # 学习
165-
# ........
166-
[0.32, 0.52, 0.75, 0.22], # 机器
167-
])
168-
169-
# 将词转换为独热编码
170-
def word_to_onehot(word, vocab_size):
171-
onehot = np.zeros(vocab_size)
172-
if word in vocab:
173-
onehot[vocab[word]] = 1
174-
# 以 "我"这个字为例,vocab["我"] 为2,对应下标位置的值为1,其他为0.
175-
# onehot[2] = 1 即[0,0,1,0,0,.....,0]
176-
else:
177-
onehot[vocab["<UNK>"]] = 1 # 即未知为1.其他为0 [0,1,0,0,0,.....,0]
178-
return onehot # 形状为 :1,5000
179-
180-
# 通过独热编码获取词嵌入
181-
def get_embedding_via_onehot(word, vocab, embedding_matrix):
182-
onehot = word_to_onehot(word, len(vocab))
183-
return np.dot(onehot, embedding_matrix) # 1,5000 @ 5000,N列 = 1,N列
184-
185-
# 示例
186-
tokens = ["我", "爱", "学习", "机器", "学习"] # 5个词
187-
embeddings = [get_embedding_via_onehot(token, vocab, embedding_matrix) for token in tokens]
188-
# 形状为 5 行 N列,每行即是词对应的向量
189-
```
190-
191-
实际应用中,我们通常直接使用词索引进行查找,避免独热编码的稀疏计算:
192-
193-
```python
194-
import torch
195-
import numpy as np
196-
embedding_matrix = np.array([
197-
# 假设为N个维度,N列,这里具象化为4列
198-
[0.00, 0.00, 0.00, 0.00], # <PAD>
199-
[0.12, -0.51, 0.32, 0.89], # <UNK>
200-
[0.87, 0.42, -0.26, 0.35], # 我
201-
[0.65, 0.71, 0.38, -0.15], # 爱
202-
[0.45, 0.68, 0.21, 0.37], # 学习
203-
# ........
204-
[0.32, 0.52, 0.75, 0.22], # 机器
205-
])
206-
207-
# 使用PyTorch的Embedding层
208-
vocab_size,embedding_dim = embedding_matrix.shape
209-
# embedding_dim 表示词嵌入向量的维度大小,即每个词被映射为4维向量,自己根据预定义的嵌入矩阵设置
210-
# vocab_size 表示词汇表的大小,自己根据预定义的嵌入矩阵设置
211-
212-
# 假设我们有一个词表和嵌入矩阵
213-
vocab = {"<PAD>": 0,
214-
"<UNK>": 1,
215-
"我": 2,
216-
"爱": 3,
217-
"学习": 4,
218-
#..........
219-
"机器": 5000,
220-
}
221-
222-
# 创建嵌入层并初始化权重
223-
embedding = torch.nn.Embedding(vocab_size, embedding_dim)
224-
# 设置预定义的嵌入矩阵
225-
embedding.weight.data = torch.tensor(embedding_matrix, dtype=torch.float)
226-
227-
# 将文本转换为索引
228-
def tokens_to_indices(tokens, vocab):
229-
return [vocab.get(token, vocab["<UNK>"]) for token in tokens]
230-
231-
# 示例
232-
tokens = ["我", "爱", "学习", "机器", "学习"]
233-
indices = tokens_to_indices(tokens, vocab)
234-
token_indices = torch.tensor(indices)
235-
token_embeddings = embedding(token_indices) # 并行计算
236-
237-
print(token_embeddings)
238-
'''
239-
240-
在实际的Transformer模型中,词嵌入通常是模型训练的一部分,会根据任务目标不断优化调整。这种基于查表的方式比循环判断更高效,可以并行处理整个序列的所有词,大大提高了计算速度。
241-
242-
词嵌入只考虑了词的语义信息,但在序列中,词的位置也很重要。Transformer通过位置编码(Positional Encoding)来捕捉序列中词的位置信息
243-
'''
244-
```
245118

246119
### 位置编码
247120

@@ -322,6 +195,8 @@ print(final_input)
322195
这个空间占用代表了64组数据,每组数据有1024个token,每个向量有768个参数,每个参数占用16位(2字节)。
323196
:::
324197

198+
{/*
199+
325200
## 注意力机制
326201
327202
### 拆分QKV
@@ -340,6 +215,13 @@ print(final_input)
340215
341216
其中,$W_q$、$W_k$、$W_v$ 是可变权重矩阵,$X$ 是输入的词向量。
342217
218+
:::tip
219+
220+
在PyTorch等深度学习框架中,为了高效利用计算资源(例如CUDA核心),我们不会真的执行三次独立的矩阵乘法。
221+
222+
223+
:::
224+
343225
344226
### 多头分割
345227

docs/docs/深度学习/opencv.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,7 @@ for i, (name, result) in enumerate(results.items()):
12911291
plt.tight_layout()
12921292
plt.show()
12931293
```
1294+
12941295
## 边缘与轮廓
12951296

12961297
### 边缘检测cv2.Canny

docs/docs/选择编程语言/Python/3序列.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,11 @@ def func(a, b, c):
12111211

12121212
args = (1, 2, 3)
12131213
result = func(*args) # 等同于 func(1, 2, 3)
1214+
1215+
1216+
# 字典同样可以解包
1217+
kwargs = {'a': 1, 'b': 2, 'c': 3}
1218+
result = func(**kwargs) # 等同于 func(a=1, b=2, c=3)
12141219
```
12151220

12161221
[PEP 3132 – 扩展可迭代对象解包](https://peps.python.org/pep-3132/)

0 commit comments

Comments
 (0)