免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Maths, CS AI Compendium 深度学习精讲:从 MLP、卷积与注意力到 Transformer、VAE 与生成模型

Maths, CS  AI Compendium 深度学习精讲:从 MLP、卷积与注意力到 Transformer、VAE 与生成模型 Maths, CS AI Compendium 深度学习精讲:从 MLP、卷积与注意力到 Transformer、VAE 与生成模型【免费下载链接】maths-cs-ai-compendiumBecome a cracked AI/ML researcher/engineer with this unconventional textbook covering maths, computing, and ML with intuition.项目地址: https://gitcode.com/GitHub_Trending/mat/maths-cs-ai-compendium本文基于 Maths, CS AI Compendium 第 06 章机器学习篇的 Deep Learning 一节,系统讲解深度为何有效、MLP 的前向计算与参数结构、五大激活函数的取舍、梯度消失/爆炸的成因与五类解法、权重初始化、四种归一化层,以及 CNN、RNN/LSTM、注意力机制、Transformer、ViT 与自编码器/VAE 的核心公式与直觉。读完并完成文末四个可运行的 JAX 编程任务后,你将能够从零实现 MLP 决策边界、1D 卷积、缩放点积注意力和 1D 瓶颈自编码器,并理解现代大模型架构的每一块积木。深度意味着什么:层级表示与组合性深度的定义很朴素:浅层网络只有一个隐藏层,深层网络有 Many 个。深度的真正价值在于层级表示(hierarchical representations):浅层学到简单特征(图像中的边缘、音频中的基频),深层再把它们组合成复杂概念(人脸、句子)。这种组合性(compositionality)正是深度学习能力的来源——每一层都在上一层抽象的词表上继续加工。这个观点贯穿全书:第 01 章的向量是基本表示单元,第 02 章的矩阵是线性变换,而深度网络就是把非线性逐层串接起来的复合变换。MLP:最简单也最基础的网络最简单的深度网络是多层感知机(MLP),又称全连接网/稠密网。每一层的计算都是:$$h \sigma(Wx b)$$其中 $W$ 是权重矩阵(第 02 章的矩阵乘法,$\mathbf{W} \in \mathbb{R}^{d_{\text{out}} \times d_{\text{in}}}$),$b$ 是偏置向量,$\sigma$ 是非线性激活函数。上一层的输出就是下一层的输入。为什么非线性不可省略?若 $\sigma$ 是线性的,则 $W_2(W_1 x) (W_2 W_1)x$——无论叠多少层都坍缩成一次矩阵乘法。这正是 第 02 章矩阵运算 中矩阵乘结合律的直接推论:没有非线性,深度在数学上不存在。参数量与批量计算一个输入维度 $d_{\text{in}}$、输出维度 $d_{\text{out}}$ 的稠密层共有 $d_{\text{in}} \times d_{\text{out}} d_{\text{out}}$ 个参数(权重加偏置)。$Wx$ 本质就是 第 02 章 的矩阵-向量乘。批量场景下输入是形状 $(B, d_{\text{in}})$ 的矩阵 $X$,输出为 $XW^T b$,形状 $(B, d_{\text{out}})$——一次矩阵乘法完成整个 batch 的前向传播。万能逼近定理:深度买的是效率万能逼近定理(universal approximation theorem)说:单隐层只要神经元足够多,就能以任意精度逼近紧致定义域上的任意连续函数。听起来深度似乎无所谓,但关键在于足够多这个代价:实践中,同样的函数用深层网络表示时参数量可以比浅层指数级更少。深度提供的不是能不能表示的表达力,而是用多少参数表示的效率。激活函数:让深度有意义的那一步激活函数 $\sigma$ 提供非线性。五种最常用的函数及其取舍如下:激活函数公式特点与适用场景ReLU$\text{ReLU}(x)\max(0,x)$最常用。计算快、正输入不饱和、输出稀疏(大量神经元恰好为 0)。缺点:输入恒为负的神经元永远输出 0,若卡死在那里就死亡停止学习(dead ReLU)Sigmoid$\sigma(x)\frac{1}{1e^{-x}}$压缩到 $(0,1)$,适合二分类输出层;隐层使用问题大——远离 0 的输入处曲线近乎平坦,梯度消失Tanh$\tanh(x)\frac{e^x-e^{-x}}{e^xe^{-x}}$压缩到 $(-1,1)$,零中心化(优于 sigmoid,利于梯度流动),但两端仍会梯度消失GELU$\text{GELU}(x)x\cdot\Phi(x)$$\Phi$ 为标准正态 CDF。ReLU 的光滑近似,允许小负值通过。GPT 与 BERT 的默认激活Swish$\text{Swish}(x)x\cdot\sigma(x)$另一种光滑门控,实践中与 GELU 表现相近从表中可以看出设计演化脉络:sigmoid/tanh 有界但两端饱和 → ReLU 解除正半轴饱和但负轴硬截断 → GELU/Swish 用概率门做平滑过渡。激活函数对梯度的影响,直接引出了下一节的梯度病态问题。梯度消失与梯度爆炸:深度网络的两大病理网络加深后,梯度必须经由链式法则(第 03 章微积分)穿过所有层回传,途中被逐层因子连乘:梯度消失(vanishing):若这些因子持续小于 1(sigmoid/tanh 饱和区就是典型),梯度指数级缩向 0,浅层几乎学不到东西。梯度爆炸(exploding):若因子持续大于 1,梯度指数级膨胀,导致数值溢出、训练不稳定。文档给出的五类解法,构成现代深度网络稳定训练的标准工具箱:用 ReLU / GELU 激活——正输入区梯度恒为 1,不饱和;谨慎的权重初始化(下一节);归一化层(再下一节);残差连接(skip connections,后文 ResNet 部分);梯度裁剪(gradient clipping)——对爆炸梯度,把梯度范数限制在某个上限内,配合 第 03 章优化 中的梯度下降使用。权重初始化:Xavier 与 He初始化决定训练起点处激活与梯度的尺度。权重太大 → 激活爆炸;太小 → 激活消失。两种经典方案:Xavier(Glorot)初始化:权重取方差为 $\frac{2}{d_{\text{in}} d_{\text{out}}}$ 的分布,在 tanh/线性激活假设下让激活方差跨层大致恒定;He(Kaiming)初始化:方差为 $\frac{2}{d_{\text{in}}}$,为 ReLU 专门标定——ReLU 会把约一半激活清零,所以需要两倍方差来补偿。经验法则:隐层用 tanh → Xavier;用 ReLU/GELU → He。文末任务 1 的代码里手动采用normal * 0.5的等价做法(小方差高斯),就是这一思想的简化版。归一化层:BatchNorm、LayerNorm、InstanceNorm、GroupNorm归一化层通过保证每层输入统计量一致(大致零均值、单位方差)来稳定训练。Batch Normalisation在batch 维度上归一化:对每个通道,计算 mini-batch 内所有样本的均值与方差后标准化,并引入可学习的缩放 $\gamma$ 和平移 $\beta$,让网络必要时可以撤销归一化:$$\hat{x} \frac{x - \mu_B}{\sqrt{\sigma_B^2 \epsilon}}, \quad y \gamma \hat{x} \beta$$它的两个固有缺陷:依赖 batch size——batch 太小则统计量噪声大;训练/推理不一致——推理时改用滑动均值(running averages)替代 batch 统计量,产生 train/test 差异。其余三种Layer Normalisation:对每个样本在特征维度上归一化,不依赖 batch 内其他样本,是Transformer 与循环网络的标准选择(下文的 Transformer 编码器块中每个子层后都有 Add LayerNorm);Instance Normalisation:对每个样本、每个通道在空间维度上独立归一化,风格迁移中很流行;Group Normalisation:把通道分组、组内归一化,是 LayerNorm 与 InstanceNorm 的折中,常用于小 batch 的 CNN。四种归一化的差异本质是在张量的哪几个轴上统计,可结合第 02 章的张量维度视角对照理解。Dropout:随机失活的正则化Dropout在训练时随机把比例 $p$ 的神经元置零,迫使网络不依赖任何单个神经元,鼓励冗余表示;测试时全部神经元激活。工程上的标准实现是inverted dropout:训练时把激活乘以 $\frac{1}{1-p}$ 补偿,这样测试时就不需要再做任何缩放——推理路径与训练路径的期望保持一致。CNN:用卷积取代全连接CNN 利用空间结构:不做每个输入连每个输出的稠密连接,而是让一个小滤波器(kernel)在输入上滑动,每个位置算一次点积。滤波器权重在所有位置共享——参数量大幅下降,同时天然引入平移不变性。卷积运算与输出尺寸2D 输入与 $k \times k$ 滤波器 $K$ 的卷积:$$(\text{input} * K)[i,j] \sum_{m0}^{k-1} \sum_{n0}^{k-1} \text{input}[im, jn] \cdot K[m, n]$$输出尺寸由三个超参数决定:Stride(步长):滤波器每两次计算之间移动的像素数,stride 2 把空间维度减半;Padding(填充):在输入边界补零。same 填充保持空间尺寸,valid 不补;输出尺寸公式:$\text{out} \lfloor (\text{in} - k 2p) / s \rfloor 1$。Pooling、空洞卷积与 1x1 卷积Pooling(池化):下采样特征图。max pooling 取窗口最大值,average pooling 取均值——在保留关键信息的同时压缩空间维度;Dilated convolution(空洞卷积):在滤波器元素之间插入间隔,扩大感受野而不增加参数。dilation rate 2 时,3x3 滤波器实际覆盖 5x5 区域;1x1 卷积:不看空间邻居,只在通道维度上混合信息——相当于在每个空间位置做一个稠密层,最常用于低成本地改变通道数。跳连与 ResNet:解决退化问题Skip connections(残差连接)让输入绕过若干层直接相加:$\text{output} F(x) x$。此时层只需学习残差 $F(x) \text{output} - x$,当最优变换接近恒等时任务变得容易。ResNet 正是靠这一技巧把网络叠到 100 层以上,解决了更深的网络反而比浅的差的退化问题——这也是梯度病态五解法中第 4 条的落地形式。层级特征体系CNN 构建特征层级:浅层检测边缘与纹理,中层组合出部件(眼睛、车轮),深层识别完整物体;同时感受野(某层神经元看得见的输入区域)随深度增大而扩大。卷积核滑动的几何过程可对照 第 08 章卷积网络 进一步深入(特征金字塔、检测、分割)。Embeddings 与分词:把离散符号变成向量Embedding把离散 token(词、字符、商品 ID)映射为稠密向量。Embedding 层就是一张查找表:矩阵 $E$,形状 (词表大小, 嵌入维度)。查 token $i$ 就是取 $E$ 的第 $i$ 行——数学上等价于乘一个 one-hot 向量,是 第 02 章 矩阵-向量乘的特例。Embedding 在训练中习得,相似 token 会收敛到相似向量。Tokenisation(分词)把原始文本切成 token 序列:词级分词按空格切,但无法处理未登录词;子词分词(BPE、WordPiece、SentencePiece)把文本拆成高频子词单元,在词表大小与覆盖率之间取平衡。如 unhappiness → [un, happiness] 或 [un, happ, iness]。RNN 与长序列困境RNN逐个处理序列,用一个隐状态向未来携带信息:$$h_t \tanh(W_h h_{t-1} W_x x_t b)$$$h_t$ 是对截至时刻 $t$ 所见到的一切的压缩摘要;$W_h$、$W_x$ 在所有时间步共享(与 CNN 共享空间权重同理)。vanilla RNN 的死穴:从 $t$ 到 $t-k$ 的梯度信号要连乘 $k$ 次 $W_h$,指数级缩小(或放大)。长距离依赖根本学不动。LSTM 与 GRU:门控解决长程依赖LSTM(长短期记忆网络)引入独立的细胞状态$c_t$,让它以极小干扰横贯时间轴,并用三个门控制信息的写入、保留与读出:遗忘门决定擦除什么:$f_t \sigma(W_f [h_{t-1}, x_t] b_f)$输入门决定写入什么:$i_t \sigma(W_i [h_{t-1}, x_t] b_i)$,候选值 $\tilde{c}_t \tanh(W_c [h_{t-1}, x_t] b_c)$细胞状态更新:$c_t f_t \odot c_{t-1} i_t \odot \tilde{c}_t$输出门决定暴露什么:$o_t \sigma(W_o [h_{t-1}, x_t] b_o)$,且 $h_t o_t \odot \tanh(c_t)$细胞状态如同传送带:当遗忘门持续接近 1 时,信息可以不经衰减地流过任意多个时间步——这就是 LSTM 破解长程梯度消失的机制。GRU(门控循环单元)把细胞状态与隐状态合并为同一个,用两个门替代三个门:更新门(合并遗忘门与输入门)与重置门。GRU 参数更少,效果常与 LSTM 相当。RNN 家族的终极局限是顺序处理:必须先算 token 1 再算 token 2,无法并行,且全部上下文必须挤过一个固定大小的隐状态——信息瓶颈。注意力机制正是为此而生。注意力机制:Q、K、V 与缩放点积注意力让模型不再把输入压缩成固定向量,而是对输出位置直接回看所有输入位置,决定哪些相关。现代公式用query(查询)、key(键)、value(值)三元组,类比图书馆检索:query 是你要找什么,key 是每本书的标签,value 是书的正文;用 query 对比所有 key,决定取哪些 value。缩放点积注意力(scaled dot-product attention):$$\text{Attention}(Q, K, V) \text{softmax}!\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$逐项拆解:$QK^T$ 是矩阵乘(第 02 章),元素是点积,即 第 01 章 意义上的余弦相似度度量;除以 $\sqrt{d_k}$ 防止点积过大导致 softmax 饱和成近似 one-hot、梯度消失;softmax 把相似度变成概率分布;乘 $V$ 得到值的加权和。多头注意力(multi-head attention)并行运行 $h$ 组注意力,各组使用不同的 Q/K/V 学习投影,让模型同时关注不同表示子空间(一个头管句法关系,另一个头管语义关系),输出拼接后再投影:$$\text{MultiHead}(Q, K, V) \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W^O$$Transformer:没有循环、全靠注意力Transformer(Vaswani et al., 2017)完全由注意力与前馈层构建,没有循环:编码器块重复:多头自注意力 → Add LayerNorm → 前馈网络 → Add LayerNorm(两个 Add 都是残差连接,见上节);解码器块额外加入掩码自注意力(mask 掉未来 token,防止偷看)与交叉注意力(attend 到编码器输出)。位置编码注意力是置换等变的:它把输入当作集合而非序列。没有位置信息,the cat sat on the mat 和 the mat sat on the cat 对它完全相同。原始 Transformer 用正弦位置编码:$$PE_{(pos, 2i)} \sin!\left(\frac{pos}{10000^{2i/d}}\right), \quad PE_{(pos, 2i1)} \cos!\left(\frac{pos}{10000^{2i/d}}\right)$$每个位置得到唯一向量,供模型区分位置;现代模型更多使用学习式位置嵌入或相对位置编码(RoPE、ALiBi)。复杂度与并行性Transformer 可全 token 并行($QK^T$ 一次矩阵乘算完整个自注意力矩阵),在现代硬件上训练远快于 RNN。代价是自注意力复杂度为序列长度的 $O(n^2)$(每个 token 关注每个 token),而 RNN 是 $O(n)$。这正是长上下文模型需要稀疏注意力、线性注意力、FlashAttention 等特殊变因的原因,也是第 16 章讨论 GPU 矩阵乘硬件加速(GPU 架构与 CUDA)的核心应用场景。ViT 与 MLP-Mixer:卷积和注意力都可选项吗?Vision Transformer(ViT)把 Transformer 用于图像:图像切成固定大小 patch(如 16x16),每个 patch 展平成向量当作一个 token;前置一个可学习 [CLS] token,其最终表示用于分类。ViT 完全没有卷积归纳偏置,却在数据量足够时追平或超过 CNN——再次印证深度买的是效率而非某种特定结构。MLP-Mixer更激进:注意力与卷积都用 MLP 替代,交替使用token 混合 MLP(跨空间位置)与通道混合 MLP(跨特征)。它同样有竞争力,提示现代架构的关键洞见或许不是注意力本身,而是高效地在 token 与特征之间混合信息。自编码器与 VAE:从压缩表示到生成模型自编码器(autoencoder)训练网络重建自己的输入:编码器把输入压到低维瓶颈(隐码),解码器再还原:$$z f_{\text{enc}}(x), \quad \hat{x} f_{\text{dec}}(z), \quad \mathcal{L} |x - \hat{x}|^2$$瓶颈强迫网络只保留最重要的特征。用途:降维、去噪(带噪输入重建干净输出)、异常检测(重建误差异常高 输入异常)。VAE(变分自编码器)加入概率视角:编码器不输出单点 $z$,而是输出分布参数(高斯均值 $\mu$ 与方差 $\sigma^2$),隐码从该分布采样:$z \mu \sigma \odot \epsilon$,其中 $\epsilon \sim \mathcal{N}(0, I)$。这个重参数化技巧(reparameterisation trick)让采样可微,梯度得以回传。VAE 损失有两项:$$\mathcal{L} \underbrace{|x - \hat{x}|^2}{\text{重建项}} \underbrace{D{\text{KL}}(q(z|x) | p(z))}_{\text{正则项}}$$第二项是 第 05 章信息论 定义的 KL 散度:它把学到的后验 $q(z|x)$ 推向先验 $p(z) \mathcal{N}(0, I)$,使隐空间平滑、结构良好。于是可以从先验直接采样并解码出新数据——这就是 VAE 成为生成模型的原理。文档还提及扩散模型(diffusion models)作为生成家族的延伸,其流程与训练目标可结合 第 08 章 的生图部分对照阅读。编程实战:四个可运行的 JAX 练习原文档附 4 个 CoLab/notebook 编程任务,下面完整保留。运行环境说明:本仓库自带浏览器端 notebook 运行器(pyodide-runner.js),从源码结构看:它通过 Pyodide(v0.27.7)预装numpy、matplotlib、micropip,并注入一个JAX shim——jax.numpy直接转发 numpy,jax.jit是恒等函数,jax.grad用 $10^{-5}$ 步长的中心有限差分近似,jax.nn.softmax是数值稳定版。因此在仓库内置 runner 中,任务 2、任务 3 可直接运行;任务 1、任务 4 依赖scikit-learn(需额外安装),且有限差分梯度在大参数规模下明显慢于真实 JAX 的自动微分,建议在 CoLab 等真实 JAX 环境运行全部四个任务。任务 1:从零实现 MLP 并可视化决策边界在 JAX 中手写一个 2→16→16→1 的两隐层 MLP,在同心圆二分类上训练(2000 步,学习率 0.1),并绘制决策边界:import jax import jax.numpy as jnp import matplotlib.pyplot as plt from sklearn.datasets import make_circles # Data X, y make_circles(n_samples500, noise0.1, factor0.5, random_state42) X, y jnp.array(X), jnp.array(y, dtypejnp.float32) # Initialise a 2-layer MLP: 2 - 16 - 16 - 1 def init_params(key): k1, k2, k3 jax.random.split(key, 3) return { W1: jax.random.normal(k1, (2, 16)) * 0.5, b1: jnp.zeros(16), W2: jax.random.normal(k2, (16, 16)) * 0.5, b2: jnp.zeros(16), W3: jax.random.normal(k3, (16, 1)) * 0.5, b3: jnp.zeros(1), } def forward(params, x): h jnp.maximum(0, x params[W1] params[b1]) # ReLU h jnp.maximum(0, h params[W2] params[b2]) # ReLU logit (h params[W3] params[b3]).squeeze() return jax.nn.sigmoid(logit) def loss_fn(params, X, y): pred forward(params, X) return -jnp.mean(y * jnp.log(pred 1e-7) (1 - y) * jnp.log(1 - pred 1e-7)) grad_fn jax.jit(jax.grad(loss_fn)) params init_params(jax.random.PRNGKey(0)) lr 0.1 for step in range(2000): grads grad_fn(params, X, y) params {k: params[k] - lr * grads[k] for k in params} # Plot decision boundary xx, yy jnp.meshgrid(jnp.linspace(-2, 2, 200), jnp.linspace(-2, 2, 200)) grid jnp.column_stack([xx.ravel(), yy.ravel()]) zz forward(params, grid).reshape(xx.shape) plt.figure(figsize(7, 6)) plt.contourf(xx, yy, zz, levels[0, 0.5, 1], alpha0.3, colors[#e74c3c, #3498db]) plt.scatter(X[y0,0], X[y0,1], c#e74c3c, s10, labelClass 0) plt.scatter(X[y1,0], X[y1,1], c#3498db, s10, labelClass 1) plt.title(MLP Decision Boundary on Concentric Circles) plt.legend(); plt.grid(alpha0.3); plt.show() acc jnp.mean((forward(params, X) 0.5) y) print(fAccuracy: {acc:.2%})要点对照:* 0.5的手动初始化即前文谨慎权重初始化的简化版;隐层 ReLU 对应梯度不饱和解法;损失为带 $10^{-7}$ 数值保护的二分类交叉熵。任务 2:从零实现 1D 卷积并与jnp.convolve对照手写 valid 模式的 1D 卷积,把边缘检测核[-1, 0, 1]作用在含阶跃变化的信号上,验证与内建jnp.convolve一致:import jax.numpy as jnp import matplotlib.pyplot as plt def conv1d(signal, kernel): 1D convolution (valid mode) from scratch. n, k len(signal), len(kernel) output jnp.zeros(n - k 1) for i in range(n - k 1): output output.at[i].set(jnp.sum(signal[i:ik] * kernel)) return output # Create a signal with a step function t jnp.linspace(0, 4, 200) signal jnp.where(t 1, 0.0, jnp.where(t 2, 1.0, jnp.where(t 3, 0.5, 1.5))) # Edge detection kernel edge_kernel jnp.array([-1.0, 0.0, 1.0]) # Our implementation vs built-in our_output conv1d(signal, edge_kernel) jnp_output jnp.convolve(signal, edge_kernel, modevalid) fig, axes plt.subplots(3, 1, figsize(10, 6), sharexTrue) axes[0].plot(t, signal, color#3498db, linewidth1.5) axes[0].set_title(Original Signal); axes[0].set_ylabel(Value) axes[1].plot(t[:len(our_output)], our_output, color#e74c3c, linewidth1.5) axes[1].set_title(After Edge Detection (our conv1d)); axes[1].set_ylabel(Value) axes[2].plot(t[:len(jnp_output)], jnp_output, color#27ae60, linewidth1.5, linestyle--) axes[2].set_title(After Edge Detection (jnp.convolve)); axes[2].set_ylabel(Value) axes[2].set_xlabel(t) plt.tight_layout(); plt.show() print(fOutputs match: {jnp.allclose(our_output, jnp_output)})输出长度 $n - k 1$ 正是前文输出尺寸公式在 1D、stride1、padding0 下的特例;$[-1, 0, 1]$ 核在信号跳变处给出尖峰——这就是浅层检测边缘的数学本质。任务 3:从零实现缩放点积注意力并可视化注意力矩阵对 4 个 token、嵌入维度 8 的随机 Q/K/V 计算注意力,并把权重矩阵画成热力图:import jax import jax.numpy as jnp import matplotlib.pyplot as plt def scaled_dot_product_attention(Q, K, V): Scaled dot-product attention. d_k Q.shape[-1] scores Q K.T / jnp.sqrt(d_k) weights jax.nn.softmax(scores, axis-1) output weights V return output, weights # Example: 4 tokens, embedding dim 8 key jax.random.PRNGKey(42) k1, k2, k3 jax.random.split(key, 3) seq_len, d_model 4, 8 Q jax.random.normal(k1, (seq_len, d_model)) K jax.random.normal(k2, (seq_len, d_model)) V jax.random.normal(k3, (seq_len, d_model)) output, weights scaled_dot_product_attention(Q, K, V) print(fQ shape: {Q.shape}) print(fAttention weights shape: {weights.shape}) print(fOutput shape: {output.shape}) print(f\nAttention weights (rows sum to 1):) print(weights) print(fRow sums: {weights.sum(axis-1)}) # Visualise attention fig, ax plt.subplots(figsize(5, 4)) im ax.imshow(weights, cmapBlues, vmin0, vmax1) ax.set_xlabel(Key position); ax.set_ylabel(Query position) ax.set_title(Attention Weights) tokens [tok 0, tok 1, tok 2, tok 3] ax.set_xticks(range(4)); ax.set_xticklabels(tokens) ax.set_yticks(range(4)); ax.set_yticklabels(tokens) for i in range(4): for j in range(4): ax.text(j, i, f{weights[i,j]:.2f}, hacenter, vacenter, fontsize10) plt.colorbar(im); plt.tight_layout(); plt.show()运行后会看到每行权重和恰为 1(softmax 约束),且权重矩阵为 $4 \times 4$——即 $O(n^2)$ 复杂度在 $n4$ 时的直观形态。任务 4:1D 瓶颈自编码器与隐空间可视化在 make_moons 数据上训练 2→8→1→8→2 的 tanh 自编码器(3000 步,学习率 0.01),用隐码给原始数据与重建数据着色:import jax import jax.numpy as jnp import matplotlib.pyplot as plt from sklearn.datasets import make_moons # Data X, _ make_moons(n_samples500, noise0.05, random_state42) X jnp.array(X) # Autoencoder: 2 - 8 - 1 - 8 - 2 def init_ae(key): k1, k2, k3, k4 jax.random.split(key, 4) return { enc_W1: jax.random.normal(k1, (2, 8)) * 0.5, enc_b1: jnp.zeros(8), enc_W2: jax.random.normal(k2, (8, 1)) * 0.5, enc_b2: jnp.zeros(1), dec_W1: jax.random.normal(k3, (1, 8)) * 0.5, dec_b1: jnp.zeros(8), dec_W2: jax.random.normal(k4, (8, 2)) * 0.5, dec_b2: jnp.zeros(2), } def encode(p, x): h jnp.tanh(x p[enc_W1] p[enc_b1]) return h p[enc_W2] p[enc_b2] def decode(p, z): h jnp.tanh(z p[dec_W1] p[dec_b1]) return h p[dec_W2] p[dec_b2] def ae_loss(p, X): z encode(p, X) X_hat decode(p, z) return jnp.mean((X - X_hat) ** 2) grad_fn jax.jit(jax.grad(ae_loss)) params init_ae(jax.random.PRNGKey(0)) lr 0.01 for step in range(3000): grads grad_fn(params, X) params {k: params[k] - lr * grads[k] for k in params} z encode(params, X) X_hat decode(params, Z) if False else decode(params, z) fig, axes plt.subplots(1, 2, figsize(12, 5)) axes[0].scatter(X[:,0], X[:,1], cz.squeeze(), cmapviridis, s10) axes[0].set_title(Original Data (coloured by latent code)) axes[1].scatter(X_hat[:,0], X_hat[:,1], cz.squeeze(), cmapviridis, s10) axes[1].set_title(Reconstruction from 1D bottleneck) for ax in axes: ax.set_aspect(equal); ax.grid(alpha0.3) plt.tight_layout(); plt.show() print(fReconstruction MSE: {ae_loss(params, X):.4f})训练后重建 MSE 收敛、隐码颜色在月牙上平滑渐变——直观看到瓶颈迫使网络学到数据的一维主方向。把它升级为输出 $(\mu, \sigma^2)$ KL 正则,就得到了前文的 VAE。延伸阅读:在 Compendium 中的衔接路径本节是全书的枢纽,各概念都有前后呼应,建议按以下路径深入:前置数学:第 02 章矩阵(稠密层即矩阵乘)、第 03 章链式法则与梯度下降、第 05 章信息论中的 KL 散度(VAE 损失的第二项);相邻章节:Gradient Machine Learning(训练视角)、Distributed Deep Learning(数据/张量并行);架构延伸:第 07 章 Transformers 与语言模型(GPT/LLM 全貌)、第 08 章卷积网络 与 Vision Transformers(视觉侧深化);硬件与实现:注意力/矩阵乘的硬件加速见 第 16 章 GPU 架构与 CUDA。本仓库以 MkDocs Material 主题发布(mkdocs.yml),数学公式经pymdownx.arithmatex与 MathJax(javascripts/mathjax.js)渲染,代码块可在内置 Pyodide runner 中直接执行——即本文公式与代码在站点上均为可交互形式,配合 llms.txt 亦可作为 LLM 的知识库入口。【免费下载链接】maths-cs-ai-compendiumBecome a cracked AI/ML researcher/engineer with this unconventional textbook covering maths, computing, and ML with intuition.项目地址: https://gitcode.com/GitHub_Trending/mat/maths-cs-ai-compendium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表