1. 論文制作
論文制作については、「StyleGAN-Style-based Generative Adversarial Network」を参照してください。
2.コード
コードリファレンスstyleGAN.py - facebookresearch/pytorch_GAN_zoo - GitHub1s
Trainer の簡単な構造は次のとおりです (一部省略)。
2.1 ネットワークのマッピング
2.1.1 ネットワーク構造
8 つの MLP で構成され、出力 w は入力 z と同じサイズ (512×1)
class MappingLayer(nn.Module):
#dimInput:512 dimLatent:512 nLayers:8
def __init__(self, dimIn, dimLatent, nLayers, leakyReluLeak=0.2):
super(MappingLayer, self).__init__()
self.FC = nn.ModuleList()
inDim = dimIn
for i in range(nLayers):
self.FC.append(EqualizedLinear(inDim, dimLatent, lrMul=0.01, equalized=True, initBiasToZero=True))
inDim = dimLatent
self.activation = torch.nn.LeakyReLU(leakyReluLeak)
def forward(self, x):
for layer in self.FC:
x = self.activation(layer(x))
2.1.2 マッピング ネットワークへの入力
def buildNoiseData(self, n_samples, inputLabels=None):
inputLatent = torch.randn(
n_samples, self.config.noiseVectorDim).to(self.device)
return inputLatent, None
#根据噪声维度生成随机输入
inputLatent, targetRandCat = self.buildNoiseData(n_samples)
2.1.3 切り捨て手法
切り捨て技術を使用すると、W の極端な領域からのサンプリングが回避されます。
計算方法:
- 重心の計算
- 指定された w の中心からの偏差を次のようにスケールします。
if self.training:
self.mean_w = self.gamma_avg * self.mean_w + (1-self.gamma_avg) * mapping.mean(dim=0, keepdim=True)
if self.phiTruncation < 1:#0.999
mapping = self.mean_w + self.phiTruncation * (mapping - self.mean_w)
2.2 セクション
(ただし、AdaIN では「水滴」問題が発生することが StyleGAN2 で判明しました)
- ①まず、各特徴マップ xi (特徴マップ) を独立に正規化します。特徴マップ内の各値は、その特徴マップの平均から減算され、分散で除算されます。
- ②学習可能なアフィン変換 A (全結合層) は、w をスタイル = (ys,i,yb,i) の AdaIN の変換とスケーリング係数 y に変換します。
- ③ 次に、スタイルで学習した変換係数とスケーリング係数を使用して、各特徴マップ上でスケールと変換変換を実行します。
class AdaIN(nn.Module):
def __init__(self, dimIn, dimOut, epsilon=1e-8):
super(AdaIN, self).__init__()
self.epsilon = epsilon
self.styleModulator = EqualizedLinear(dimIn, 2*dimOut, equalized=True,
initBiasToZero=True)
self.dimOut = dimOut
def forward(self, x, y):
# x: N x C x W x H
batchSize, nChannel, width, height = x.size()
tmpX = x.view(batchSize, nChannel, -1)
mux = tmpX.mean(dim=2).view(batchSize, nChannel, 1, 1)
varx = torch.clamp((tmpX*tmpX).mean(dim=2).view(batchSize, nChannel, 1, 1) - mux*mux, min=0)
varx = torch.rsqrt(varx + self.epsilon)
x = (x - mux) * varx
# Adapt style
styleY = self.styleModulator(y)
yA = styleY[:, : self.dimOut].view(batchSize, self.dimOut, 1, 1)
yB = styleY[:, self.dimOut:].view(batchSize, self.dimOut, 1, 1)
return yA * x + yB
2.3 合成ネットワーク
2.3.1 入力定数
ランダムに生成された学習可能なパラメータが初期量として入力されます
self.baseScale0 = nn.Parameter(torch.ones(1, dimMapping, 4, 4), requires_grad=True)
2.3.2 ランダムな変更
StyleGAN のアーキテクチャは、各畳み込みの後にノイズを追加することにより、空間内でランダムな (詳細な) 変化を伴う画像を生成します。
noiseMod = self.noiseModulators[nLayer]
feature = Upscale2d(feature)
#卷积
feature = group[0](feature) + noiseMod[0](torch.randn((batchSize, 1,
feature.size(2),
feature.size(3)), device=x.device))
feature = self.activation(feature)
#AdaIN
feature = group[1](feature, mapping)
#卷积
feature = group[2](feature) + noiseMod[1](torch.randn((batchSize, 1,
feature.size(2),
feature.size(3)), device=x.device))
feature = self.activation(feature)
#AdaIN
feature = group[3](feature, mapping)
2.3.3 ノイズの発生
class NoiseMultiplier(nn.Module):
def __init__(self):
super(NoiseMultiplier, self).__init__()
self.module = nn.Conv2d(1, 1, 1, bias=False)
self.module.weight.data.fill_(0)
def forward(self, x):
return self.module(x)