augustander commited on
Commit
9117fe1
·
verified ·
1 Parent(s): 9aa6cf0

add D3 = ResnetGenerator9Plain (no dilation, no wing ResBlock, bilinear upsample) for 1024^2 + DAB loss

Browse files
Files changed (1) hide show
  1. scripts/src_ds_her2_thunder_v2.py +74 -0
scripts/src_ds_her2_thunder_v2.py CHANGED
@@ -774,6 +774,78 @@ class ResnetGenerator9Dilated(nn.Module):
774
  return self.head(x)
775
 
776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  class SkipFreeAE(nn.Module):
778
  """Encoder-decoder with pluggable downsample block (strided or DWT).
779
  Used for Exp 2 (arch A vs B) at ds_factor=1.
@@ -1190,6 +1262,8 @@ def train_one(arch: str, ds_factor: int, files_train, files_val,
1190
  elif arch == "D2":
1191
  G = ResnetGenerator9Dilated(base_ch=args.dilated_ch,
1192
  dilations=tuple(args.d2_dilations)).to(device)
 
 
1193
  elif arch == "C":
1194
  G = WaveletJointAE(base_ch=args.wavelet_ch,
1195
  wavelet=args.wavelet).to(device)
 
774
  return self.head(x)
775
 
776
 
777
+ class ResnetGenerator9Plain(nn.Module):
778
+ """Arch D3: 1024^2 CycleGAN-style Resnet 9-block generator, NO dilation.
779
+
780
+ Standard Pyramid-Pix2Pix / CycleGAN template adapted to our stack:
781
+ - GroupNorm + GELU + zero pad throughout (NOT InstanceNorm + ReLU + reflection).
782
+ - Bilinear x2 + Conv3x3 for upsampling (NOT ConvTranspose, avoids checkerboard).
783
+ - Wing blocks are lean (Conv3x3+GN+GELU only, NO ResBlock) so we fit 1024^2 at
784
+ bs=8 on A100 80GB. All the ResBlocks live in the bottleneck.
785
+ - Bottleneck: 9 x ResBlock(base_ch*4), dilation=1 (plain), same class as A3/C.
786
+
787
+ Topology:
788
+ stem: Conv7x7(3->c1) + GN + GELU (1024^2)
789
+ down1: Conv3x3(c1->c2, s=2) + GN + GELU (512^2)
790
+ down2: Conv3x3(c2->c3, s=2) + GN + GELU (256^2)
791
+ bottleneck: 9 x ResBlock(c3, dilation=1) (256^2)
792
+ up1: Bilinear x2 + Conv3x3(c3->c2) + GN + GELU (512^2)
793
+ up2: Bilinear x2 + Conv3x3(c2->c1) + GN + GELU (1024^2)
794
+ head: Conv7x7(c1->3) + Tanh (1024^2)
795
+
796
+ ~10.4M params at base_ch=64. Works at any resolution divisible by 4.
797
+ """
798
+
799
+ def __init__(self, base_ch: int = 64, groups: int = 8, n_bottleneck: int = 9):
800
+ super().__init__()
801
+ c1, c2, c3 = base_ch, base_ch * 2, base_ch * 4
802
+ g1 = min(groups, c1); g2 = min(groups, c2); g3 = min(groups, c3)
803
+ self.stem = nn.Sequential(
804
+ nn.Conv2d(3, c1, 7, padding=3),
805
+ nn.GroupNorm(g1, c1),
806
+ nn.GELU(),
807
+ )
808
+ self.down1 = nn.Sequential(
809
+ nn.Conv2d(c1, c2, 3, stride=2, padding=1),
810
+ nn.GroupNorm(g2, c2),
811
+ nn.GELU(),
812
+ )
813
+ self.down2 = nn.Sequential(
814
+ nn.Conv2d(c2, c3, 3, stride=2, padding=1),
815
+ nn.GroupNorm(g3, c3),
816
+ nn.GELU(),
817
+ )
818
+ # Plain 9-block bottleneck (dilation=1), same ResBlock class as A3/C.
819
+ self.bottleneck = nn.Sequential(
820
+ *[ResBlock(c3, groups=groups) for _ in range(n_bottleneck)]
821
+ )
822
+ self.up1 = nn.Sequential(
823
+ nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False),
824
+ nn.Conv2d(c3, c2, 3, padding=1),
825
+ nn.GroupNorm(g2, c2),
826
+ nn.GELU(),
827
+ )
828
+ self.up2 = nn.Sequential(
829
+ nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False),
830
+ nn.Conv2d(c2, c1, 3, padding=1),
831
+ nn.GroupNorm(g1, c1),
832
+ nn.GELU(),
833
+ )
834
+ self.head = nn.Sequential(
835
+ nn.Conv2d(c1, 3, 7, padding=3),
836
+ nn.Tanh(),
837
+ )
838
+
839
+ def forward(self, x):
840
+ x = self.stem(x)
841
+ x = self.down1(x)
842
+ x = self.down2(x)
843
+ x = self.bottleneck(x)
844
+ x = self.up1(x)
845
+ x = self.up2(x)
846
+ return self.head(x)
847
+
848
+
849
  class SkipFreeAE(nn.Module):
850
  """Encoder-decoder with pluggable downsample block (strided or DWT).
851
  Used for Exp 2 (arch A vs B) at ds_factor=1.
 
1262
  elif arch == "D2":
1263
  G = ResnetGenerator9Dilated(base_ch=args.dilated_ch,
1264
  dilations=tuple(args.d2_dilations)).to(device)
1265
+ elif arch == "D3":
1266
+ G = ResnetGenerator9Plain(base_ch=args.dilated_ch).to(device)
1267
  elif arch == "C":
1268
  G = WaveletJointAE(base_ch=args.wavelet_ch,
1269
  wavelet=args.wavelet).to(device)