當然,我很樂意為您解釋 EuphoriaYan 在 zi2zi-pytorch
專案中 generators.py
檔案內的程式碼。這個檔案主要定義了用於 zi2zi 訓練的生成器 (Generators) 模型架構。
首先,讓我們先理解 generators.py
在整個 zi2zi-pytorch
專案中的角色。在基於生成對抗網路 (GANs) 的 zi2zi
模型中,生成器 的職責是學習如何從輸入 (例如,noise vector 或條件資訊) 生成目標圖片(在這個專案中,目標是風格化的漢字圖片)。 generators.py
這個檔案,顧名思義,就是負責定義各種不同的生成器網路結構,讓您可以根據不同的實驗需求選用不同的生成器模型。
現在,讓我們深入分析 generators.py
檔案內的程式碼。我會針對檔案中定義的幾個主要的生成器類別逐一解釋:
檔案路徑: https://github.com/EuphoriaYan/zi2zi-pytorch/blob/master/model/generators.py
打開 generators.py
檔案,您會看到它主要包含了以下幾個 class 定義,這些 class 都繼承自 torch.nn.Module
,表示它們都是 PyTorch 的模型模組:
ResnetGenerator(nn.Module)
: ResNet 架構的生成器UnetGenerator(nn.Module)
: UNet 架構的生成器
讓我們分別詳細解釋這兩個生成器類別的程式碼:
1. ResnetGenerator(nn.Module)
: ResNet 架構的生成器
- 類別用途:
ResnetGenerator
類別定義了一個基於 ResNet (Residual Network, 殘差網路) 架構的生成器。 ResNet 以其 殘差塊 (Residual Block) 結構聞名,這種結構有助於訓練非常深的網路,並能有效地減輕梯度消失的問題。 在 GANs 中使用 ResNet 架構的生成器是很常見的做法。 __init__(self, input_nc, output_nc, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, n_blocks=6, padding_type='reflect', use_spect_norm=False, use_bias=True)
:ResnetGenerator
類別的初始化函數,定義了生成器模型的各項參數:input_nc
(int): 輸入圖像的通道數 (number of channels)。 例如,灰度圖像為 1,RGB 圖像為 3。output_nc
(int): 輸出圖像的通道數。 通常與input_nc
相同。ngf
(int, default=64): 生成器基礎濾波器數量 (number of generator filters)。 這個參數控制了生成器網路的寬度。 例如,第一層卷積層的輸出通道數會是ngf
,後續層可能會倍增或減半。norm_layer
(nn.Module, default=nn.BatchNorm2d
): 正規化層 (normalization layer) 的類型。 預設使用nn.BatchNorm2d
(批次正規化)。 您也可以選擇其他正規化層,例如nn.InstanceNorm2d
或不使用正規化 (設定為None
)。use_dropout
(bool, default=False): 是否在模型中使用 Dropout 層。 Dropout 是一種正則化技術,有助於防止過擬合。n_blocks
(int, default=6): ResNet 殘差塊 (residual blocks) 的數量。 這個參數控制了 ResNet 生成器的深度。 數值越大,生成器越深。padding_type
(str, default=’reflect’): 卷積層使用的 Padding 類型。 常見的選項有'reflect'
,'replicate'
,'zero'
。'reflect'
反射填充通常在圖像生成任務中表現較好。use_spect_norm
(bool, default=False): 是否在卷積層和線性層中使用 Spectral Normalization (譜歸一化)。 Spectral Normalization 是一種用於穩定 GANs 訓練的技術,尤其在判別器 (Discriminator) 中常用。 在生成器中使用 Spectral Normalization 也可能對訓練穩定性有所幫助。use_bias
(bool, default=True): 卷積層是否使用 Bias (偏差) 項。 在卷積層後面接續 BatchNorm 的情況下,通常可以將卷積層的 bias 設定為False
,因為 BatchNorm 層本身有 affine parameters 可以起到類似 bias 的作用 (詳細原因在之前的問題中已解釋)。 但這裡預設為True
。
__init__
函數中,程式碼會根據這些參數建立 ResNet 生成器的網路層結構。 它使用了nn.Sequential
來組裝網路層,方便程式碼的組織和管理。 您會看到程式碼中定義了幾個關鍵的網路層序列:model = [nn.ReflectionPad2d(padding_size)]
: 最開始的 反射填充層 (ReflectionPad2d),用於在輸入圖像邊緣進行反射填充,以控制卷積運算後的圖像尺寸。model += [nn.Conv2d(input_nc, ngf, kernel_size=7, padding=0, bias=use_bias)],
: 第一層卷積層 (Conv2d),將輸入通道數input_nc
轉換為ngf
(基礎濾波器數量)。 使用 7×7 的大 kernel size 和 padding=0。model += [norm_layer(ngf)], model += [nn.ReLU(True)],
: 正規化層 (norm_layer) 和 ReLU 激活函數 (ReLU activation)。 ReLU 引入非線性。- 下採樣迴圈 (Downsampling loop):
for i in range(n_downsampling):
這個迴圈建立 下採樣 (Downsampling) 的網路層。 下採樣通過nn.Conv2d(nf, nf * 2, kernel_size=3, stride=2, padding=1, bias=use_bias)
來實現,卷積層的stride=2
可以將特徵圖的尺寸減半。 每次下採樣後,濾波器數量nf
會倍增 (nf *= 2
)。 同樣,每次下採樣後都會接續正規化層和 ReLU 激活函數。 - 殘差塊迴圈 (Residual Blocks loop):
for i in range(n_blocks):
這個迴圈建立 ResNet 殘差塊 (Residual Blocks)。 殘差塊是 ResNet 的核心組件,透過跳躍連接 (Skip Connection) 來改善深層網路的訓練。 程式碼中使用了ResnetBlock
類別來定義殘差塊 (這個ResnetBlock
類別可能在networks.py
或其他檔案中定義,這裡generators.py
檔案中並未直接定義ResnetBlock
的程式碼,但從程式碼調用方式可以推斷出存在ResnetBlock
類別)。 殘差塊的數量由n_blocks
參數控制。 - 上採樣迴圈 (Upsampling loop):
for i in range(n_downsampling):
這個迴圈建立 上採樣 (Upsampling) 的網路層。 上採樣通過nn.ConvTranspose2d(nf, nf // 2, kernel_size=3, stride=2, padding=1, output_padding=1, bias=use_bias)
來實現,轉置卷積層 (ConvTranspose2d) 可以將特徵圖的尺寸倍增。 每次上採樣後,濾波器數量nf
會減半 (nf //= 2
)。 同樣,每次上採樣後都會接續正規化層和 ReLU 激活函數。 model += [nn.ReflectionPad2d(padding_size)], model += [nn.Conv2d(ngf, output_nc, kernel_size=7, padding=0)], model += [nn.Tanh()]
: 最後的卷積層 (Conv2d) 和 Tanh 激活函數 (Tanh activation)。 最後的卷積層將濾波器數量恢復到output_nc
(輸出圖像的通道數)。nn.Tanh()
激活函數將輸出值限制在 [-1, 1] 之間,這在 GANs 訓練中,特別是與某些損失函數 (例如 Wasserstein GAN) 結合使用時,是很常見的做法。
self.model = nn.Sequential(*model)
將組裝好的網路層序列封裝到nn.Sequential
容器中,作為ResnetGenerator
模型的model
屬性。forward(self, input)
:ResnetGenerator
類別的前向傳播函數,定義了資料在模型中的傳播路徑。 非常簡單,直接將輸入input
傳遞給self.model
這個nn.Sequential
容器,並返回self.model
的輸出。 因為self.model
已經包含了整個 ResNet 生成器的網路結構,所以forward
函數的程式碼非常簡潔。
2. UnetGenerator(nn.Module)
: UNet 架構的生成器
- 類別用途:
UnetGenerator
類別定義了一個基於 UNet (U-Net) 架構的生成器。 UNet 是一種經典的 U-形 網路結構,最初被設計用於生物醫學圖像分割,但在圖像到圖像轉換 (Image-to-Image Translation) 任務中也表現出色,尤其擅長生成 高解析度、細節豐富 的圖像。 UNet 的關鍵特點是 跳躍連接 (Skip Connections),可以有效地將編碼器路徑的特徵信息傳遞到解碼器路徑,保留圖像的細節信息。 __init__(self, input_nc, output_nc, num_downs, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False, use_spect_norm=False, use_bias=True)
:UnetGenerator
類別的初始化函數,參數與ResnetGenerator
類似,但多了一個關鍵參數num_downs
:input_nc
,output_nc
,ngf
,norm_layer
,use_dropout
,use_spect_norm
,use_bias
: 與ResnetGenerator
的參數意義相同。num_downs
(int): UNet 架構中下採樣 (Downsampling) 的次數。 這個參數控制了 UNet 編碼器和解碼器路徑的深度。1 數值越大,UNet 越深。 UNet 的總層數會與num_downs
參數密切相關。
__init__
函數中,UnetGenerator
的網路結構是通過 遞迴 (Recursion) 的方式,使用UnetSkipConnectionBlock
這個 模組化 building block (建構模組) 來組建的。UnetSkipConnectionBlock
可能是zi2zi-pytorch
專案中定義的另一個類別,用於封裝 UNet 架構中的跳躍連接和卷積層結構 (您可以嘗試在networks.py
或其他檔案中搜尋UnetSkipConnectionBlock
的定義,以了解其具體程式碼)。 程式碼中首先定義了一個 最內層的UnetSkipConnectionBlock
(unet_block = UnetSkipConnectionBlock(..., innermost=True)
):innermost=True
表示這是 UNet 的最內層 block,通常也是編碼器路徑的最深層。 然後,使用 迴圈 (for 迴圈) 建立 中間層的UnetSkipConnectionBlock
(unet_block = UnetSkipConnectionBlock(..., submodule=unet_block)
): 迴圈迭代num_downs - 5
次 (如果num_downs
大於 5)。 關鍵之處在於submodule=unet_block
參數,這表示 當前建立的UnetSkipConnectionBlock
模組會將之前建立的unet_block
作為其內部子模組 (submodule),從而實現 UNet 架構的遞迴結構,不斷堆疊UnetSkipConnectionBlock
來加深網路。 接著,建立 最外層的UnetSkipConnectionBlock
(unet_block = UnetSkipConnectionBlock(..., outermost=True)
):outermost=True
表示這是 UNet 的最外層 block,通常也是解碼器路徑的最外層 (最接近輸出層)。 最後,與ResnetGenerator
類似,self.model = nn.Sequential(*model)
將組裝好的網路層序列 (實際上是一個UnetSkipConnectionBlock
的樹狀結構) 封裝到nn.Sequential
容器中。 在UnetGenerator
的__init__
函數中,並沒有顯式地看到類似nn.Conv2d
,nn.BatchNorm2d
,nn.ReLU
等基礎網路層的定義,這些基礎層的定義應該都封裝在了UnetSkipConnectionBlock
這個 building block 內部。forward(self, input)
:UnetGenerator
類別的前向傳播函數,同樣非常簡潔,直接將輸入input
傳遞給self.model
(也就是整個 UNet 網路結構),並返回self.model
的輸出。
總結 generators.py
檔案:
generators.py
檔案主要定義了兩種常用的圖像生成器架構:
ResnetGenerator
: 基於 ResNet 殘差塊的生成器,適合用於需要訓練深層網路的場景,並能有效提升訓練穩定性。UnetGenerator
: 基於 UNet 架構的生成器,特別擅長生成高解析度、細節豐富的圖像,適用於圖像到圖像轉換任務,例如 zi2zi 這種風格化字體生成。
這兩個生成器類別都提供了豐富的參數選項,可以讓您根據具體的任務需求和實驗目的,靈活地調整生成器的網路結構,例如調整網路的寬度 (ngf
)、深度 (n_blocks
, num_downs
)、正規化方式 (norm_layer
)、是否使用 Dropout 和 Spectral Normalization 等。
在 zi2zi-pytorch
專案中,您可以根據您的實驗需求,選擇使用 ResnetGenerator
或 UnetGenerator
作為 GAN 模型中的生成器部分。 如果您追求生成圖像的細節和高解析度,UnetGenerator
通常會是更好的選擇。 如果您需要訓練非常深的生成器,或者更關注訓練的穩定性,ResnetGenerator
可能更適合。 您也可以嘗試修改這些生成器類別的程式碼,例如調整網路層的數量、類型、激活函數、正規化方式等,以探索更適合您的 zi2zi 任務的模型架構。
chatgpt 回答:
這裡是對 zi2zi-pytorch
中 generators.py
代碼的詳細解析,包括 U-Net 生成器 (UnetGenerator
) 和 跳躍連接塊 (UnetSkipConnectionBlock
)。
📌 1️⃣ 主要結構
generators.py
定義了一個 U-Net 生成器 (UnetGenerator),其中包含 跳躍連接塊 (UnetSkipConnectionBlock),這些組件負責將字體影像轉換為不同風格。
該 U-Net 結構是 遞歸建構(Recursive Construction),透過 UnetSkipConnectionBlock
組合出完整的 Encoder-Decoder 結構,並加入 跳躍連接 (Skip Connection) 來保留特徵資訊。
📌 2️⃣ UnetGenerator
(U-Net 生成器)
📜 程式碼
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils import spectral_norm
class UnetGenerator(nn.Module):
def __init__(self, input_nc, output_nc, num_downs, ngf=64,
norm_layer=nn.BatchNorm2d, use_spectral_norm=False):
super(UnetGenerator, self).__init__()
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, norm_layer=norm_layer,
innermost=True, use_spectral_norm=use_spectral_norm)
for i in range(num_downs - 5):
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, submodule=unet_block,
norm_layer=norm_layer, use_spectral_norm=use_spectral_norm)
unet_block = UnetSkipConnectionBlock(ngf * 4, ngf * 8, submodule=unet_block,
norm_layer=norm_layer, use_spectral_norm=use_spectral_norm)
unet_block = UnetSkipConnectionBlock(ngf * 2, ngf * 4, submodule=unet_block,
norm_layer=norm_layer, use_spectral_norm=use_spectral_norm)
unet_block = UnetSkipConnectionBlock(ngf, ngf * 2, submodule=unet_block,
norm_layer=norm_layer, use_spectral_norm=use_spectral_norm)
self.model = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc,
submodule=unet_block, outermost=True, norm_layer=norm_layer,
use_spectral_norm=use_spectral_norm)
def forward(self, input):
return self.model(input)
📌 解析 UnetGenerator
這是一個 U-Net 生成器,由多個 UnetSkipConnectionBlock
遞歸組成。
1️⃣ 最內層 (innermost)
- 這是 U-Net 的最底層(瓶頸層),負責最深層的特徵提取:
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, norm_layer=norm_layer, innermost=True)
2️⃣ 中間層(regular layers)
- 透過 遞歸方式 建立多層的
UnetSkipConnectionBlock
:
for i in range(num_downs - 5):
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, submodule=unet_block, norm_layer=norm_layer)
3️⃣ 最外層 (outermost)
- 最外層負責最終的影像輸出,並使用
Tanh
作為激活函數:
self.model = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc,
submodule=unet_block, outermost=True)
📌 3️⃣ UnetSkipConnectionBlock
(U-Net 跳躍連接塊)
📜 程式碼
class UnetSkipConnectionBlock(nn.Module):
def __init__(self, outer_nc, inner_nc, input_nc=None, submodule=None, outermost=False,
innermost=False, norm_layer=nn.BatchNorm2d, use_spectral_norm=False):
super(UnetSkipConnectionBlock, self).__init__()
self.outermost = outermost
if input_nc is None:
input_nc = outer_nc
downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4, stride=2, padding=1, bias=False)
downrelu = nn.LeakyReLU(0.2, inplace=True)
downnorm = norm_layer(inner_nc)
uprelu = nn.ReLU(inplace=True)
upnorm = norm_layer(outer_nc)
if use_spectral_norm:
downconv = spectral_norm(downconv)
if outermost:
upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc, kernel_size=4, stride=2, padding=1)
model = [downconv, submodule, uprelu, upconv, nn.Tanh()]
elif innermost:
upconv = nn.ConvTranspose2d(inner_nc, outer_nc, kernel_size=4, stride=2, padding=1, bias=False)
model = [downrelu, downconv, uprelu, upconv, upnorm]
else:
upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc, kernel_size=4, stride=2, padding=1, bias=False)
model = [downrelu, downconv, downnorm, submodule, uprelu, upconv, upnorm]
self.model = nn.Sequential(*model)
def forward(self, x):
if self.outermost:
return self.model(x)
else:
return torch.cat([x, self.model(x)], 1) # 跳躍連接
📌 解析 UnetSkipConnectionBlock
這個類別負責構建 U-Net 的 Encoder-Decoder 結構,並透過 跳躍連接 (Skip Connection) 來保留特徵。
1️⃣ 定義卷積層
downconv
負責 下採樣 (Downsampling):
downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4, stride=2, padding=1, bias=False)
upconv
負責 上採樣 (Upsampling):
upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc, kernel_size=4, stride=2, padding=1, bias=False)
2️⃣ 加入 spectral_norm
(可選)
spectral_norm
有助於穩定 GAN 訓練,避免梯度爆炸:
if use_spectral_norm:
downconv = spectral_norm(downconv)
3️⃣ 處理不同 U-Net 層級
- 最外層 (
outermost
):Tanh()
作為最後輸出層:
model = [downconv, submodule, uprelu, upconv, nn.Tanh()]
- 最內層 (
innermost
):- 沒有跳躍連接,因為這是 U-Net 的最底層:
model = [downrelu, downconv, uprelu, upconv, upnorm]
- 中間層(Regular Layers):
- 加入
submodule
,透過遞歸方式建構 U-Net:
model = [downrelu, downconv, downnorm, submodule, uprelu, upconv, upnorm]
- 加入
4️⃣ 前向傳播
- 最外層:直接傳回模型輸出
- 其他層:拼接(Concatenate)跳躍連接輸入與輸出
if self.outermost:
return self.model(x)
else:
return torch.cat([x, self.model(x)], 1)
📌 4️⃣ 總結
組件 | 作用 |
---|---|
UnetGenerator | 透過 UnetSkipConnectionBlock 遞歸構建完整 U-Net |
UnetSkipConnectionBlock | 定義 Encoder-Decoder,每層透過 Skip Connection 傳遞特徵 |
spectral_norm | 穩定 GAN 訓練,避免模式崩潰 |
跳躍連接 (Skip Connection) | 保留細節特徵,避免資訊丟失 |
這個結構讓 zi2zi-pytorch 能夠 高效學習字體風格轉換 🚀!
deepseek 回答:
zi2zi-pytorch
是一個基於 PyTorch 實現的漢字風格轉換(Font Generation)專案,目標是將一種字體風格轉換為另一種字體風格。該專案的生成器(Generator)使用了 U-Net 架構,並在 generators.py
中實現。以下是对 generators.py
的程式碼詳細解釋:
檔案結構
generators.py
主要包含以下類別:
UnetSkipConnectionBlock
:實現 U-Net 的跳躍連接模組。UnetGenerator
:基於 U-Net 架構的生成器模型。
1. UnetSkipConnectionBlock
這是 U-Net 的基本構建塊,負責處理跳躍連接和特徵提取。
初始化函數 __init__
class UnetSkipConnectionBlock(nn.Module):
def __init__(self, outer_nc, inner_nc, input_nc=None,
submodule=None, outermost=False, innermost=False, norm_layer=nn.BatchNorm2d, use_dropout=False):
super(UnetSkipConnectionBlock, self).__init__()
self.outermost = outermost
if input_nc is None:
input_nc = outer_nc
downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4,
stride=2, padding=1)
downrelu = nn.LeakyReLU(0.2, True)
downnorm = norm_layer(inner_nc)
uprelu = nn.ReLU(True)
upnorm = norm_layer(outer_nc)
if outermost:
upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
kernel_size=4, stride=2,
padding=1)
down = [downconv]
up = [uprelu, upconv, nn.Tanh()]
model = down + [submodule] + up
elif innermost:
upconv = nn.ConvTranspose2d(inner_nc, outer_nc,
kernel_size=4, stride=2,
padding=1)
down = [downrelu, downconv]
up = [uprelu, upconv, upnorm]
model = down + up
else:
upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
kernel_size=4, stride=2,
padding=1)
down = [downrelu, downconv, downnorm]
up = [uprelu, upconv, upnorm]
if use_dropout:
model = down + [submodule] + up + [nn.Dropout(0.5)]
else:
model = down + [submodule] + up
self.model = nn.Sequential(*model)
- 參數說明:
outer_nc
:輸出特徵圖的通道數。inner_nc
:內部特徵圖的通道數。input_nc
:輸入特徵圖的通道數(如果未指定,則與outer_nc
相同)。submodule
:子模組,通常是另一個UnetSkipConnectionBlock
。outermost
:是否是最外層的模組。innermost
:是否是最內層的模組。norm_layer
:正規化層(如 BatchNorm)。use_dropout
:是否使用 Dropout 來防止過擬合。- 結構說明:
- 最外層(
outermost=True
):只包含一個卷積層和一個反卷積層,輸出使用Tanh
激活函數。 - 最內層(
innermost=True
):只包含卷積和反卷積層,沒有子模組。 - 中間層:包含卷積、反卷積和跳躍連接,並可以選擇是否使用 Dropout。
前向傳播 forward
def forward(self, x):
if self.outermost:
return self.model(x)
else:
return torch.cat([x, self.model(x)], 1)
- 跳躍連接:如果不是最外層,則將輸入
x
與經過模組處理的特徵圖拼接在一起(torch.cat
)。
2. UnetGenerator
這是基於 U-Net 架構的生成器模型。
初始化函數 __init__
class UnetGenerator(nn.Module):
def __init__(self, input_nc, output_nc, num_downs, ngf=64,
norm_layer=nn.BatchNorm2d, use_dropout=False):
super(UnetGenerator, self).__init__()
# 構建 U-Net 架構
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)
for i in range(num_downs - 5):
unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer, use_dropout=use_dropout)
unet_block = UnetSkipConnectionBlock(ngf * 4, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
unet_block = UnetSkipConnectionBlock(ngf * 2, ngf * 4, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
unet_block = UnetSkipConnectionBlock(ngf, ngf * 2, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
self.model = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc, submodule=unet_block, outermost=True, norm_layer=norm_layer)
- 參數說明:
input_nc
:輸入圖片的通道數(例如,灰度圖為 1,RGB 圖為 3)。output_nc
:輸出圖片的通道數。num_downs
:下採樣的次數(即 U-Net 的深度)。ngf
:生成器的特徵圖數量(基數)。norm_layer
:正規化層(如 BatchNorm)。use_dropout
:是否使用 Dropout。- 結構說明:
- 從最內層開始,逐步向外構建 U-Net 架構。
- 每一層的通道數逐漸增加(
ngf * 2
,ngf * 4
,ngf * 8
等)。 - 最外層的輸出通道數為
output_nc
。
前向傳播 forward
def forward(self, input):
return self.model(input)
- 直接將輸入傳遞給模型並返回輸出。
總結
UnetSkipConnectionBlock
:實現 U-Net 的跳躍連接,是 U-Net 的基本構建塊。UnetGenerator
:基於 U-Net 架構的生成器模型,用於將輸入圖片轉換為目標風格的圖片。- 跳躍連接:通過
torch.cat
實現,將低層次特徵傳遞到解碼器,以保留更多細節。
這個生成器模型是 zi2zi-pytorch
的核心組件,負責將一種字體風格轉換為另一種字體風格。通過調整參數(如 num_downs
和 ngf
),可以控制模型的深度和複雜度。