CV总结《一》

问题:

1.resnet

2.纹理,结构,语义;后面两个特征怎么理解

3.Stable Diffusion 是什么?

4.unet最底层bottlen bolck是干什么的,里面细节

5.diffusion里面的预测噪声网络,timestep怎么进去的?

1. ResNet 到底是什么?为什么需要它?

先不要看 ResNet,先想一个很朴素的问题。

假设我们想让神经网络识别猫。

最开始:

text 复制代码
图片
 ↓
卷积
 ↓
卷积
 ↓
分类

后来大家想:

网络是不是越深越厉害?

于是:

text 复制代码
10层
↓
20层
↓
50层
↓
100层

理论上,网络越深,表达能力应该越强。

但实际出现了一个奇怪现象:

网络加深之后,连训练集上的表现都变差了。

这不是过拟合。

因为过拟合通常是:

text 复制代码
训练集:很好
测试集:不好

而这里是:

text 复制代码
训练集:都变差了

这说明:

网络太深以后,优化变困难了。

这个现象叫:

Degradation Problem,退化问题。


一个特别通俗的例子

假设现在有一个 20 层网络,已经很好用了。

现在我非得再加 10 层。

理论上,这 10 层至少可以什么都不做,对吧?

比如:

text 复制代码
输入:猫的特征
 ↓
新加的10层
 ↓
还是原来的猫的特征

数学上就是:H(x)=x

这叫:

Identity Mapping,恒等映射。

也就是:

输入什么,输出什么。

听起来很简单。

但问题是:

让很多层卷积网络准确学成"什么都不改变",其实并没有想象中容易。


ResNet 的聪明之处来了

ResNet 说:

既然:H(x)=x

不好学,

那我干脆别让网络直接学:H(x)

而是让它学习:F(x)=H(x)-x

于是:H(x)=F(x)+x

这就是 ResNet 最核心的公式。


为什么这样反而容易?

如果最好的情况就是:H(x)=x

那么:F(x)=H(x)-x

所以:F(x)=0

也就是说:

普通网络需要学习:

"怎样把输入原封不动地复制出来?"

而 ResNet 只需要学习:

"我什么都别改,输出 0。"

通常:

学一个接近 0 的残差,比让很多层精确模拟 identity mapping 更容易。


什么叫"残差"?

这个词其实没有那么玄。

假设:

text 复制代码
原始输入 x = 100
希望得到 H(x) = 103

那么真正需要学习的变化只有:103-100=3

这个:3

就是 residual:

相对于原输入,需要修改多少。

所以 ResNet 的思路其实是:

不要重新生成所有东西,只学习"需要修改的那一小部分"。


ResNet Block 长什么样?

最简单的情况:

text 复制代码
             ┌──────────────────────┐
             │                      │
             │                      ▼
x ──→ Conv ─→ ReLU ─→ Conv ─────── (+) ─→ ReLU
             │                      ▲
             └──────────────────────┘

更准确地说:

text 复制代码
       ┌──────────── x ─────────────┐
       │                            │
       │                            ↓
x → Conv → BN → ReLU → Conv → BN → + → ReLU

上面那条直接从:

x

跑到最后的线就是:

Shortcut / Skip Connection

最后:

y=F(x)+x

其中:

text 复制代码
F(x)

就是两层卷积学习出来的变化。


ResNet 为什么还能帮助梯度传播?

text 复制代码
梯度
 ↓
门
 ↓
门
 ↓
门
 ↓
门
 ↓
前面

每经过一层都可能越来越小。

ResNet:

text 复制代码
                ────────────────
梯度 ←────────  快速通道
      ↑
     普通网络

所以 shortcut 不仅帮助 forward,也帮助 backward。


但有个问题

假如:x尺寸是:

text 复制代码
56 × 56 × 64

而 (F(x)) 是:

text 复制代码
28 × 28 × 128

你不能直接:x+F(x)

就像:

text 复制代码
3维向量 + 5维向量

没法加。

怎么办?

使用:1*1卷积。

例如:

text 复制代码
x
56×56×64
 ↓
1×1 Conv, stride=2
 ↓
28×28×128

然后:

text 复制代码
28×28×128
+
28×28×128

就能加了。

所以以后看到:

ResNet shortcut 上有一个 1×1 Conv

通常就是因为:

尺寸或者通道数对不上,需要 projection。


ResNet18 和 ResNet50 又是什么?

主要区别之一在 block。

ResNet18 常用:

text 复制代码
3×3 Conv
 ↓
3×3 Conv

叫:

BasicBlock。

ResNet50 常用:

text 复制代码
1×1
 ↓
