當然,我很樂意為您解釋 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),可以控制判別器的深度和複雜度。