- 博客(94)
- 收藏
- 关注
原创 深度学习 - 25 DDP
Dataset│▼│▼ ▼ ▼│ │ │▼ ▼ ▼│ │ │▼ ▼ ▼│ │ │▼ ▼ ▼│ │ ││Backward│▼ ▼ ▼│ │ ││ │ │▼ ▼ ▼│ │ │▼│▼│▼AllReduce││ ││ │▼│▼│▼DDP↓↓NCCL↓Collective↓↓↓GPU ↔ GPU↓↓NetworkDDP()开始背。
2026-09-27 16:00:30
222
原创 深度学习 - 24 ONNX 模型导出与量化
ONNX,全称 Open Neural Network Exchange,是一种用于表示机器学习模型的开放标准。Model├── Graph│Input:模型输入 TensorOutput:模型输出 TensorNode:计算节点,例如 MatMul、Conv、Add、Reshape、Softmax:模型参数,例如权重、biasAttribute:某些算子的静态参数Opset:节点采用哪一版本的 ONNX operator 语义。
2026-09-27 15:03:03
186
原创 深度学习 - 23 Whisper LoRA
Dropout(X)这一部分尤其需要和普通数据增强区分开。Base:LoRA:进入 LoRA 分支的 hidden-state activation。Microsoft 原始的实现就是;当前 Hugging Face PEFT 的 vanilla LoRA forward 也是同样的结构。你以为给某几个层加了 LoRA,实际匹配到的层却不是你想的那些。q_proj可能同时覆盖多个位置。当前 PEFT 的支持按模块名匹配,也支持all-linear等更广泛的选择。匹配了多少层。
2026-09-27 14:35:23
244
原创 深度学习 - 22 Beam Search
A → B → C【重点公式】PABC∣xPA∣xPB∣AxPC∣ABxPABC∣xPA∣xPB∣AxPC∣ABxPA∣xPB∣AxPC∣BxPA∣xPB∣AxPC∣Bx后者相当于假设当前预测只依赖前一个 token,而 Transformer Decoder 实际使用的是整个历史。才是正确的条件概率。Greedy 是只保留 1 条路径的搜索;
2026-09-27 11:01:26
272
原创 深度学习 - 18 (1) CTC从基础到完全掌握
CTC 可以先不理解成一堆公式,而是理解成下面这条数据流:CTC 最重要的不是“模型如何输出 target”。事实上模型根本没有直接输出 target。模型只做一件事:CTC 再利用 target 构造出的状态空间,计算:假设一段语音经过 Fbank 和 Encoder 后得到:即 10 个时间步。而真实文本只有:长度:很明显:而训练数据通常只有:并没有:这样的 frame-level alignment。也就是说,我们知道:但不知道:CTC 的做法就是:这是整个 CTC 数据流的起点。假
2026-09-27 10:19:29
253
原创 深度学习 - 21 Whisper
Whisper 是一种典型的 Encoder-Decoder Transformer Speech-to-Text 模型。它和传统 ASR 中常见的 CTC、RNN-T 最大的区别之一,是:因此,从建模形式看,Whisper 更接近:输入是一段语音 XXX,输出是 Token 序列 Y=(y1,y2,…,yL)Y=(y_1,y_2,\dots,y_L)Y=(y1,y2,…,yL)。模型最终建模的是:P(Y∣X)=∏t=1LP(yt∣y<t,X)P(Y|X)=\prod_{t=1}^{L}P(y_t|
2026-09-25 16:33:24
263
原创 深度学习 - 20 Zipformer
Zipformer 是一个面向语音识别的高效 Encoder 架构,最核心的变化可以概括成一句话:Conformer 通常经过前端 subsampling 后,在整个 Encoder 中保持相对固定的时间分辨率;Zipformer 则采用类似 U-Net 的多尺度结构,让不同 Encoder Stack 在不同时间分辨率上建模。原始 Zipformer 论文中的典型结构是:原论文明确把这种结构称为 U-Net-like encoder,并指出中间 Stack 工作在更低的 frame rate;同时不同
2026-09-25 10:39:04
250
原创 深度学习 - 19 Conformer
x│├─ MHSA│├─ FFN│└─ outputFFN 的作用不是进行 token 之间的交互。X∈RB×T×DX∈RB×T×DFFNxW2σW1xb1b2FFNxW2σW1xb1b2其中第一层通常把维度从DDD扩大到DffD_{ff}DffDff≈4DDff≈4D再投影回DDD。Attention↓不同时间位置之间发生交互。
2026-09-25 08:57:55
171
原创 深度学习 - 18 CTC:Connectionist Temporal Classification
BπB(\pi)Bπ合并连续重复的相同 label删除 blankA A _ B B→A _ B→A BA _ A不会被合并成一个 A,因为两个 A不是连续的A _ A↓A A这就是为什么 blank 不只是“空输出”,它还承担了分隔重复 Token的作用。假设 Encoder 输出有TTTππ1π2πTππ1π2πTπt∈blank∪Vπt∈blank∪V这样的整个序列就叫一个Path。
2026-09-25 07:52:19
150
原创 深度学习 - 17 ASR Subsampling 与 Streaming
如果 acoustic feature 每秒产生RRRR1ΔtRΔt1其中Δt\Delta tΔt是 frame shift。R10.01100R0.011100Streaming ASR 的核心要求不是:“一次只输入很短的音频。在音频尚未结束时,就能够持续地产生识别结果。把原本对完整序列的计算,改造成可以随着时间推进而增量计算的过程。
2026-09-24 13:48:34
213
原创 深度学习 - 16 ASR 整体架构
Conformer;Zipformer;当前情况下 vocabulary 中每个 token 的分数是多少?↓↓如果 hidden dimension 是DDD,词表大小是VVVW∈RV×DW∈RV×Dh∈RDh∈RDzWhbz=Wh+bzWhbz∈RVz∈RV把内部连续表示投影到离散 vocabulary 的分类空间。不是。更多候选 token更大的 output projection。
2026-09-23 17:15:16
138
原创 深度学习 - 15 ASR 基本问题
a1≤a2≤⋯≤aUa1≤a2≤⋯≤aU它表达的是时间顺序保持,而不是一对一映射。一个 token 可以覆盖多个 acoustic frames。
2026-09-23 17:01:39
199
原创 深度学习 - 14 Transformer 架构
│↓Q / K / V↓↓│↓为什么需要完整模型?│↓ ↓ ↓│ │ │↓ ↓ ↓Feature 深层训练 Sequence OrderMixing 稳定性 Information↓↓↓Encoder││ K / V↓Decoder└── FFN↓↓TrainingInferenceAudio↓长时间序列↓↓↓↓↓ASR│↓ ↓│ ││ ││Attention 解决信息交互;
2026-09-23 15:35:55
128
原创 深度学习 - 13 Attention 机制
Attention 是一种根据当前 Query 与所有 Key 的相关性动态生成权重,并对对应 Value 做加权聚合的机制。AttentionQKVsoftmaxQK⊤dkVAttentionQKVsoftmaxdkQK⊤V它允许序列中一个位置直接访问其他位置的信息。
2026-09-23 15:13:41
72
原创 深度学习 - 12(1) PyTorch - Data Pipeline ,CUDA / Memory , Mixed Precision
.....它回答的是:给我第index个样本,我怎样得到它?↓读取 wav↓读取 transcript↓读取 metadata↓提取 / 加载 feature↓数据增强↓返回:featuretranscriptnum_frames所以 Dataset 负责样本的获取和样本级处理。它不应该负责:“这一轮到底读取哪些样本、怎样排序、怎样组成 Batch”。这些工作由后面的 Sampler/DataLoader 负责。
2026-09-23 09:37:09
262
原创 深度学习 - 12 PyTorch - Data Pipeline ,CUDA / Memory , Mixed Precision
Dataset是数据访问协议,不等于“把全部数据加载到内存”。它描述如何根据索引或迭代状态产生样本。:实现,通常还实现__len__()。样本有稳定索引,随机打乱、分布式切分、按长度分桶都比较自然。:实现__iter__(),适合流式数据、远程数据源、无法随机访问的超大语料。多 worker 时,每个进程都有 Dataset 副本,必须自行做 shard,否则不同 worker 可能重复产生相同样本。
2026-09-22 17:19:41
248
原创 深度学习 - 11 PyTorch - Training API
通常应把一个实际的作为一个 optimizer update step。多个 micro-batch 只是一次参数更新前的梯度累积,因此 warmup、LR schedule、checkpoint interval 等如果定义在 optimizer-step 粒度上,也应按这个 global_step 推进。
2026-09-22 16:40:31
135
原创 深度学习 - 10 PyTorch - nn.Module
是 PyTorch 神经网络模型的基础抽象。它不是简单的“把几个 Tensor 包起来的 Python class”,更准确地说:PyTorch 官方文档明确将 Module 描述为:例如:逻辑结构实际上是:这棵树非常重要。因为很多 PyTorch 能力,本质上都是沿着这棵树递归执行的:所以:假设完全不用 :然后自己写:数学上完全可以。但很快会出现一系列工程问题:如果这些事情都手写,模型训练框架会迅速失去统一性。 就把这些事情集中起来:所以可以把 看成:一个 Module 可以拥有三种重要状
2026-09-22 15:56:17
136
原创 深度学习 - 09 PyTorch - Autograd
PyTorch Autograd 是 PyTorch 的。yfx∂x∂yX→Linear→Activation→Linear→L∂W1∂L∂b1∂L∂W2∂L∂b2∂LAutograd 的职责就是根据前向计算过程中发生的 Tensor 操作,自动构造和利用一张计算图,在调用backward()后,把这些梯度计算出来。这两个职责必须区分。
2026-09-22 14:34:46
86
原创 深度学习 - 08 PyTorch - Tensor
在某一个维度上移动一个位置,需要在底层 Storage 中跨过多少个元素。为什么?dim 0 移动一步→ 跨过整整一行→ 4 个元素dim 1 移动一步→ 只向后移动 1 个元素。
2026-09-22 13:45:24
140
原创 深度学习 - 07 数值稳定性
前面的 Loss、Optimizer、Regularization、Normalization 最终都会落到一个现实问题:因此数学上成立的表达式,不代表计算机里一定能稳定地算出来。例如数学上:e100e^{100}e100当然是有限的,但如果输入再大:e1000e^{1000}e1000就可能超出当前数据类型能够表示的范围。类似地:e−1000e^{-1000}e−1000在数学上非常接近 000,但在有限精度表示中可能直接变成:000于是:而在深度网络中,一旦某个关键 Tensor 出现
2026-09-21 09:25:42
163
原创 深度学习 - 06 Normalization
BatchNorm 通过 batch 统计量稳定 channel 的激活分布,但因此依赖 batch size 和 train/eval 状态;LayerNorm 在每个样本内部沿 feature dimension 做归一化,不依赖 batch,因此特别适合 Transformer、Conformer 和 ASR;RMSNorm 则进一步去掉 mean-centering,只进行 RMS 尺度归一化,以更简单的计算获得稳定的表示尺度。
2026-09-21 09:25:20
171
原创 深度学习 - 05 正则化
正则化是在训练目标或训练过程之外增加约束,以降低模型对训练数据偶然模式的依赖,从而改善泛化。LtotalLdataλRθLtotalLdataλRθ但 Dropout、Early Stopping 等并不直接通过增加 Loss 项实现。它不一定修改 Loss,而是限制 optimization trajectory 的长度。
2026-09-20 17:28:05
194
原创 深度学习 - 04 优化
上一章解决的是:得到 Loss 以后,还需要解决另一个更直接的问题:这就是优化(Optimization)要解决的问题。神经网络训练可以概括为:其中最容易混淆的是: 负责计算:∇θL\nabla_\theta L∇θL也就是:Optimizer 则负责根据这个梯度决定:最基本的参数更新就是 Gradient Descent:θt+1=θt−η∇θL(θt)\boxed{\theta_{t+1}=\theta_t-\eta\nabla_\theta L(\theta_t)}θt+1=θt−η∇
2026-09-20 17:25:07
157
原创 深度学习:03 损失函数
损失函数(Loss Function)本质上是在回答一个问题:神经网络训练的完整过程可以抽象成:X→fθ(X)→Y^→L(Y^,Y)→∇θL→θX \rightarrow f_\theta(X) \rightarrow \hat{Y} \rightarrow L(\hat{Y},Y) \rightarrow \nabla_\theta L \rightarrow \thetaX→fθ(X)→Y^→L(Y^,Y)→∇θL→θ其中:因此,Loss 并不是训练流程中的一个孤立模块。它实际上是连接:模型输出
2026-09-20 16:07:23
144
原创 深度学习 - 02 激活函数
σx11e−xσx1e−x1σx∈01σx∈01因此它天然可以解释成:一个类似概率的数值。x << 0 → 接近 0x >> 0 → 接近 1错误。Attention 中间也会使用 Softmax。更准确:Softmax 常用于需要形成归一化分布或权重分布的位置。GELU = ...为什么神经网络需要激活函数?↓因为纯 Linear 叠加仍然是 Linear↓所以必须加入非线性↓早期常用 Sigmoid / Tanh↓。
2026-09-20 15:25:33
208
原创 深度学习 - 01 训练基础
深度学习训练本质上是在解决一个优化问题:可以把整个过程压缩成:这里最重要的是区分三个东西:因此:更准确地说:Forward→Loss→Backward→Gradient→Optimizer→Parameter Update\text{Forward}\rightarrow\text{Loss}\rightarrow\text{Backward}\rightarrow\text{Gradient}\rightarrow\text{Optimizer}\rightarrow\text{P
2026-09-20 12:26:19
286
原创 深度学习 - LSTM
ForgetInputCandidateOutput可以按照这个顺序:LSTM 是 RNN 的一种改进结构,主要解决普通 RNN 在长序列训练中容易出现梯度消失、长期依赖学习困难的问题。它相比普通 RNN 增加了 Cell Statecₜ,同时维护 Hidden Statehₜ,并利用 Forget Gate、Input Gate、Candidate 和 Output Gate 对记忆进行控制。在时间步t,首先使用当前输入xₜ和上一时刻隐藏状态hₜ₋₁。
2026-09-18 16:08:23
164
原创 LeetCode 算法专题:哈希(Hash)
把一个对象通过哈希函数映射成一个整数,再利用这个整数快速定位数据。key↓↓hash value↓↓找到数据bucket 7那么查找时就不需要遍历所有数据,而是直接去bucket 7附近找。通过计算把“查找”变成“定位”。元素数量 / bucket 数量元素 = 8080 / 100→150 / 100冲突可能越来越严重。rehash(重新哈希 / 扩容)如何快速表示一个区间的累计信息。如何快速查找某个历史状态。前缀和哈希区间问题↓转化成两个前缀状态之间的关系↓。
2026-09-05 17:49:34
213
原创 C++ : 类 多态
同一个接口,在不同对象上表现出不同的行为。public:public:public:DogCatp1 的静态类型:Animal*p1 指向对象的动态类型:Dogp2 的静态类型:Animal*p2 指向对象的动态类型:CatAnimal*这就是动态多态。vptr虚指针(virtual pointer)它通常是对象中的一个隐藏指针,用于找到当前对象对应的虚函数相关信息。│ vptr │vptr指向某个与 Derived 动态类型对应的虚函数表。vptr。
2026-09-03 12:38:24
131
原创 C++ : 类 继承
继承允许一个类基于已有类建立新的类。已有的类称为基类(Base Class),新的类称为派生类(Derived Class)。d.eat();// 来自 Animald.bark();// Dog 自己Dog是一种Animal。也就是典型的。属于,这通常更适合使用组合(composition),而不是继承。这里存在经典问题。如果。
2026-09-03 12:37:12
226
原创 C++ : 类 封装
推荐回答:C++ 封装是将数据和操作数据的行为组织在类中,并通过publicprotectedprivate等访问控制机制限制外部访问,从而隐藏实现细节、保护对象状态并降低模块之间的耦合。C++ 封装││ │组织数据 控制访问│ │数据 + 相关行为 public / protected / private│ │↓隐藏实现细节↓保护对象状态↓降低模块耦合↓维护对象不变式。
2026-09-03 12:35:36
217
原创 C++ : 类
CPU 访问内存时,并不是完全随意地访问任意字节位置。不同类型通常有自己的对齐要求。int → 4 字节double → 8 字节struct A {int x;double y;offset 0offset 4offset 84 + 8 = 12C++ Class│↓一种用户自定义类型│↓ ↓Object对象 成员函数代码│ │↓ │实际占据对象内存 ││ │↓ ↓ │非static数据成员 padding ││ ││ │↓ ↓。
2026-09-02 17:24:15
185
原创 C++ : std::string
│││├── clear() ≠ 一定释放内存│├── shrink_to_fit() ≠ 强制缩容│├── 扩容策略不是标准固定的 2 倍│├── 现代实现通常有 SSO│├── string 可以包含 '\0'│├── size() 和 strlen() 不是一回事│├── c_str() 指针不是永久有效│├── data() / c_str() 都要考虑生命周期│├── string_view 不拥有数据│。
2026-09-02 11:26:05
98
原创 C++ : unordered_map
两个不同的 key,最终都落到了bucket[2]。这就叫哈希冲突(hash collision)。冲突不是“哈希函数写错了”才会出现。key 的可能数量 > bucket 的数量例如 key 可以有十亿种,而 bucket 只有一百个,那么不同 key 最终落到同一个 bucket 是必然事件。即使 key 数量没有超过 bucket 数量,只要映射空间和输入空间的关系不理想,也同样可能发生冲突。一般采用的是链式哈希(separate chaining)思路。
2026-09-02 11:11:13
169
原创 C++ : map
先不要急着理解红黑树。5030702040608050/ \30 70/ \ / \左子树所有节点 < 当前节点 < 右子树所有节点50/ \30 7030 < 5070 > 5030/ \20 4020 < 3040 > 30二叉搜索树(Binary Search Tree,BST)。因为红黑树本质上仍然是二叉搜索树。左子树 < 当前节点 < 右子树中序遍历(in-order traversal)得到的结果天然有序。50/ \30 70/ \ / \左↓根。
2026-09-02 11:10:16
134
原创 C++ : vector
原来:插入:为了给100345因此成本与后面的元素数量相关。在头部插入↓移动几乎所有元素↓O(n)所以vector随机访问尾部追加遍历批量处理而不是频繁的头部/中间插入。操作典型复杂度operator[]O(1)at()O(1)front()O(1)back()O(1)摊销 O(1)摊销 O(1)pop_back()O(1)insert()中间位置O(n)erase()中间位置O(n)clear()O(n)size()O(1)capacity()O(1)reserve()
2026-09-02 11:09:12
119
原创 C++ : 深拷贝、浅拷贝与移动语义(std::move / std::forward)
逐字节/逐成员地复制对象的内存内容,如果成员中包含指针,只拷贝指针的值(地址),不拷贝指针指向的实际数据。浅拷贝示意图:b1 b2 (浅拷贝之后)▼ ▼│ 同一块堆内存 │ ← b1和b2都指向这里,谁先析构就先释放,│ (100个int) │ 另一个的data_变成悬空指针不仅拷贝指针本身,还为新对象重新分配一块独立的内存,把原始数据完整复制过去,让两个对象的资源完全独立、互不影响。public:// 自定义拷贝构造函数,实现深拷贝// 真正复制数据内容。
2026-09-01 10:21:34
270
原创 C++ : 编译链接流程
理解链接阶段的报错,必须先分清声明(declaration)和定义(definition)// 声明:只是说"这个变量存在,类型是int",不分配内存// 定义:真正分配内存并赋初值// 声明:只是函数签名} // 定义:包含函数体,真正生成机器指令一个符号可以被声明多次(在多个文件里各自声明一次没有问题),但在整个程序范围内,只能被定义一次——这就是ODR(One Definition Rule,一次定义原则)。头文件里通常只放声明(函数原型、extern。
2026-09-01 10:21:10
251
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