3×3
 ↓
1×1

叫:

Bottleneck Block。

例如:

text 复制代码
256 channels
     ↓
1×1 Conv
     ↓
64 channels
     ↓
3×3 Conv
     ↓
64 channels
     ↓
1×1 Conv
     ↓
256 channels

为什么?

因为 3×3 卷积很贵。

先:

256\\rightarrow64

降低维度。

再进行 3×3。

最后恢复:

64\\rightarrow256

可以节约大量计算。


面试怎么回答 ResNet?

如果面试官问:

ResNet 为什么有效?

你不要只说:

防止梯度消失。

应该说:

深层普通网络会出现 degradation problem,即随着网络加深,训练误差反而升高。ResNet 通过 shortcut 将目标映射 (H(x)) 改成残差学习 (F(x)=H(x)-x),最终输出 (H(x)=F(x)+x)。当额外层不需要学习新信息时,只需要让 (F(x)) 接近 0,就可以实现 identity mapping,因此更加容易优化。同时 shortcut 也提供了直接的梯度传播路径,使深层网络更容易训练。

这就是比较完整的回答。


2. 纹理、结构、语义到底是什么?

这个非常重要。

我们还是拿:

举例。


第一层:纹理 Texture

纹理是很局部的。

比如:

text 复制代码
毛发
条纹
颗粒
草地细纹
砖墙纹路

你截一小块:

text 复制代码
///////
///////
///////

可能就能知道:

这里像毛发。

但你不知道:

这是猫还是狗。

所以:

纹理强调局部的重复模式和细节。


第二层:结构 Structure

结构比纹理更大尺度。

例如:

text 复制代码
猫耳朵的轮廓
眼睛的位置
脸的形状
车轮和车身的位置关系
建筑物边缘
人的手臂轮廓

例如只看到:

text 复制代码
   /\
  /  \

你可能觉得:

这像一个耳朵。

这已经不只是"毛发纹理"了。

而是在理解:

某些边缘是怎样组合在一起的。

所以:

结构是不同局部特征之间的空间组织关系。


第三层:语义 Semantic

语义就更高级。

语义是:

"这个东西是什么?"

例如:

text 复制代码
这是一只猫
这是一个人
这是汽车
这是天空
这是道路

注意。

猫可以:

text 复制代码
白猫
黑猫
花猫
短毛
长毛
坐着
躺着

纹理可能完全不同。

结构也会发生变化。

但:

语义依然是"猫"。

所以语义是:

对对象或者场景含义的抽象理解。


三个层次放一起

假设一张:

老虎图片。

低层 CNN:

text 复制代码
橙色
黑色条纹
边缘

这是:

纹理。

中层:

text 复制代码
耳朵
眼睛
四肢轮廓
脸部结构

这是:

结构。

高层:

text 复制代码
这是老虎

这是:

语义。


为什么 UNet 同时需要这些?

例如图像恢复。

输入是一张模糊猫图。

你既需要知道:

这里应该有毛发。

这是纹理。

也需要知道:

眼睛应该在哪,耳朵形状应该是什么。

这是结构。

还需要知道:

整体上这是猫,而不是桌子。

这是语义。

所以:

Encoder 越往下:

越偏结构和高级语义。

浅层:

更偏边缘、纹理和局部细节。

这就是为什么 UNet 要有 skip connection。


3. Stable Diffusion 是什么?

先一句话:

Stable Diffusion 是一种在"潜空间"里运行的文本条件扩散模型,可以根据文字生成图片。

例如你输入:

一只宇航员猫坐在月球上。

它生成图片。


普通 Diffusion

普通 diffusion 可以直接对图片进行:

text 复制代码
512×512×3

加噪、去噪。

但是图片非常大。

计算非常贵。


Stable Diffusion 的关键思想

不要直接在像素空间做 diffusion。

先把:

512\\times512\\times3

图片压缩成一个更小的 latent:

text 复制代码
512×512×3
    ↓ VAE Encoder
64×64×4

然后:

在 64×64×4 的 latent 上做 diffusion。

这就快很多。

所以 Stable Diffusion 属于:

Latent Diffusion Model,LDM。


Stable Diffusion 主要有三大部分

你先记:

text 复制代码
Text Encoder
+
VAE
+
UNet

① Text Encoder

例如:

"a cat wearing sunglasses"

先经过文本编码器。

得到:

text 复制代码
文本
 ↓
Text Encoder
 ↓
Text Embedding

把文字变成数字特征。

早期 Stable Diffusion 常用 CLIP Text Encoder。


② VAE

VAE 的作用:

图片空间 ↔ latent 空间。

Encoder:

