自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(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​σW1​xb1​b2​其中第一层通常把维度从DDD扩大到DffD_{ff}Dff​Dff≈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.011​100Streaming 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 做加权聚合的机制。Attention⁡QKVsoftmax⁡QK⊤dkVAttentionQKVsoftmaxdk​​QK⊤​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∂y​X→Linear→Activation→Linear→L∂W1​∂L​∂b1​∂L​∂W2​∂L​∂b2​∂L​Autograd 的职责就是根据前向计算过程中发生的 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θLtotal​Ldata​λ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++ : new / delete / malloc / free

malloc。

2026-09-01 15:50:08 103

原创 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关注的人

提示
确定要删除当前文章?
取消 删除