杏杏 發表於 2025-12-30 21:14:00

吴恩达深度学习课程四:计算机视觉 第四周:卷积网络应用 (二) 图像风格转换

<p>此分类用于记录吴恩达深度学习课程的学习笔记,目前已完结,点击进入全集目录<br>
课程相关信息链接如下:</p>
<ol>
<li>原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai</li>
<li>github课程资料,含课件与笔记:吴恩达深度学习教学资料</li>
<li>课程配套练习(中英)与答案:吴恩达深度学习课后习题与答案</li>
</ol>
<p>本篇为第四课的第四周内容,4.6到4.11的内容,同时也是本篇理论部分的最后一篇。</p>
<hr>
<p>本周为第四课的第四周内容,这一课所有内容的中心只有一个:<strong>计算机视觉</strong>。应用在深度学习里,就是专门用来进行图学习的模型和技术,是在之前全连接基础上的“特化”,也是相关专业里的一个重要研究大类。<br>
<strong>这一整节课都存在大量需要反复理解的内容和机器学习、数学基础。</strong> 因此我会尽可能的补足基础,用比喻和实例来演示每个部分,从而帮助理解。<br>
第四周的内容是对前三周内容的综合应用,介绍了一些通过卷积网络实现的实际应用,它们在使用卷积网络的基础上又各有自己的特点来匹配不同的任务要求,是对<strong>如何真实应用卷积网络</strong>的良好演示。<br>
本篇的内容关于<strong>图像风格转换</strong>。</p>
<h1 id="1-什么是图像风格转换">1. 什么是图像风格转换?</h1>
<p>并不难理解,我们之前也提到过它,用课程里的例子来进行演示:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230210604629-1505817373.png" alt="image.png" loading="lazy"><br>
如图所示,使用图像风格转换,我们就可以把自己拍的照片在保证内容不变的同时,转换成名画,或者整蛊版的画风。这种应用更贴近我们的生活,在现在的手机应用里也十分普遍。<br>
现在就来看看如何实现图像风格转换。</p>
<h1 id="2-如何实现图像风格转换">2. 如何实现图像风格转换?</h1>
<p>我们已经不止一次提到,神经网络中的许多学习任务,本质上都可以抽象为一个<strong>优化问题</strong>:通过定义合适的目标函数,并借助梯度下降等方法,使优化目标不断减小,从而得到期望的结果。<br>
在监督学习中,这一过程通常表现为不断更新模型参数,以减小模型输出与标签之间的差异。</p>
<p>而在图像风格转换任务中,也沿用了同样的优化思想。<br>
此时,我们需要回答的关键问题是:<strong>如何度量内容图像与风格图像之间的差异,使生成结果在保持内容结构的同时,逐步逼近目标风格?</strong></p>
<p>答案就在于<strong>构造合适的代价函数</strong>。<br>
代价函数这个名字已经很久没有出现过了,我们先回顾一下损失函数和代价函数的概念:前者是<strong>单个</strong>样本输出和标签之间的差距,后者是<strong>训练集中所有</strong>样本输出和标签之间差距的平均值。<br>
但在实际工程实现和大量论文中,二者往往被混用,深度学习框架中也普遍使用 loss 来指代最终用于反向传播的优化目标。<br>
因此,虽然<strong>二者数学上可区分,但在实际工程上经常不区分</strong>,我们明白含义就好。</p>
<p>回到正题,在 2015 年,一篇名为A Neural Algorithm of Artistic Style的论文首次提出神经风格转换的概念。<br>
这篇论文的核心思想是:在<strong>固定预训练卷积神经网络参数</strong>的前提下,利用网络中间层特征,将图像的内容结构与风格统计进行显式分离,并通过在特征空间中最小化相应的代价函数,直接对输入图像进行优化,从而重构出一幅同时匹配内容与风格约束的图像。</p>
<p>简单来说,图像风格转换的代价函数被分成了两部分:<strong>内容代价函数和风格代价函数</strong>:</p>
<p></p><div class="math display">\[\mathcal{J}_{\text{total}}(G)
= \alpha \, \mathcal{J}_{\text{content}}(C,G)
+ \beta \, \mathcal{J}_{\text{style}}(S,G)
\]</div><p></p><p>其中,<span class="math inline">\(\mathcal{J}_{\text{content}}\)</span> 用于约束生成图像在高层特征空间中与内容图像保持一致,<span class="math inline">\(\mathcal{J}_{\text{style}}\)</span> 则通过统计特征相关性来刻画并匹配目标风格,<span class="math inline">\(\alpha\)</span> 与 <span class="math inline">\(\beta\)</span> 用于平衡内容与风格在生成结果中的相对重要性。</p>
<p>陈述偏学术,有些迷惑很正常,我们下面就来详细展开:</p>
<h2 id="21-图像风格转换的训练逻辑">2.1 图像风格转换的训练逻辑</h2>
<p>在刚刚说明神经风格转换的核心思想时,你可能注意到了一个细节:<strong>固定预训练卷积神经网络参数</strong>。<br>
这意味着,我们在优化的过程中<strong>不去改变网络本身的权重</strong>。<br>
那问题来了:如果网络不动,代价函数还能下降吗?答案是肯定的——关键在于<strong>优化的对象变了</strong>。</p>
<p>这便是神经风格转换的一个核心点:<strong>被优化的不是网络参数,而是生成图像本身</strong>。<br>
这是什么意思?我们展开说明:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230210605797-2058246293.png" alt="image.png" loading="lazy"><br>
如图所示,你会发现,在这套训练逻辑中,<strong>网络只是一个工具,就像一把已经刻好的尺子,只负责提取图像的内容和风格特征。</strong><br>
我们将生成图像输入网络,通过前向传播得到其内容特征和风格特征,再与内容图像和风格图像的预计算目标特征比较,得到代价函数。随后,<strong>通过梯度反向传播,更新生成图像像素,而网络参数保持固定。</strong><br>
这样一来,虽然网络不训练,我们仍然可以通过迭代优化生成图像,使其内容与风格逐步逼近目标。<br>
了解了基本的训练逻辑后,我们再来看看到底如何实现代价函数。</p>
<h2 id="22-内容代价函数">2.2 内容代价函数</h2>
<p>我们先来看看较为直观的内容代价函数:<span class="math inline">\(\mathcal{J}_{\text{content}}(C,G)\)</span><br>
顾名思义,这部分代价函数的作用是用来<strong>衡量生成图像和内容图像之间的差异</strong>,显然,我们希望这部分能最小化来保持图像内容不变。</p>
<p>如何实现这部分?<br>
我们知道,在卷积神经网络中,随着网络层数的增加,输出特征图的抽象程度逐渐提高:</p>
<ul>
<li><strong>浅层特征</strong>主要捕捉局部纹理和边缘信息</li>
<li><strong>深层特征</strong>则编码全局语义和高级抽象</li>
</ul>
<p>我们一般使用深层特征来进行分类或检测等任务,<strong>但如果直接使用深层特征来计算内容损失,虽然语义信息丰富,但局部结构可能丢失;如果只用浅层特征,又容易被细节干扰。</strong><br>
因此,我们通常选择<strong>中间层特征</strong>来计算内容代价,它既能反映图像的整体结构,又保留足够的局部信息,正好适合衡量生成图像与内容图像之间的差异。<br>
可以形象地理解为:我们不希望只对纹理“计较”,也不希望只看整体概念,而是找到一个<strong>中间尺度</strong>,既能保留结构,又不过于抽象。<br>
也就是说,我们让用来计算内容代价的两组特征向量的抽象程度维持在一个合适的程度,既不是简单的纹理,也不是全局语义,就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230210605054-1967661990.png" alt="image.png" loading="lazy"><br>
明白了这一点后,我们现在就来看看到底如何计算内容代价:<br>
并不复杂,一句话就可以说明:<strong>计算这两组向量中对应量差的平方和。</strong><br>
公式表示为:</p>
<p></p><div class="math display">\[\mathcal{J}_{\text{content}}(C,G)=|a^{(C)}-a^{(G)}|^2
\]</div><p></p><p>其中,<span class="math inline">\(l\)</span> 为我们选定的输出特征抽象程度合适的层级。<br>
你也可以加入归一化:</p>
<p></p><div class="math display">\[\mathcal{J}_{\text{content}}(C,G)=\frac{1}{2}|a^{(C)}-a^{(G)}|^2
\]</div><p></p><p>了解完计算方式后,我们来看一个实例加深一下印象:</p>
<p>假设我们在某一中间层得到的特征图如下:</p>
<ul>
<li>内容图像 <span class="math inline">\(C\)</span> 的特征向量:</li>
</ul>
<p></p><div class="math display">\(C)} =
\begin{bmatrix}
0.2 &amp; 0.5 &amp; 0.3 \\
0.1 &amp; 0.4 &amp; 0.6
\end{bmatrix}
\]</div><p></p><ul>
<li>生成图像 <span class="math inline">\(G\)</span> 的对应特征向量:</li>
</ul>
<p></p><div class="math display">\(G)} =
\begin{bmatrix}
0.1 &amp; 0.7 &amp; 0.2 \\
0.2 &amp; 0.3 &amp; 0.5
\end{bmatrix}
\]</div><p></p><p>代入内容代价公式计算:</p>
<p></p><div class="math display">\[\begin{aligned}
\mathcal{J}_{\text{content}}(C,G) &amp;= \frac{1}{2} \Big[
(0.1-0.2)^2 + (0.7-0.5)^2 + (0.2-0.3)^2 \\
&amp;\quad + (0.2-0.1)^2 + (0.3-0.4)^2 + (0.5-0.6)^2
\Big] \\
&amp;= \frac{1}{2} \Big[ 0.01 + 0.04 + 0.01 + 0.01 + 0.01 + 0.01 \Big] \\
&amp;= \frac{1}{2} \cdot 0.09 \\
&amp;= 0.045
\end{aligned}
\]</div><p></p><p>可以看到,这个值就表示生成图像在该层特征上与内容图像的差异。<strong>优化的目标就是让这个值尽量减小</strong>,从而让生成图像尽量保留原有内容结构。</p>
<p>这就是对内容代价的计算,下面我们继续看代价的另一部分:风格代价。</p>
<h2 id="23-风格代价函数">2.3 风格代价函数</h2>
<p>相比内容代价,风格代价显得就抽象了些。我们把这节分为几部分,来进行较详细的介绍。</p>
<h3 id="1量化风格">(1)量化风格</h3>
<p>显然,要计算风格代价的首要问题就在于:<strong>我们要如何量化一幅图像的“风格”?</strong></p>
<p>直觉上,风格并不取决于“画的是什么”,而更多体现在<strong>颜色搭配、纹理分布、笔触规律</strong>等整体视觉特征上,也就是说,**风格是一种“统计特性”,而不是依赖具体空间位置的结构信息。</p>
<p>因此,在计算风格代价时,我们需要一种统计方式:<strong>这种方式不关注具体的空间位置信息,而是聚焦于统计不同特征之间的相关性。</strong><br>
我们展开解释一下这句话,就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230210603103-954591223.png" alt="image.png" loading="lazy"><br>
进一步地,我们把这样一幅彩色图像输入卷积网络,随着网络传播,输出特征图的通道数也不断增加,这时,<strong>每一个通道都可以粗略地理解为网络从图像中提取到的一类特征响应</strong>,它们可能对应颜色、纹理、局部形状或更复杂的视觉模式。<br>
既然如此,不同特征通道之间自然也会存在某种统计上的关联关系,例如某些纹理特征往往与特定颜色分布同时出现,就像这样:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230210604011-1547261915.png" alt="image.png" loading="lazy"></p>
<p>因此,我们可以将一幅图像的风格,量化为<strong>其特征图中各通道之间的相关性统计</strong>。<br>
而同时,下一个就自然而然的产生:我们怎么统计各通道的相关性?</p>
<h3 id="2gram-矩阵">(2)Gram 矩阵</h3>
<p>在神经风格转换中,Gatys 等人选择使用 <strong>Gram Matrix(格拉姆矩阵)</strong> 来刻画特征通道之间的相关性。<br>
先不急着摆公式,我们来看看为什么 Gram 矩阵是一个合适的选择:<br>
我们刚刚提到过,如果某两类特征在同一幅图像中<strong>经常同时被强烈激活</strong>,那么我们就可以认为它们在统计意义上是“相关的”。<br>
而 Gram 矩阵做的事情正是这一点:它不关心这些特征在图像的哪个位置出现,而只关心——<br>
<strong>不同特征通道在整幅图像中是否倾向于一起出现,以及出现得有多强。</strong><br>
也就是说,Gram 矩阵刻画的是一种 <strong>“特征与特征之间的共现关系”</strong>。</p>
<p>了解了Gram 矩阵的作用后,我们先用人话解释一下Gram 矩阵的计算过程:<strong>对所有通道两两组合,计算其相同位置上两个元素乘积的和,作为 Gram 矩阵中以两通道索引为坐标处的值。</strong><br>
然后,来看公式:<br>
我们采用如下符号约定:</p>
<ol>
<li><span class="math inline">\(a_{i,j,k}^{}\)</span>:表示第 <span class="math inline">\(l\)</span> 层中,空间位置 <span class="math inline">\((i,j)\)</span> 处,第 <span class="math inline">\(k\)</span> 个通道的激活值。</li>
<li>特征图空间尺寸为 <span class="math inline">\(n_H^{} \times n_W^{}\)</span>,通道数为 <span class="math inline">\(n_C^{}\)</span>。</li>
</ol>
<p>在第 <span class="math inline">\(l\)</span> 层中,输出特征图 的 Gram 矩阵 <span class="math inline">\(G^{} \in \mathbb{R}^{n_C^{} \times n_C^{}}\)</span> 定义为:</p>
<p></p><div class="math display">\}=
\sum_{i=1}^{n_H^{}}
\sum_{j=1}^{n_W^{}}
a_{i,j,k}^{}   
a_{i,j,k'}^{}
\]</div><p></p><p>其中:</p>
<ul>
<li><span class="math inline">\(k, k'\)</span> 表示两个不同的特征通道。</li>
<li>对所有空间位置 <span class="math inline">\((i,j)\)</span> 求和,<strong>显式消除了空间位置信息</strong>。</li>
</ul>
<p>在实际计算中,通常会对 Gram 矩阵进行归一化:</p>
<p></p><div class="math display">\}=
\frac{1}{n_H^{} n_W^{}}
\sum_{i=1}^{n_H^{}}
\sum_{j=1}^{n_W^{}}
a_{i,j,k}^{}
a_{i,j,k'}^{}
\]</div><p></p><p>这样可以避免特征图尺寸变化对风格代价产生不必要的影响。</p>
<p>最后,我们发现:<strong>Gram 矩阵中的每一个元素 <span class="math inline">\(G_{k k'}^{}\)</span>,刻画的是第 <span class="math inline">\(k\)</span> 个特征与第 <span class="math inline">\(k'\)</span> 个特征在整幅图像中的共现强度,而不是它们出现的位置。</strong></p>
<p>我们补充一个实例:<br>
设第 <span class="math inline">\(l\)</span> 层共有 <span class="math inline">\(n_C^{} = 3\)</span> 个通道,每个通道的特征图大小为 <span class="math inline">\(2\times 2\)</span>,三个通道的特征图分别为:</p>
<p></p><div class="math display">\[\mathbf{F}_1^{} = \begin{bmatrix} 1 &amp; 2 \\ 0 &amp; 1 \end{bmatrix},\quad
\mathbf{F}_2^{} = \begin{bmatrix} 2 &amp; 1 \\ 1 &amp; 0 \end{bmatrix},\quad
\mathbf{F}_3^{} = \begin{bmatrix} 0 &amp; 1 \\ 2 &amp; 1 \end{bmatrix}.
\]</div><p></p><p>Gram 矩阵计算公式为:</p>
<p></p><div class="math display">\} = \sum_{i=1}^{2} \sum_{j=1}^{2} a_{i,j,k}^{} a_{i,j,k'}^{}.
\]</div><p></p><ol>
<li>计算对角项(通道自身的相关性)</li>
</ol>
<p></p><div class="math display">\[\begin{aligned}
G_{11}^{} &amp;= 1\cdot1 + 2\cdot2 + 0\cdot0 + 1\cdot1 = 1^2 + 2^2 + 0^2 + 1^2 = 6,\\
G_{22}^{} &amp;= 2\cdot2 + 1\cdot1 + 1\cdot1 + 0\cdot0 = 2^2 + 1^2 + 1^2 + 0^2 = 6,\\
G_{33}^{} &amp;= 0\cdot0 + 1\cdot1 + 2\cdot2 + 1\cdot1 = 0^2 + 1^2 + 2^2 + 1^2 = 6.
\end{aligned}
\]</div><p></p><ol start="2">
<li>计算非对角项(不同通道之间的相关性)</li>
</ol>
<p></p><div class="math display">\[\begin{aligned}
G_{12}^{} &amp;= 1\cdot2 + 2\cdot1 + 0\cdot1 + 1\cdot0 = 4,\\
G_{13}^{} &amp;= 1\cdot0 + 2\cdot1 + 0\cdot2 + 1\cdot1 = 3,\\
G_{23}^{} &amp;= 2\cdot0 + 1\cdot1 + 1\cdot2 + 0\cdot1 = 3.
\end{aligned}
\]</div><p></p><ol start="3">
<li>由于 Gram 矩阵是对称的:</li>
</ol>
<p></p><div class="math display">\} = G_{12}^{},\quad G_{31}^{} = G_{13}^{},\quad G_{32}^{} = G_{23}^{}.
\]</div><p></p><p>最终 Gram 矩阵即为:</p>
<p></p><div class="math display">\} =
\begin{bmatrix}
6 &amp; 4 &amp; 3 \\
4 &amp; 6 &amp; 3 \\
3 &amp; 3 &amp; 6
\end{bmatrix}.
\]</div><p></p><p>最终,这个 <span class="math inline">\(3 \times 3\)</span> 的 Gram 矩阵完整地刻画了三种特征在整幅图像中的两两共现关系,而完全不包含任何空间位置信息。<br>
到这一步,我们就实现了用一个矩阵来量化一幅图像的风格。</p>
<h3 id="3计算风格代价">(3)计算风格代价</h3>
<p>在成功实现对图像风格的量化后,我们便可以计算风格代价:<span class="math inline">\(\mathcal{J}_{\text{style}}(S,G)\)</span><br>
它的计算逻辑并不复杂:<strong>对生成图像 G 和风格图像 S 的Gram 矩阵中对相应位置元素做差并平方,最后求和。</strong><br>
为保证与特征图尺寸和通道数无关,我们通常会加入归一化。<br>
最终,它的公式是这样的:</p>
<p></p><div class="math display">\[\mathcal{J}_{\text{style}}^{}(S,G) = \frac{1}{(2 n_H^{} n_W^{} n_C^{})^2} \sum_{k=1}^{n_C^{}} \sum_{k'=1}^{n_C^{}} \big(G_{kk'}^{(S)} - G_{kk'}^{(G)}\big)^2
\]</div><p></p><p>再来演示一下:<br>
<img src="https://img2024.cnblogs.com/blog/3708248/202512/3708248-20251230211202414-382274127.png" alt="image" loading="lazy"><br>
值得注意的是,上述公式严格来说只是<strong>单层风格代价</strong>,因为我们只使用了网络中某一层输出的特征图。<br>
如果我们把图像传播到网络的多个卷积层,分别计算各层的 Gram 矩阵并得到对应的风格代价,再按权重加权求和,就得到<strong>多层风格代价</strong>:</p>
<p></p><div class="math display">\[\mathcal{J}_{\text{style}}(S,G) = \sum_{l} \lambda^{} \, \mathcal{J}_{\text{style}}^{}(S,G)
\]</div><p></p><ul>
<li><span class="math inline">\(\lambda^{}\)</span>:第 <span class="math inline">\(l\)</span> 层风格代价的权重,可根据需要调节。</li>
</ul>
<p>多层加权的好处是<strong>兼顾不同层次的风格特征</strong>:低层更偏向纹理和颜色,高层更偏向整体图案和结构,从而生成的图像风格更加自然丰富。</p>
<p>由此,我们便成功定义了可用于图像风格转换的代价函数,接下来就可以通过网络的反向传播实现风格转换。<br>
在本周的实践内容中,我们也会实际演示一下这种应用。</p>
<p>另外,在本周课程最后,吴恩达老师补充了一节对一维卷积和三维卷积的介绍。<br>
简单来说:一维卷积通常用于处理序列数据,例如时间序列或文本信号,它在序列方向上滑动卷积核,提取局部模式或特征。<br>
三维卷积则常用于处理视频或体数据,它在高度、宽度和时间(或深度)三个维度上同时滑动卷积核,从而能够捕捉空间和时间上的联合特征,适合分析动态场景或三维结构信息。<br>
我们就不再多展开这部分内容了,等遇到了它们的具体应用时,我们再详细介绍它们。</p>
<h1 id="4总结">4.总结</h1>
<table>
<thead>
<tr>
<th>概念</th>
<th>原理</th>
<th>比喻</th>
</tr>
</thead>
<tbody>
<tr>
<td>图像风格转换</td>
<td>利用预训练卷积神经网络提取图像内容和风格特征,通过优化生成图像使其内容保持不变、风格逼近目标图像</td>
<td>网络像一把刻好的尺子,生成图像像橡皮泥,通过不断调整橡皮泥使其符合尺子刻度</td>
</tr>
<tr>
<td>代价函数(总)</td>
<td>将内容代价与风格代价加权求和:<span class="math inline">\(\mathcal{J}_{\text{total}} = \alpha \mathcal{J}_{\text{content}} + \beta \mathcal{J}_{\text{style}}\)</span></td>
<td>衡量生成图像与目标图像“差距”的指标,越小越匹配</td>
</tr>
<tr>
<td>内容代价函数</td>
<td>衡量生成图像与内容图像在中间层特征空间的差异,通常使用平方和计算</td>
<td>找到“中间尺度”既保留结构,又不过于抽象,就像兼顾局部纹理与整体概念</td>
</tr>
<tr>
<td>内容特征选择</td>
<td>使用中间层特征,既保留全局结构,又不过分关注局部纹理</td>
<td>不希望只对纹理计较,也不希望只看整体概念</td>
</tr>
<tr>
<td>风格代价函数</td>
<td>利用Gram矩阵刻画各特征通道之间的相关性,通过平方差和加权求和计算</td>
<td>Gram矩阵像统计特征共现的表格,不关心位置,只关注不同特征同时出现的强度</td>
</tr>
<tr>
<td>Gram矩阵</td>
<td>对每对特征通道,在所有空间位置上求乘积并求和,归一化后得到</td>
<td>特征通道之间的“共现强度矩阵”,类似观察特征是否喜欢一起出现</td>
</tr>
<tr>
<td>单层 vs 多层风格代价</td>
<td>单层只考虑某一层特征,多层将多层风格代价加权求和,更全面捕捉风格</td>
<td>低层捕捉纹理与颜色,高层捕捉整体图案与结构</td>
</tr>
<tr>
<td>一维卷积</td>
<td>在序列方向上滑动卷积核,处理序列数据如时间序列或文本</td>
<td>像沿着时间轴观察和提取局部模式</td>
</tr>
<tr>
<td>三维卷积</td>
<td>在高、宽、深/时间三个维度上滑动卷积核,处理视频或体数据</td>
<td>像在空间和时间上同时观察动态或三维结构</td>
</tr>
</tbody>
</table><br><br>
来源:https://www.cnblogs.com/Goblinscholar/p/19423276
頁: [1]
查看完整版本: 吴恩达深度学习课程四:计算机视觉 第四周:卷积网络应用 (二) 图像风格转换