text 复制代码
图片
 ↓
VAE Encoder
 ↓
latent

Decoder:

text 复制代码
latent
 ↓
VAE Decoder
 ↓
图片

Diffusion 不需要一直处理原始大图片。


③ UNet

真正负责:

预测噪声。

整个过程:

text 复制代码
随机噪声 latent
      ↓
    UNet
      ↓
去一点噪声
      ↓
    UNet
      ↓
再去一点
      ↓
...
      ↓
clean latent
      ↓
VAE Decoder
      ↓
图片

Text 怎么控制图片?

靠:

Cross Attention。

大致:

text 复制代码
UNet feature
     ↓
     Q

文本 embedding
     ↓
    K,V

然后做:

Attention(Q,K,V)

于是 UNet 在生成不同区域时会参考:

文本说了什么。

所以:

text 复制代码
"a red car"

和:

text 复制代码
"a blue dog"

会影响生成。


Stable Diffusion 总流程

你可以记这张:

text 复制代码
Prompt
  │
  ▼
Text Encoder
  │
Text Embedding
  │
  └──────────────┐
                 ▼
Random latent → UNet → 去噪 → UNet → 去噪 → ...
                 ▲
                 │
              timestep
                 │
                 ▼
             Clean latent
                 │
                 ▼
            VAE Decoder
                 │
                 ▼
               Image

这就是最基本的 Stable Diffusion。


4. UNet 最底层 Bottleneck 是干什么的?

很好,这个问题你开始问到 UNet 真正的内部了。

经典 UNet:

text 复制代码
Encoder
↓
↓
↓
Bottleneck
↑
↑
↑
Decoder

Bottleneck 就是:

U 最底部那一层。


为什么叫 Bottleneck?

因为这时候:

空间尺寸最小:

text 复制代码
H/8 × W/8

或者:

text 复制代码
H/16 × W/16

但是 channel 往往最多。

比如:

text 复制代码
输入:
256×256×3

↓

128×128×64

↓

64×64×128

↓

32×32×256

↓

16×16×512   ← Bottleneck

它到底干什么?

最重要的作用:

整合高层、全局的信息。

为什么?

因为经过连续下采样之后,一个位置对应原图很大一片区域。

所以它的 receptive field 很大。

在这里,网络看到的不再只是:

一个毛发。

而可能是:

猫的整张脸。

或者:

整体结构。


举例

浅层:

text 复制代码
这个位置有一条边。

再深一点:

text 复制代码
这些边组成一个耳朵。

Bottleneck:

text 复制代码
这里整体可能是一只猫。

然后 Decoder 利用这个高级信息:

把图逐渐恢复回来。


经典 UNet Bottleneck 里面是什么?

传统 UNet 通常类似:

text 复制代码
Conv 3×3
 ↓
BN / GroupNorm
 ↓
ReLU
 ↓
Conv 3×3
 ↓
BN / GroupNorm
 ↓
ReLU

如果是现代 diffusion UNet,则更复杂。

常见:

text 复制代码
ResBlock
   ↓
Attention
   ↓
ResBlock

为什么 Bottleneck 经常放 Attention?

因为空间已经很小。

例如原图:

512512
直接 self-attention:
262144个 token,非常贵。
但降到:32
32

只有:1024个位置。

这时候做 Attention 便宜很多。

而且 bottleneck 本来就是:

负责全局结构。

Attention 又特别适合:

建模长距离关系。

所以非常合适。


Diffusion UNet 的 Bottleneck 举个简化版本

text 复制代码
Encoder
  ↓
ResBlock
  ↓
Attention
  ↓
ResBlock
  ↓
────── Bottleneck ──────
  ↓
ResBlock
  ↓
Self-Attention / Cross-Attention
  ↓
ResBlock
  ↓
────── Decoder ─────────

在 Stable Diffusion 里面:

Cross Attention 还能把文本条件放进来。


5. Diffusion 预测噪声网络里,timestep 怎么进去?

这是一个非常重要的问题。

先解决:

为什么必须告诉 UNet 时间 (t)?


想象两个输入

一个:

x_{10}

只有一点噪声:

text 复制代码
🐱 还能明显看出猫

另一个:

x_{900}

已经几乎:

text 复制代码
████░▒▓░▒▓

全是噪声。

显然:

处理方法不能完全一样。

所以 UNet 必须知道:

"现在噪声进行到第几步了?"

也就是:t

最简单的想法

直接给 UNet 一个数字:

text 复制代码
t = 500

不太好。

为什么?

网络更擅长处理:

向量 embedding。

所以要把:

t

变成:

e_t

一个高维向量。

这叫:

