當然,我很樂意為您解釋 EuphoriaYan 在 zi2zi-pytorch
專案中 discriminators.py
檔案內的程式碼。這個檔案主要定義了用於 zi2zi
模型訓練的判別器 (Discriminators) 模型架構。
首先,再次強調判別器在 GANs (生成對抗網路) 中的核心作用。在 zi2zi
這個情境下,判別器的任務是區分輸入的圖像究竟是「真實的風格字體圖像」還是「由生成器所生成的風格字體圖像」。 判別器扮演著「警察」或「裁判」的角色,它會盡可能地辨識出哪些圖像來自真實資料,哪些是偽造的。 而生成器的目標則是盡力「欺騙」判別器,產生讓判別器難以分辨真偽的圖像。 透過生成器和判別器不斷地對抗和學習,最終目標是讓生成器能夠產生極度逼真的風格字體圖像。
現在,我們來深入解析 discriminators.py
檔案的程式碼。 您可以在這個連結找到程式碼: https://github.com/EuphoriaYan/zi2zi-pytorch/blob/master/model/discriminators.py
打開 discriminators.py
檔案後,您會發現它主要定義了以下幾個 class,這些 class 皆繼承自 torch.nn.Module
,表示它們是 PyTorch 的模型模組,且都扮演判別器的角色:
BasicDiscriminator(nn.Module)
: 基礎的判別器架構NLayerDiscriminator(nn.Module)
: N 層卷積的判別器PixelDiscriminator(nn.Module)
: 像素級別的判別器MultiscaleDiscriminator(nn.Module)
: 多尺度判別器
接下來,我將逐一解釋每個判別器類別的程式碼,說明其架構、參數和運作方式:
1. BasicDiscriminator(nn.Module)
: 基礎判別器
- 類別用途:
BasicDiscriminator
提供了一個非常基礎的判別器結構,通常作為一個簡單的 Baseline 或起點。 它的結構相對淺層,主要用於快速實驗和驗證想法。 __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_spect_norm=False, use_bias=True)
:BasicDiscriminator
的初始化函數,定義了模型的參數:input_nc
(int): 輸入圖像的通道數 (number of channels)。 判別器接收的輸入通常是真實或生成的風格字體圖像 (及其可能包含的條件資訊,如果有的話)。ndf
(int, default=64): 判別器基礎濾波器數量 (number of discriminator filters)。 類似於生成器的ngf
,ndf
控制了判別器網路的寬度。n_layers
(int, default=3): 判別器中卷積層的層數。 這個參數控制了判別器的深度。BasicDiscriminator
的結構相對簡單,層數不會太深。norm_layer
(nn.Module, default=nn.BatchNorm2d
): 正規化層 (normalization layer) 的類型。 預設使用nn.BatchNorm2d
。 與生成器類似,您可以選擇其他正規化層或不使用。use_spect_norm
(bool, default=False): 是否使用 Spectral Normalization (譜歸一化)。 在判別器中使用 Spectral Normalization 是非常常見的做法,它有助於穩定 GANs 的訓練,並能有效地控制判別器的 Lipschitz 常數,從而改善 GANs 的收斂性。BasicDiscriminator
預設不使用譜歸一化,但可以通過設定此參數啟用。use_bias
(bool, default=True): 卷積層是否使用 Bias (偏差) 項。 與生成器類似,預設為True
。
__init__
函數中,程式碼使用nn.Sequential
來建立判別器的網路層序列。BasicDiscriminator
的結構主要由 卷積層 (nn.Conv2d
)、正規化層 (norm_layer
) 和 LeakyReLU 激活函數 (nn.LeakyReLU
) 堆疊而成。 您會看到:sequence = [nn.Conv2d(input_nc, ndf, kernel_size=4, stride=2, padding=1)]
: 第一層卷積層,將輸入通道數input_nc
轉換為ndf
,並使用 4×4 的 kernel size, stride=2 和 padding=1。stride=2
實現了下採樣 (Downsampling),降低特徵圖的空間解析度。nf_mult = 1, nf_mult_prev = 1
: 初始化濾波器數量倍增因子nf_mult
和nf_mult_prev
。 這兩個變數用於控制後續卷積層的濾波器數量。- 卷積層迴圈 (Convolutional layers loop):
for n in range(1, n_layers):
這個迴圈建立 中間的卷積層。 迴圈迭代n_layers - 1
次,建立n_layers - 1
個卷積層。 在迴圈中:nf_mult_prev = nf_mult
: 更新nf_mult_prev
為上一次迴圈的nf_mult
值。nf_mult = min(2 ** n, 8)
: 計算當前層的濾波器數量倍增因子nf_mult
。 濾波器數量會隨著層數加深而倍增 (乘以 2),但最大不超過 8 倍。 這是為了控制判別器的寬度不會無限增長。sequence += [nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=4, stride=2, padding=1, bias=use_bias)]
: 卷積層,輸入通道數為ndf * nf_mult_prev
,輸出通道數為ndf * nf_mult
,同樣使用 4×4 kernel, stride=2, padding=1 進行下採樣。sequence += [norm_layer(ndf * nf_mult)]
: 正規化層 (norm_layer)。sequence += [nn.LeakyReLU(0.2, True)]
: LeakyReLU 激活函數 (LeakyReLU activation)。 LeakyReLU 是一種常用的 GANs 判別器激活函數,相比 ReLU,LeakyReLU 在輸入為負值時仍然有微小的梯度,有助於梯度傳播。
nf_mult_prev = nf_mult, nf_mult = min(2 ** n_layers, 8)
: 再次更新nf_mult_prev
和nf_mult
,用於最後一層卷積層。sequence += [nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=4, stride=1, padding=1, bias=use_bias)]
: 最後一層卷積層 (Last Convolutional Layer)。 與中間層類似,但stride=1
,不進行下採樣。 這一層通常用於在最後將特徵圖縮小到一個較小的尺寸,以便最終的輸出層進行判別。sequence += [norm_layer(ndf * nf_mult)], sequence += [nn.LeakyReLU(0.2, True)]
: 最後一層卷積層後,同樣接續正規化層和 LeakyReLU 激活函數。sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=4, stride=1, padding=1)]
: 輸出卷積層 (Output Convolutional Layer)。 將通道數從ndf * nf_mult
轉換為 1。 輸出通道數為 1 表示判別器最終的輸出是一個 單通道的特徵圖 (或可以理解為每個位置輸出一個值),這個特徵圖的每個位置的值代表了判別器對應輸入圖像區域的「真實性」判斷。
use_spect_norm
參數來控制是否在卷積層中應用 Spectral Normalization (譜歸一化)。 如果use_spect_norm=True
,則使用spectral_norm(layer)
函數對卷積層進行譜歸一化。spectral_norm
函數可能是zi2zi-pytorch
專案中定義的一個工具函數,用於實現譜歸一化操作 (您可以在util/
或其他工具檔案中尋找其定義)。 最後,self.model = nn.Sequential(*sequence)
將組裝好的網路層序列封裝到nn.Sequential
容器中,作為BasicDiscriminator
模型的model
屬性。forward(self, input)
:BasicDiscriminator
的前向傳播函數。 與生成器類似,非常簡單,直接將輸入input
傳遞給self.model
並返回self.model
的輸出。BasicDiscriminator
的輸出是一個 特徵圖 (feature map),其形狀取決於輸入圖像的尺寸和判別器的網路結構 (下採樣層數等)。 對於 PatchGAN 風格的判別器,輸出通常是一個較小的特徵圖,每個位置的值代表對應輸入圖像局部區域的真實性判斷。
2. NLayerDiscriminator(nn.Module)
: N 層卷積判別器
- 類別用途:
NLayerDiscriminator
類別是BasicDiscriminator
的一個更通用的版本。 它允許使用者 更靈活地控制判別器的層數 (n_layers
),從而調整判別器的深度和複雜度。 它的基本結構與BasicDiscriminator
相似,都是基於堆疊卷積層、正規化層和激活函數。 __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_spect_norm=False, use_bias=True)
:NLayerDiscriminator
的初始化函數,參數與BasicDiscriminator
完全相同,包括input_nc
,ndf
,n_layers
,norm_layer
,use_spect_norm
,use_bias
。n_layers
參數在這裡的作用更加突出,因為NLayerDiscriminator
的主要特點就是可以通過n_layers
參數來控制判別器的層數。NLayerDiscriminator
的__init__
函數程式碼結構與BasicDiscriminator
非常相似,主要區別在於類別名稱和類別描述。 它的網路層結構也是基於堆疊卷積層、正規化層和 LeakyReLU 激活函數,並使用nn.Sequential
組裝。 下採樣迴圈、濾波器數量倍增策略、最後一層卷積層和輸出卷積層的設計都與BasicDiscriminator
幾乎完全一致。NLayerDiscriminator
在功能上可以看作是BasicDiscriminator
的泛化版本,當n_layers=3
時,它們的網路結構應該是相同的。forward(self, input)
:NLayerDiscriminator
的前向傳播函數也與BasicDiscriminator
完全一致,將輸入傳遞給self.model
並返回輸出特徵圖。
3. PixelDiscriminator(nn.Module)
: 像素級別判別器
- 類別用途:
PixelDiscriminator
是一種 像素級別 (Pixel-wise) 的判別器。 與BasicDiscriminator
和NLayerDiscriminator
不同,PixelDiscriminator
並不會對輸入圖像進行多次下採樣,而是 主要關注於圖像的局部區域 (例如,一個 16×16 或 30×30 的 Patch)。PixelDiscriminator
的目標是判斷輸入圖像的每個局部區域 (或每個像素周圍的區域) 是真實的還是偽造的。 它通常用於對抗生成器產生 局部細節 (local details) 方面的不足。 __init__(self, input_nc, ndf=64, norm_layer=nn.BatchNorm2d, use_spect_norm=False, use_bias=True)
:PixelDiscriminator
的初始化函數,參數與前兩個判別器類似,包括input_nc
,ndf
,norm_layer
,use_spect_norm
,use_bias
。 注意PixelDiscriminator
沒有n_layers
參數,因為它的層數是固定的,結構相對簡單。 在__init__
函數中,PixelDiscriminator
的網路結構與前兩個判別器有明顯不同。 它使用較少的卷積層,且下採樣次數也更少,以保持對局部細節的敏感性。 您會看到:sequence = [nn.Conv2d(input_nc, ndf, kernel_size=1, stride=1, padding=0)]
: 第一層卷積層。 使用 1×1 的 kernel size 和 stride=1, padding=0。 1×1 卷積主要用於 通道數變換,並不會改變特徵圖的空間尺寸。sequence += [nn.LeakyReLU(0.2, True)]
: LeakyReLU 激活函數。sequence += [nn.Conv2d(ndf, ndf * 2, kernel_size=4, stride=2, padding=1, bias=use_bias)]
: 第二層卷積層。 使用 4×4 kernel, stride=2, padding=1 進行 第一次下採樣。 濾波器數量倍增為ndf * 2
。sequence += [norm_layer(ndf * 2)], sequence += [nn.LeakyReLU(0.2, True)]
: 正規化層和 LeakyReLU 激活函數。sequence += [nn.Conv2d(ndf * 2, 1, kernel_size=4, stride=1, padding=1, bias=use_bias)]
: 最後一層卷積層 (Output Convolutional Layer)。 將通道數從ndf * 2
轉換為 1。stride=1
,不進行下採樣。PixelDiscriminator
的輸出也是一個 單通道的特徵圖,但這個特徵圖的尺寸通常會比較大,接近輸入圖像的原始尺寸 (因為下採樣次數很少)。 特徵圖的每個位置的值可以理解為判別器對應輸入圖像 局部區域 (例如,感受野為 16×16 或 30×30 的區域) 的真實性判斷。
PixelDiscriminator
也使用了use_spect_norm
參數來控制是否使用 Spectral Normalization。 同樣,最後使用self.model = nn.Sequential(*sequence)
將網路層序列封裝。forward(self, input)
:PixelDiscriminator
的前向傳播函數。 與前兩個判別器類似,將輸入傳遞給self.model
並返回輸出特徵圖。PixelDiscriminator
的輸出特徵圖尺寸通常較大,接近輸入圖像尺寸,每個位置的值代表像素級別的真實性判斷。
4. MultiscaleDiscriminator(nn.Module)
: 多尺度判別器
- 類別用途:
MultiscaleDiscriminator
是一種 多尺度 (Multi-Scale) 或 多 Patch 大小 (Multi-Patch-Size) 的判別器。 它使用 多個不同尺度的判別器 (在zi2zi-pytorch
中,預設是 3 個,由num_D
參數控制) 並行地對輸入圖像進行判別。 每個尺度的判別器可能具有不同的網路深度和結構,但都旨在從 不同尺度 或 不同感受野 的角度來評估輸入圖像的真實性。MultiscaleDiscriminator
的目的是讓判別器能夠 更全面地捕捉圖像在不同尺度上的偽造痕跡,從而提升 GANs 的生成品質。 __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, num_D=3, use_spect_norm=False, use_bias=True)
:MultiscaleDiscriminator
的初始化函數,參數與NLayerDiscriminator
類似,但新增了一個關鍵參數num_D
:input_nc
,ndf
,n_layers
,norm_layer
,use_spect_norm
,use_bias
: 與NLayerDiscriminator
的參數意義相同。num_D
(int, default=3): 多尺度判別器的數量 (number of discriminators)。 預設值為 3,表示MultiscaleDiscriminator
會使用 3 個並行的判別器。
__init__
函數中,MultiscaleDiscriminator
並 沒有直接定義網路層序列,而是 建立了一個判別器列表self.submodels
。 它使用了 迴圈 (for 迴圈) 建立num_D
個判別器子模型:for i in range(num_D):
: 迴圈迭代num_D
次,建立num_D
個判別器子模型。netD_submodel = NLayerDiscriminator(...)
: 在迴圈內部,每次都實例化一個NLayerDiscriminator
物件。 這表示MultiscaleDiscriminator
的每個子模型都是一個NLayerDiscriminator
架構的判別器。 這些NLayerDiscriminator
子模型的參數 (例如input_nc
,ndf
,n_layers
,norm_layer
等) 可以通過MultiscaleDiscriminator
的參數統一設定。self.submodels.append(netD_submodel)
: 將實例化後的NLayerDiscriminator
子模型添加到self.submodels
列表中。
MultiscaleDiscriminator
的每個子模型都是一個獨立的NLayerDiscriminator
,它們具有相同的網路架構,但輸入數據可能有所不同 (因為是多尺度判別器)。forward(self, input)
:MultiscaleDiscriminator
的前向傳播函數。 與前幾個判別器不同,MultiscaleDiscriminator
的forward
函數需要處理 多個子模型 的前向傳播和輸出結果的彙整:result = []
: 初始化一個空列表result
,用於儲存每個子模型的輸出結果。downsample = nn.AvgPool2d(3, stride=2, padding=[1, 1], count_include_pad=False)
: 定義一個 平均池化層 (Average Pooling) 用於下採樣。for i in range(self.num_D):
: 迴圈迭代每個子模型。model_out = self.submodels[i](input)
: 將當前輸入input
(或下採樣後的input
) 傳遞給第i
個子模型self.submodels[i]
進行前向傳播。 得到第i
個子模型的輸出model_out
。result.append(model_out)
: 將子模型的輸出model_out
添加到result
列表中。if i != self.num_D - 1: input = downsample(input)
: 對輸入input
進行下採樣 (Average Pooling)。 除了最後一個子模型外,每次迴圈迭代後,都會使用平均池化層對輸入input
進行下採樣,降低輸入圖像的尺寸。 這就是MultiscaleDiscriminator
實現多尺度的關鍵: 每個子模型接收不同尺度的輸入圖像。 第一個子模型接收原始尺寸的輸入,第二個子模型接收下採樣一次後的輸入,第三個子模型接收下採樣兩次後的輸入,依此類推。 每個子模型在不同尺度上判別圖像的真實性。
return result
: 返回包含 所有子模型輸出結果的列表result
。MultiscaleDiscriminator
的輸出是一個列表,列表中的每個元素是 一個子模型的輸出特徵圖。 在計算 GANs 的損失函數時,通常需要將這些多尺度判別器的輸出結果都納入考慮。
總結 discriminators.py
檔案:
discriminators.py
檔案提供了多種不同架構的判別器模型,用於 zi2zi-pytorch
專案的 GANs 訓練:
BasicDiscriminator
: 基礎的、淺層的判別器,適合快速實驗和 Baseline 比較。NLayerDiscriminator
: 可控制層數的卷積判別器,提供了調整判別器深度的靈活性,是較常用的判別器類型。PixelDiscriminator
: 像素級別判別器,關注圖像局部細節的真實性,適用於需要生成細節豐富圖像的任務。MultiscaleDiscriminator
: 多尺度判別器,使用多個不同尺度的判別器並行判別,能更全面地捕捉圖像在不同尺度上的偽造痕跡,通常能提升 GANs 的生成品質,但計算成本也會更高。
在 zi2zi-pytorch
專案中,您可以根據您的具體任務需求和計算資源,選擇使用不同類型的判別器。 NLayerDiscriminator
和 MultiscaleDiscriminator
是更常用且功能更強大的選擇。 您可以通過調整這些判別器的參數 (例如 ndf
, n_layers
, num_D
, use_spect_norm
等),來進一步客製化判別器的網路結構,以達到最佳的訓練效果。
希望這個詳細的程式碼解釋能夠幫助您理解 zi2zi-pytorch
專案中 discriminators.py
檔案的內容和作用。 如果您還有其他關於 zi2zi-pytorch
專案或 GANs 模型的問題,歡迎隨時提出。
chatgpt 回答:
這裡是 zi2zi-pytorch
中 discriminators.py
的詳細解析,包括 PatchGAN 判別器 (NLayerDiscriminator
) 和 自適應歧視器 (MultiScaleDiscriminator
)。
📌 1️⃣ 主要結構
在 discriminators.py
中,定義了 兩種 GAN 判別器 (Discriminators):
NLayerDiscriminator
:基於 PatchGAN 的判別器,適用於影像轉換。MultiScaleDiscriminator
:多尺度 (Multi-Scale) 判別器,透過不同解析度進行評估,提升穩定性。
這些判別器的目標是判斷 輸入圖片是否為真實 (Real) 或生成 (Fake)。
📌 2️⃣ NLayerDiscriminator
(PatchGAN 判別器)
📜 程式碼
import torch
import torch.nn as nn
from torch.nn.utils import spectral_norm
class NLayerDiscriminator(nn.Module):
def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_spectral_norm=False):
super(NLayerDiscriminator, self).__init__()
kw = 4
padw = 1
sequence = [nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw), nn.LeakyReLU(0.2, True)]
nf_mult = 1
nf_mult_prev = 1
for n in range(1, n_layers):
nf_mult_prev = nf_mult
nf_mult = min(2 ** n, 8)
conv = nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=2, padding=padw, bias=False)
if use_spectral_norm:
conv = spectral_norm(conv)
sequence += [conv, norm_layer(ndf * nf_mult), nn.LeakyReLU(0.2, True)]
nf_mult_prev = nf_mult
nf_mult = min(2 ** n_layers, 8)
sequence += [nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw, bias=False)]
sequence += [norm_layer(ndf * nf_mult), nn.LeakyReLU(0.2, True)]
sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw)]
self.model = nn.Sequential(*sequence)
def forward(self, input):
return self.model(input)
📌 解析 NLayerDiscriminator
這是一個 PatchGAN 判別器,目標是針對 局部區域 (Patch) 進行判別,而不是整張圖片。
1️⃣ 第一層(輸入層)
- 使用 卷積層 (
Conv2d
) + LeakyReLU 進行特徵提取:
sequence = [nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw), nn.LeakyReLU(0.2, True)]
- 這一層 不使用批次正規化 (BatchNorm),避免影響梯度流。
2️⃣ 中間層
- 使用
n_layers-1
個卷積層,每層通道數倍增,直到 512 (8 × 64):
for n in range(1, n_layers):
conv = nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=2, padding=padw, bias=False)
if use_spectral_norm:
conv = spectral_norm(conv)
sequence += [conv, norm_layer(ndf * nf_mult), nn.LeakyReLU(0.2, True)]
- 使用
spectral_norm
(可選),提升訓練穩定性。
3️⃣ 最終判別層
- 兩個額外的 卷積層 進行判別:
sequence += [nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult, kernel_size=kw, stride=1, padding=padw, bias=False)]
sequence += [norm_layer(ndf * nf_mult), nn.LeakyReLU(0.2, True)]
sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw)]
- 最後的輸出是一個 1×Patch 矩陣,每個值表示該區域為真實 (
real
) 或偽造 (fake
)。
📌 3️⃣ MultiScaleDiscriminator
(多尺度判別器)
📜 程式碼
class MultiScaleDiscriminator(nn.Module):
def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, num_D=3, use_spectral_norm=False):
super(MultiScaleDiscriminator, self).__init__()
self.num_D = num_D
self.discriminators = nn.ModuleList()
for i in range(num_D):
self.discriminators.append(NLayerDiscriminator(input_nc, ndf, n_layers, norm_layer, use_spectral_norm))
self.downsample = nn.AvgPool2d(kernel_size=3, stride=2, padding=[1, 1], count_include_pad=False)
def forward(self, input):
result = []
downsampled_input = input
for D in self.discriminators:
result.append(D(downsampled_input))
downsampled_input = self.downsample(downsampled_input)
return result
📌 解析 MultiScaleDiscriminator
這是一個 多尺度判別器 (Multi-Scale Discriminator),其作用是 從不同解析度進行判別,提升模型的泛化能力。
1️⃣ 建立多個判別器
self.discriminators = nn.ModuleList()
for i in range(num_D):
self.discriminators.append(NLayerDiscriminator(input_nc, ndf, n_layers, norm_layer, use_spectral_norm))
- 這裡建立 num_D(默認 3)個
NLayerDiscriminator
,每個負責不同解析度的輸入。
2️⃣ 使用 AvgPool2d
進行下採樣
self.downsample = nn.AvgPool2d(kernel_size=3, stride=2, padding=[1, 1], count_include_pad=False)
- 每次輸入 經過一個判別器後,會進行 2×2 平均池化,讓下一個判別器處理 更低解析度 的版本。
3️⃣ 前向傳播
result = []
downsampled_input = input
for D in self.discriminators:
result.append(D(downsampled_input))
downsampled_input = self.downsample(downsampled_input)
return result
- 這樣,每個判別器都會對不同解析度的輸入進行評估,提升模型對不同尺寸細節的學習能力。
📌 4️⃣ 總結
判別器 | 作用 |
---|---|
NLayerDiscriminator | PatchGAN 判別器,適用於影像轉換 |
MultiScaleDiscriminator | 多尺度判別器,使用不同解析度提升穩定性 |
spectral_norm | 避免模式崩潰,提高穩定性 |
AvgPool2d | 在 MultiScaleDiscriminator 中進行 2×2 池化,讓低解析度版本也能參與訓練 |
這些判別器讓 zi2zi-pytorch 的 字體風格轉換 變得更加穩定,並能夠更好地捕捉不同尺度的特徵!🚀
deepseek 回答:
在 zi2zi-pytorch
專案中,discriminators.py
檔案實現了判別器(Discriminator)模型。判別器的目標是區分真實圖片和生成器生成的假圖片,從而幫助生成器改進生成質量。以下是對 discriminators.py
程式碼的詳細解釋:
檔案結構
discriminators.py
主要包含以下類別:
NLayerDiscriminator
:基於多層卷積的判別器模型。PixelDiscriminator
:基於像素級別的判別器模型(較少使用)。
1. NLayerDiscriminator
這是主要的判別器模型,基於多層卷積網路(Multi-Layer Convolutional Network)。
初始化函數 __init__
class NLayerDiscriminator(nn.Module):
def __init__(self, input_nc, ndf=64, n_layers=3, norm_layer=nn.BatchNorm2d, use_sigmoid=False):
super(NLayerDiscriminator, self).__init__()
if type(norm_layer) == functools.partial:
use_bias = norm_layer.func == nn.InstanceNorm2d
else:
use_bias = norm_layer == nn.InstanceNorm2d
kw = 4
padw = 1
sequence = [
nn.Conv2d(input_nc, ndf, kernel_size=kw, stride=2, padding=padw),
nn.LeakyReLU(0.2, True)
]
nf_mult = 1
nf_mult_prev = 1
for n in range(1, n_layers):
nf_mult_prev = nf_mult
nf_mult = min(2 ** n, 8)
sequence += [
nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
kernel_size=kw, stride=2, padding=padw, bias=use_bias),
norm_layer(ndf * nf_mult),
nn.LeakyReLU(0.2, True)
]
nf_mult_prev = nf_mult
nf_mult = min(2 ** n_layers, 8)
sequence += [
nn.Conv2d(ndf * nf_mult_prev, ndf * nf_mult,
kernel_size=kw, stride=1, padding=padw, bias=use_bias),
norm_layer(ndf * nf_mult),
nn.LeakyReLU(0.2, True)
]
sequence += [nn.Conv2d(ndf * nf_mult, 1, kernel_size=kw, stride=1, padding=padw)]
if use_sigmoid:
sequence += [nn.Sigmoid()]
self.model = nn.Sequential(*sequence)
- 參數說明:
input_nc
:輸入圖片的通道數(例如,灰度圖為 1,RGB 圖為 3)。ndf
:判別器的特徵圖數量(基數)。n_layers
:卷積層的數量。norm_layer
:正規化層(如 BatchNorm 或 InstanceNorm)。use_sigmoid
:是否在輸出層使用 Sigmoid 激活函數。- 結構說明:
- 第一層:一個卷積層,將輸入圖片轉換為特徵圖,並使用 LeakyReLU 激活函數。
- 中間層:多個卷積層,每層的特徵圖數量逐漸增加(
ndf * nf_mult
),並使用正規化層和 LeakyReLU 激活函數。 - 最後一層:一個卷積層,將特徵圖轉換為單一通道的輸出(用於判斷真假)。
- Sigmoid:可選的 Sigmoid 激活函數,將輸出限制在 [0, 1] 範圍內。
前向傳播 forward
def forward(self, input):
return self.model(input)
- 直接將輸入傳遞給模型並返回輸出。
2. PixelDiscriminator
這是一個較簡單的判別器模型,基於像素級別的卷積網路。
初始化函數 __init__
class PixelDiscriminator(nn.Module):
def __init__(self, input_nc, ndf=64, norm_layer=nn.BatchNorm2d, use_sigmoid=False):
super(PixelDiscriminator, self).__init__()
if type(norm_layer) == functools.partial:
use_bias = norm_layer.func == nn.InstanceNorm2d
else:
use_bias = norm_layer == nn.InstanceNorm2d
self.net = [
nn.Conv2d(input_nc, ndf, kernel_size=1, stride=1, padding=0),
nn.LeakyReLU(0.2, True),
nn.Conv2d(ndf, ndf * 2, kernel_size=1, stride=1, padding=0, bias=use_bias),
norm_layer(ndf * 2),
nn.LeakyReLU(0.2, True),
nn.Conv2d(ndf * 2, 1, kernel_size=1, stride=1, padding=0, bias=use_bias)
]
if use_sigmoid:
self.net += [nn.Sigmoid()]
self.net = nn.Sequential(*self.net)
- 參數說明:
input_nc
:輸入圖片的通道數。ndf
:判別器的特徵圖數量(基數)。norm_layer
:正規化層(如 BatchNorm 或 InstanceNorm)。use_sigmoid
:是否在輸出層使用 Sigmoid 激活函數。- 結構說明:
- 卷積層:使用 1×1 卷積核,對每個像素進行處理。
- 激活函數:使用 LeakyReLU 激活函數。
- 正規化層:在第二層卷積後使用正規化層。
- Sigmoid:可選的 Sigmoid 激活函數,將輸出限制在 [0, 1] 範圍內。
前向傳播 forward
def forward(self, input):
return self.net(input)
- 直接將輸入傳遞給模型並返回輸出。
總結
NLayerDiscriminator
:基於多層卷積的判別器,適用於大多數圖像生成任務。PixelDiscriminator
:基於像素級別的判別器,較少使用,適用於簡單任務。- 判別器的作用:區分真實圖片和生成器生成的假圖片,從而幫助生成器改進生成質量。
在 zi2zi-pytorch
專案中,NLayerDiscriminator
是主要的判別器模型,用於訓練生成器以生成高質量的字體風格轉換結果。通過調整參數(如 n_layers
和 ndf
),可以控制判別器的深度和複雜度。