__all__
Resolution
module-attribute
Resolution = Literal[
4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192
]
__all__
module-attribute
__all__ = [
"Discriminator",
"Generator",
"Resolution",
"default_channels",
"Blur",
"EqualConv2d",
"EqualLeakyReLU",
"EqualLinear",
"d_loss",
"d_reg_loss",
"g_loss",
"g_reg_loss",
]
__author__
module-attribute
__author__ = 'Peter Yuen'
__email__
module-attribute
__email__ = 'ppeetteerrsx@gmail.com'
__version__
module-attribute
__version__ = '0.0.0'
default_channels
module-attribute
default_channels: Dict[Resolution, int] = {
4: 512,
8: 512,
16: 512,
32: 512,
64: 512,
128: 256,
256: 128,
512: 64,
1024: 32,
}
Blur
Blur(blur_kernel: List[int], factor: int, kernel_size: int)
Bases: nn.Module
Upsample (factor > 0)
Applied after a transpose convolution of stride U and kernel size K
Apply blurring FIR filter (before / after) a (downsampling / upsampling) op
Parameters:
Name | Type | Description | Default |
---|---|---|---|
input |
Tensor
|
(N, C, (H - 1) * U + K - 1 + 1, (W - 1) * U + K - 1 + 1) |
required |
blur_kernel |
Tensor
|
FIR filter |
required |
factor |
int
|
U. Defaults to 2. |
required |
kernel_size |
int
|
K. Defaults to 3. |
required |
Returns:
Name | Type | Description |
---|---|---|
Tensor | (N, C, H * U, W * U) |
Downsample (factor < 0)
Applied before a convolution of stride U and kernel size K
Parameters:
Name | Type | Description | Default |
---|---|---|---|
input |
Tensor
|
(N, C, H, W) |
required |
blur_kernel |
Tensor
|
FIR filter |
required |
factor |
int
|
U. Defaults to 2. |
required |
kernel_size |
int
|
K. Defaults to 3. |
required |
Returns:
Name | Type | Description |
---|---|---|
Tensor | (N, C, H - (U + 1) + K - 1, H - (U + 1) + K - 1) |
Source code in stylegan2_torch/equalized_lr.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
|
__call__
class-attribute
__call__ = proxy(forward)
kernel
instance-attribute
kernel: Tensor = None
pad
instance-attribute
pad = (pad0, pad1)
forward
forward(input: Tensor) -> Tensor
Source code in stylegan2_torch/equalized_lr.py
171 172 |
|
Discriminator
Discriminator(
resolution: Resolution,
channels: Dict[Resolution, int] = default_channels,
blur_kernel: List[int] = [1, 3, 3, 1],
)
Bases: nn.Module
Discriminator module
Source code in stylegan2_torch/discriminator/__init__.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
__call__
class-attribute
__call__ = proxy(forward)
blocks
instance-attribute
blocks = nn.Sequential(
ConvBlock(1, channels[resolution], 1),
[
ResBlock(
channels[2**i],
channels[2**i - 1],
blur_kernel,
)
for i in range(self.n_layers, 2, -1)
],
)
final_conv
instance-attribute
final_conv = ConvBlock(channels[4] + 1, channels[4], 3)
final_linear
instance-attribute
final_linear = EqualLinear(channels[4], 1)
final_relu
instance-attribute
final_relu = EqualLeakyReLU(
channels[4] * 4 * 4, channels[4]
)
n_layers
instance-attribute
n_layers = int(math.log(resolution, 2))
stddev_feat
instance-attribute
stddev_feat = 1
stddev_group
instance-attribute
stddev_group = 4
forward
forward(input: Tensor, *, return_features: bool = False)
Source code in stylegan2_torch/discriminator/__init__.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
|
EqualConv2d
EqualConv2d(
in_channel: int,
out_channel: int,
kernel_size: int,
stride: int = 1,
padding: int = 0,
bias: bool = True,
)
Bases: nn.Module
Conv2d with equalized learning rate
Source code in stylegan2_torch/equalized_lr.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
__call__
class-attribute
__call__ = proxy(forward)
bias
instance-attribute
bias = Parameter(torch.zeros(out_channel)) if bias else None
padding
instance-attribute
padding = padding
scale
instance-attribute
scale = 1 / math.sqrt(in_channel * kernel_size ** 2)
stride
instance-attribute
stride = stride
weight
instance-attribute
weight = Parameter(
torch.randn(
out_channel, in_channel, kernel_size, kernel_size
)
)
__repr__
__repr__() -> str
Source code in stylegan2_torch/equalized_lr.py
51 52 53 54 55 |
|
forward
forward(input: Tensor) -> Tensor
Source code in stylegan2_torch/equalized_lr.py
42 43 44 45 46 47 48 49 |
|
EqualLeakyReLU
EqualLeakyReLU(
in_dim: int, out_dim: int, lr_mult: float = 1
)
Bases: nn.Module
Leaky ReLU with equalized learning rate
Source code in stylegan2_torch/equalized_lr.py
99 100 101 102 103 104 105 106 107 108 109 |
|
__call__
class-attribute
__call__ = proxy(forward)
bias
instance-attribute
bias = Parameter(torch.zeros(out_dim))
lr_mult
instance-attribute
lr_mult = lr_mult
scale
instance-attribute
scale = 1 / math.sqrt(in_dim) * lr_mult
weight
instance-attribute
weight = Parameter(
torch.randn(out_dim, in_dim).div_(lr_mult)
)
__repr__
__repr__() -> str
Source code in stylegan2_torch/equalized_lr.py
115 116 117 118 |
|
forward
forward(input: Tensor) -> Tensor
Source code in stylegan2_torch/equalized_lr.py
111 112 113 |
|
EqualLinear
EqualLinear(
in_dim: int,
out_dim: int,
bias_init: int = 0,
lr_mult: float = 1,
)
Bases: nn.Module
Linear with equalized learning rate
Source code in stylegan2_torch/equalized_lr.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
|
__call__
class-attribute
__call__ = proxy(forward)
bias
instance-attribute
bias = Parameter(torch.zeros(out_dim).fill_(bias_init))
lr_mult
instance-attribute
lr_mult = lr_mult
scale
instance-attribute
scale = 1 / math.sqrt(in_dim) * lr_mult
weight
instance-attribute
weight = Parameter(
torch.randn(out_dim, in_dim).div_(lr_mult)
)
__repr__
__repr__() -> str
Source code in stylegan2_torch/equalized_lr.py
86 87 88 89 |
|
forward
forward(input: Tensor) -> Tensor
Source code in stylegan2_torch/equalized_lr.py
83 84 |
|
Generator
Generator(
resolution: Resolution,
latent_dim: int = 512,
n_mlp: int = 8,
lr_mlp_mult: float = 0.01,
channels: Dict[Resolution, int] = default_channels,
blur_kernel: List[int] = [1, 3, 3, 1],
)
Bases: nn.Module
Generator module
Source code in stylegan2_torch/generator/__init__.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
|
__call__
class-attribute
__call__ = proxy(forward)
convs
instance-attribute
convs = nn.ModuleList()
input
instance-attribute
input = ConstantInput(channels[4], 4)
latent_dim
instance-attribute
latent_dim = latent_dim
mapping
instance-attribute
mapping = MappingNetwork(latent_dim, n_mlp, lr_mlp_mult)
n_layers
instance-attribute
n_layers = int(math.log(resolution, 2))
n_w_plus
instance-attribute
n_w_plus = self.n_layers * 2 - 2
to_rgbs
instance-attribute
to_rgbs = nn.ModuleList()
up_convs
instance-attribute
up_convs = nn.ModuleList()
forward
forward(
input: Sequence[Tensor],
*,
return_latents: bool = False,
input_type: Literal["z", "w", "w_plus"] = "z",
trunc_option: Optional[Tuple[float, Tensor]] = None,
mix_index: Optional[int] = None,
noises: Optional[List[Optional[Tensor]]] = None
)
Source code in stylegan2_torch/generator/__init__.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
|
mean_latent
mean_latent(n_sample: int, device: str) -> Tensor
Source code in stylegan2_torch/generator/__init__.py
98 99 100 101 102 103 |
|
__docs
__docs()
Build gh-pages documentation branch.
Source code in stylegan2_torch/__init__.py
51 52 53 54 55 56 57 58 |
|
__serve
__serve()
Serve local documentation.
Source code in stylegan2_torch/__init__.py
40 41 42 43 44 45 46 47 48 |
|
__test
__test()
Runs pytest locally and keeps only coverage.xml
for GitHub Actions to upload to Codecov.
Source code in stylegan2_torch/__init__.py
30 31 32 33 34 35 36 37 |
|
d_loss
d_loss(real_pred: Tensor, fake_pred: Tensor) -> Tensor
Calculates the discriminator loss. (equivalent to adversarial loss in original GAN paper).
loss = softplus(-f(x)) + softplus(f(x))
Parameters:
Name | Type | Description | Default |
---|---|---|---|
real_pred |
Tensor
|
Predicted scores for real images |
required |
fake_pred |
Tensor
|
Predicted scores for fake images |
required |
Returns:
Name | Type | Description |
---|---|---|
Tensor |
Tensor
|
Discriminator loss |
Source code in stylegan2_torch/loss.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
d_reg_loss
d_reg_loss(real_pred: Tensor, real_img: Tensor) -> Tensor
Note
The loss function was first proposed in https://arxiv.org/pdf/1801.04406.pdf. This regularization term penalizes the discriminator from producing a gradient orthogonal to the true data manifold (i.e. Expected gradient w.r.t. real image distribution should be zero). This means that:
- Discriminator score cannot improve once generator reaches true data distribution (because discriminator gives same expected score if inputs are from sample distribution, based on this regularization term)
- Near Nash equilibrium, discriminator is encouraged to minimize the gradient magnitude (because adversarial loss cannot improve, see 1)
Points 1 and 2 are sort of chicken-and-egg in nature but the idea is to help converge to the Nash equilibrium.
Calculates the discriminator R_1 loss.
Source code in stylegan2_torch/loss.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
g_loss
g_loss(fake_pred: Tensor) -> Tensor
Calculates the generator loss.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
fake_pred |
Tensor
|
Predicted scores for fake images |
required |
Returns:
Name | Type | Description |
---|---|---|
Tensor |
Tensor
|
Generator loss |
Source code in stylegan2_torch/loss.py
62 63 64 65 66 67 68 69 70 71 72 73 74 |
|
g_reg_loss
g_reg_loss(
fake_img: Tensor,
latents: Tensor,
mean_path_length: Union[Tensor, Literal[0]],
decay: float = 0.01,
) -> Tuple[Tensor, Tensor, Tensor]
Calculates Generator path length regularization loss.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
fake_img |
Tensor
|
Generated images (N, C, H, W) |
required |
latents |
Tensor
|
W+ latent vectors (N, P, 512), P = number of style vectors |
required |
mean_path_length |
Union[Tensor, Literal[0]]
|
Current accumulated mean path length (dynamic |
required |
decay |
float
|
Decay in accumulating |
0.01
|
Returns:
Type | Description |
---|---|
Tuple[Tensor, Tensor, Tensor]
|
Tuple[Tensor, Tensor, Tensor]: Path loss, mean path, path length |
Note
This loss function was first introduced in StyleGAN2. The idea is that fixed-sized steps in W results in fixed-magnitude change in image.
Key Intuition: minimizing \(\mathbb{E}_{\mathbf{w},\mathbf{y}~N(0,1)}(||\mathbf{J^T_{\mathbf{w}}\mathbf{y}}||_2 - a)^2\) is equivalent to scaling \(W+\) equally in each dimension.
Reason:
- Do SVD on \(\mathbf{J^T_{\mathbf{w}}} = U \bar{\Sigma} V^T\)
- \(U\) and \(V\) are orthogonal and hence irrelevant (since orthogonal matrices simply rotates the vector, but \(\mathbf{y}\) is N(0,1), it is still the same distribution after rotation)
- \(\bar{\Sigma}\) has \(L\) non-zero singular values representing scaling factor in \(L\) dimensions
- Loss is minimized when \(\bar{\Sigma}\) has identical singular values equal \(\frac{a}{\sqrt{L}}\) (because high-dimensional normal distributions have norm centered around \(\sqrt{L}\))
Info
Implementation:
- \(a\) is set dynamically using the moving average of the path_lengths (sort of like searching for the appropriate scaling factor in an non-agressive manner).
- As explained in paper's Appendix B, ideal weight for path regularization is \(\gamma_{pl} = \frac{\ln 2}{r^2(\ln r - \ln 2)}\). This is achieved by setting
pl_weight
, then in the code, the loss is first scaled by \(r^2\) (i.e. height * width) innoise
then byn_layers
inpath_lengths
by taken mean over then_layers
style vectors. Resulting is equivalent as saying that ideapl_weight
is 2. See here. path_batch_shrink
controls the fraction of batch size to use to reduce memory footprint of regularization. Since it is done without freeing the memory of the existing batch.- Identity \(\mathbf{J^T_{\mathbf{w}}} \mathbf{y} = \nabla (g(\mathbf{w}) \mathbf{y})\)
Source code in stylegan2_torch/loss.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
|