Time Embedding / Timestep Embedding


第一步:把 t 编码

通常使用和 Transformer 类似的:

sinusoidal positional embedding。

比如:t=500

经过:

text 复制代码
Sinusoidal Embedding

变成:

text 复制代码
[0.21, -0.95, 0.53, 0.12, ...]

可能是:128维或者256维。

为什么不用单个数字?

因为 embedding 能够表达不同尺度的时间关系。

有点像给每一个:

text 复制代码
t=1
t=2
t=3
...

分配一个独特但连续变化的"身份证"。


第二步:经过 MLP

通常:

text 复制代码
t
 ↓
Sinusoidal Embedding
 ↓
Linear
 ↓
SiLU
 ↓
Linear
 ↓
Time embedding

比如最终:

e_t\\in\\mathbb R\^{512}


第三步:送到 UNet 的各个 ResBlock

注意:

timestep 不是只在输入的时候拼一次。

通常会送进很多个 ResBlock。

例如:

text 复制代码
          timestep
             ↓
        Time Embedding
             ↓
             ├──────────→ ResBlock1
             ├──────────→ ResBlock2
             ├──────────→ ResBlock3
             ├──────────→ Bottleneck
             ├──────────→ Decoder Block
             └──────────→ ...

所以整个 UNet 都知道:

我现在处于 t=500。


举一个具体数字

Feature:

text 复制代码
B × 128 × 64 × 64

Time embedding:

text 复制代码
B × 512

经过:

text 复制代码
Linear
512 → 128

得到:

text 复制代码
B × 128

reshape:

text 复制代码
B × 128 × 1 × 1

再:

text 复制代码
Feature
B×128×64×64

+

Time
B×128×1×1

broadcast:

text 复制代码
↓

B×128×64×64

所以相当于:

根据不同 timestep,给不同 channel 一个不同的偏置/调制。


一个简单的 Diffusion ResBlock

你以后在代码里面可能看到这种逻辑:

python 复制代码
h = conv1(x)

temb = linear(time_embedding)

h = h + temb[:, :, None, None]

h = conv2(h)

out = h + x

这是最容易理解的版本。


最后把五个问题串起来

你现在可以形成这一张图:

text 复制代码
                 Diffusion
                     │
                     │ x_t + timestep
                     ▼
                 ┌─────────┐
                 │  UNet   │
                 └─────────┘
                     │
       ┌─────────────┼─────────────┐
       │             │             │
       ▼             ▼             ▼
    Encoder      Bottleneck      Decoder
       │             │             │
  纹理/局部信息   全局结构/语义    恢复空间细节
       │             │             │
       └────── Skip Connection ────┘

UNet 内部很多 block
       │
       ▼
    ResBlock
       │
       ├──── ResNet 思想:F(x)+x
       │
       └──── timestep embedding 注入

而 Stable Diffusion 又是在这个基础上再加:

text 复制代码
Prompt
  ↓
Text Encoder
  ↓
Cross Attention
  ↓
Diffusion UNet

以及把 diffusion 从:

text 复制代码
pixel space

搬到了:

text 复制代码
latent space

所以你以后会发现:

ResNet → UNet → Attention → Diffusion → Stable Diffusion

根本不是五个零散知识点。

它们其实是一条完整的技术链。

相关推荐
阿图灵2 小时前
OpenCV 图像操作六件套:读取、裁剪、缩放、旋转、通道分割与保存
图像处理·人工智能·python·深度学习·opencv·计算机视觉
pjj198542 小时前
opencv-图像透视转换
人工智能·opencv·计算机视觉
浪兎兎2 小时前
【深度学习】(四)案例:基于PyTorch的全连接神经网络实现手机价格区间预测
pytorch·深度学习·神经网络
牧羊人.3332 小时前
计算机视觉基础 第 11 章| 特征检测与特征匹配
图像处理·人工智能·opencv·计算机视觉
EW Frontier2 小时前
【DOA估计】四根天线、一块SDR,神经网络把测向误差压进2度以内【附python代码】
人工智能·python·神经网络·doa估计·aoa估计
遥感知识服务13 小时前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
W_3260020 小时前
Python-OpenCV HSV颜色空间与inRange颜色分割:按颜色提取目标物体
图像处理·人工智能·python·opencv·机器学习
txg66621 小时前
可控扩散驱动模糊测试:CtrlFuzz 如何在“流形空间”中精准探索神经网络漏洞
人工智能·深度学习·神经网络
民乐团扒谱机1 天前
【微实验】物理启发神经网络(PINN):当AI学会遵守物理定律(附matlab代码))
人工智能·神经网络·matlab