程式碼解釋 github 專案 zi2zi-pytorch 作者是 EuphoriaYan, 程式碼 /model/discriminators.py

當然,我很樂意為您解釋 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 的模型模組,且都扮演判別器的角色:

  1. BasicDiscriminator(nn.Module): 基礎的判別器架構
  2. NLayerDiscriminator(nn.Module): N 層卷積的判別器
  3. PixelDiscriminator(nn.Module): 像素級別的判別器
  4. 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)。 類似於生成器的 ngfndf 控制了判別器網路的寬度。
    • 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_multnf_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_prevnf_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_biasn_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) 的判別器。 與 BasicDiscriminatorNLayerDiscriminator 不同,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 轉換為 1stride=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 的前向傳播函數。 與前幾個判別器不同,MultiscaleDiscriminatorforward 函數需要處理 多個子模型 的前向傳播和輸出結果的彙整:
    • 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: 返回包含 所有子模型輸出結果的列表 resultMultiscaleDiscriminator 的輸出是一個列表,列表中的每個元素是 一個子模型的輸出特徵圖。 在計算 GANs 的損失函數時,通常需要將這些多尺度判別器的輸出結果都納入考慮。

總結 discriminators.py 檔案:

discriminators.py 檔案提供了多種不同架構的判別器模型,用於 zi2zi-pytorch 專案的 GANs 訓練:

  • BasicDiscriminator: 基礎的、淺層的判別器,適合快速實驗和 Baseline 比較。
  • NLayerDiscriminator: 可控制層數的卷積判別器,提供了調整判別器深度的靈活性,是較常用的判別器類型。
  • PixelDiscriminator: 像素級別判別器,關注圖像局部細節的真實性,適用於需要生成細節豐富圖像的任務。
  • MultiscaleDiscriminator: 多尺度判別器,使用多個不同尺度的判別器並行判別,能更全面地捕捉圖像在不同尺度上的偽造痕跡,通常能提升 GANs 的生成品質,但計算成本也會更高。

zi2zi-pytorch 專案中,您可以根據您的具體任務需求和計算資源,選擇使用不同類型的判別器。 NLayerDiscriminatorMultiscaleDiscriminator 是更常用且功能更強大的選擇。 您可以通過調整這些判別器的參數 (例如 ndf, n_layers, num_D, use_spect_norm 等),來進一步客製化判別器的網路結構,以達到最佳的訓練效果。

希望這個詳細的程式碼解釋能夠幫助您理解 zi2zi-pytorch 專案中 discriminators.py 檔案的內容和作用。 如果您還有其他關於 zi2zi-pytorch 專案或 GANs 模型的問題,歡迎隨時提出。


chatgpt 回答:

這裡是 zi2zi-pytorchdiscriminators.py 的詳細解析,包括 PatchGAN 判別器 (NLayerDiscriminator)自適應歧視器 (MultiScaleDiscriminator)


📌 1️⃣ 主要結構

discriminators.py 中,定義了 兩種 GAN 判別器 (Discriminators)

  1. NLayerDiscriminator:基於 PatchGAN 的判別器,適用於影像轉換。
  2. 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️⃣ 總結

判別器作用
NLayerDiscriminatorPatchGAN 判別器,適用於影像轉換
MultiScaleDiscriminator多尺度判別器,使用不同解析度提升穩定性
spectral_norm避免模式崩潰,提高穩定性
AvgPool2dMultiScaleDiscriminator 中進行 2×2 池化,讓低解析度版本也能參與訓練

這些判別器讓 zi2zi-pytorch字體風格轉換 變得更加穩定,並能夠更好地捕捉不同尺度的特徵!🚀


deepseek 回答:

zi2zi-pytorch 專案中,discriminators.py 檔案實現了判別器(Discriminator)模型。判別器的目標是區分真實圖片和生成器生成的假圖片,從而幫助生成器改進生成質量。以下是對 discriminators.py 程式碼的詳細解釋:


檔案結構

discriminators.py 主要包含以下類別:

  1. NLayerDiscriminator:基於多層卷積的判別器模型。
  2. 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_layersndf),可以控制判別器的深度和複雜度。

About the author

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *