autoencoder.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. import torch
  2. import pytorch_lightning as pl
  3. import torch.nn.functional as F
  4. from contextlib import contextmanager
  5. from taming.modules.vqvae.quantize import VectorQuantizer2 as VectorQuantizer
  6. from ldm.modules.diffusionmodules.model import Encoder, Decoder
  7. from ldm.modules.distributions.distributions import DiagonalGaussianDistribution
  8. from ldm.util import instantiate_from_config
  9. class VQModel(pl.LightningModule):
  10. def __init__(self,
  11. ddconfig,
  12. lossconfig,
  13. n_embed,
  14. embed_dim,
  15. ckpt_path=None,
  16. ignore_keys=[],
  17. image_key="image",
  18. colorize_nlabels=None,
  19. monitor=None,
  20. batch_resize_range=None,
  21. scheduler_config=None,
  22. lr_g_factor=1.0,
  23. remap=None,
  24. sane_index_shape=False, # tell vector quantizer to return indices as bhw
  25. use_ema=False
  26. ):
  27. super().__init__()
  28. self.embed_dim = embed_dim
  29. self.n_embed = n_embed
  30. self.image_key = image_key
  31. self.encoder = Encoder(**ddconfig)
  32. self.decoder = Decoder(**ddconfig)
  33. self.loss = instantiate_from_config(lossconfig)
  34. self.quantize = VectorQuantizer(n_embed, embed_dim, beta=0.25,
  35. remap=remap,
  36. sane_index_shape=sane_index_shape)
  37. self.quant_conv = torch.nn.Conv2d(ddconfig["z_channels"], embed_dim, 1)
  38. self.post_quant_conv = torch.nn.Conv2d(embed_dim, ddconfig["z_channels"], 1)
  39. if colorize_nlabels is not None:
  40. assert type(colorize_nlabels)==int
  41. self.register_buffer("colorize", torch.randn(3, colorize_nlabels, 1, 1))
  42. if monitor is not None:
  43. self.monitor = monitor
  44. self.batch_resize_range = batch_resize_range
  45. if self.batch_resize_range is not None:
  46. print(f"{self.__class__.__name__}: Using per-batch resizing in range {batch_resize_range}.")
  47. self.use_ema = use_ema
  48. if self.use_ema:
  49. self.model_ema = LitEma(self)
  50. print(f"Keeping EMAs of {len(list(self.model_ema.buffers()))}.")
  51. if ckpt_path is not None:
  52. self.init_from_ckpt(ckpt_path, ignore_keys=ignore_keys)
  53. self.scheduler_config = scheduler_config
  54. self.lr_g_factor = lr_g_factor
  55. @contextmanager
  56. def ema_scope(self, context=None):
  57. if self.use_ema:
  58. self.model_ema.store(self.parameters())
  59. self.model_ema.copy_to(self)
  60. if context is not None:
  61. print(f"{context}: Switched to EMA weights")
  62. try:
  63. yield None
  64. finally:
  65. if self.use_ema:
  66. self.model_ema.restore(self.parameters())
  67. if context is not None:
  68. print(f"{context}: Restored training weights")
  69. def init_from_ckpt(self, path, ignore_keys=list()):
  70. sd = torch.load(path, map_location="cpu")["state_dict"]
  71. keys = list(sd.keys())
  72. for k in keys:
  73. for ik in ignore_keys:
  74. if k.startswith(ik):
  75. print("Deleting key {} from state_dict.".format(k))
  76. del sd[k]
  77. missing, unexpected = self.load_state_dict(sd, strict=False)
  78. print(f"Restored from {path} with {len(missing)} missing and {len(unexpected)} unexpected keys")
  79. if len(missing) > 0:
  80. print(f"Missing Keys: {missing}")
  81. print(f"Unexpected Keys: {unexpected}")
  82. def on_train_batch_end(self, *args, **kwargs):
  83. if self.use_ema:
  84. self.model_ema(self)
  85. def encode(self, x):
  86. h = self.encoder(x)
  87. h = self.quant_conv(h)
  88. quant, emb_loss, info = self.quantize(h)
  89. return quant, emb_loss, info
  90. def encode_to_prequant(self, x):
  91. h = self.encoder(x)
  92. h = self.quant_conv(h)
  93. return h
  94. def decode(self, quant):
  95. quant = self.post_quant_conv(quant)
  96. dec = self.decoder(quant)
  97. return dec
  98. def decode_code(self, code_b):
  99. quant_b = self.quantize.embed_code(code_b)
  100. dec = self.decode(quant_b)
  101. return dec
  102. def forward(self, input, return_pred_indices=False):
  103. quant, diff, (_,_,ind) = self.encode(input)
  104. dec = self.decode(quant)
  105. if return_pred_indices:
  106. return dec, diff, ind
  107. return dec, diff
  108. def get_input(self, batch, k):
  109. x = batch[k]
  110. if len(x.shape) == 3:
  111. x = x[..., None]
  112. x = x.permute(0, 3, 1, 2).to(memory_format=torch.contiguous_format).float()
  113. if self.batch_resize_range is not None:
  114. lower_size = self.batch_resize_range[0]
  115. upper_size = self.batch_resize_range[1]
  116. if self.global_step <= 4:
  117. # do the first few batches with max size to avoid later oom
  118. new_resize = upper_size
  119. else:
  120. new_resize = np.random.choice(np.arange(lower_size, upper_size+16, 16))
  121. if new_resize != x.shape[2]:
  122. x = F.interpolate(x, size=new_resize, mode="bicubic")
  123. x = x.detach()
  124. return x
  125. def training_step(self, batch, batch_idx, optimizer_idx):
  126. # https://github.com/pytorch/pytorch/issues/37142
  127. # try not to fool the heuristics
  128. x = self.get_input(batch, self.image_key)
  129. xrec, qloss, ind = self(x, return_pred_indices=True)
  130. if optimizer_idx == 0:
  131. # autoencode
  132. aeloss, log_dict_ae = self.loss(qloss, x, xrec, optimizer_idx, self.global_step,
  133. last_layer=self.get_last_layer(), split="train",
  134. predicted_indices=ind)
  135. self.log_dict(log_dict_ae, prog_bar=False, logger=True, on_step=True, on_epoch=True)
  136. return aeloss
  137. if optimizer_idx == 1:
  138. # discriminator
  139. discloss, log_dict_disc = self.loss(qloss, x, xrec, optimizer_idx, self.global_step,
  140. last_layer=self.get_last_layer(), split="train")
  141. self.log_dict(log_dict_disc, prog_bar=False, logger=True, on_step=True, on_epoch=True)
  142. return discloss
  143. def validation_step(self, batch, batch_idx):
  144. log_dict = self._validation_step(batch, batch_idx)
  145. with self.ema_scope():
  146. log_dict_ema = self._validation_step(batch, batch_idx, suffix="_ema")
  147. return log_dict
  148. def _validation_step(self, batch, batch_idx, suffix=""):
  149. x = self.get_input(batch, self.image_key)
  150. xrec, qloss, ind = self(x, return_pred_indices=True)
  151. aeloss, log_dict_ae = self.loss(qloss, x, xrec, 0,
  152. self.global_step,
  153. last_layer=self.get_last_layer(),
  154. split="val"+suffix,
  155. predicted_indices=ind
  156. )
  157. discloss, log_dict_disc = self.loss(qloss, x, xrec, 1,
  158. self.global_step,
  159. last_layer=self.get_last_layer(),
  160. split="val"+suffix,
  161. predicted_indices=ind
  162. )
  163. rec_loss = log_dict_ae[f"val{suffix}/rec_loss"]
  164. self.log(f"val{suffix}/rec_loss", rec_loss,
  165. prog_bar=True, logger=True, on_step=False, on_epoch=True, sync_dist=True)
  166. self.log(f"val{suffix}/aeloss", aeloss,
  167. prog_bar=True, logger=True, on_step=False, on_epoch=True, sync_dist=True)
  168. if version.parse(pl.__version__) >= version.parse('1.4.0'):
  169. del log_dict_ae[f"val{suffix}/rec_loss"]
  170. self.log_dict(log_dict_ae)
  171. self.log_dict(log_dict_disc)
  172. return self.log_dict
  173. def configure_optimizers(self):
  174. lr_d = self.learning_rate
  175. lr_g = self.lr_g_factor*self.learning_rate
  176. print("lr_d", lr_d)
  177. print("lr_g", lr_g)
  178. opt_ae = torch.optim.Adam(list(self.encoder.parameters())+
  179. list(self.decoder.parameters())+
  180. list(self.quantize.parameters())+
  181. list(self.quant_conv.parameters())+
  182. list(self.post_quant_conv.parameters()),
  183. lr=lr_g, betas=(0.5, 0.9))
  184. opt_disc = torch.optim.Adam(self.loss.discriminator.parameters(),
  185. lr=lr_d, betas=(0.5, 0.9))
  186. if self.scheduler_config is not None:
  187. scheduler = instantiate_from_config(self.scheduler_config)
  188. print("Setting up LambdaLR scheduler...")
  189. scheduler = [
  190. {
  191. 'scheduler': LambdaLR(opt_ae, lr_lambda=scheduler.schedule),
  192. 'interval': 'step',
  193. 'frequency': 1
  194. },
  195. {
  196. 'scheduler': LambdaLR(opt_disc, lr_lambda=scheduler.schedule),
  197. 'interval': 'step',
  198. 'frequency': 1
  199. },
  200. ]
  201. return [opt_ae, opt_disc], scheduler
  202. return [opt_ae, opt_disc], []
  203. def get_last_layer(self):
  204. return self.decoder.conv_out.weight
  205. def log_images(self, batch, only_inputs=False, plot_ema=False, **kwargs):
  206. log = dict()
  207. x = self.get_input(batch, self.image_key)
  208. x = x.to(self.device)
  209. if only_inputs:
  210. log["inputs"] = x
  211. return log
  212. xrec, _ = self(x)
  213. if x.shape[1] > 3:
  214. # colorize with random projection
  215. assert xrec.shape[1] > 3
  216. x = self.to_rgb(x)
  217. xrec = self.to_rgb(xrec)
  218. log["inputs"] = x
  219. log["reconstructions"] = xrec
  220. if plot_ema:
  221. with self.ema_scope():
  222. xrec_ema, _ = self(x)
  223. if x.shape[1] > 3: xrec_ema = self.to_rgb(xrec_ema)
  224. log["reconstructions_ema"] = xrec_ema
  225. return log
  226. def to_rgb(self, x):
  227. assert self.image_key == "segmentation"
  228. if not hasattr(self, "colorize"):
  229. self.register_buffer("colorize", torch.randn(3, x.shape[1], 1, 1).to(x))
  230. x = F.conv2d(x, weight=self.colorize)
  231. x = 2.*(x-x.min())/(x.max()-x.min()) - 1.
  232. return x
  233. class VQModelInterface(VQModel):
  234. def __init__(self, embed_dim, *args, **kwargs):
  235. super().__init__(embed_dim=embed_dim, *args, **kwargs)
  236. self.embed_dim = embed_dim
  237. def encode(self, x):
  238. h = self.encoder(x)
  239. h = self.quant_conv(h)
  240. return h
  241. def decode(self, h, force_not_quantize=False):
  242. # also go through quantization layer
  243. if not force_not_quantize:
  244. quant, emb_loss, info = self.quantize(h)
  245. else:
  246. quant = h
  247. quant = self.post_quant_conv(quant)
  248. dec = self.decoder(quant)
  249. return dec
  250. class AutoencoderKL(pl.LightningModule):
  251. def __init__(self,
  252. ddconfig,
  253. lossconfig,
  254. embed_dim,
  255. ckpt_path=None,
  256. ignore_keys=[],
  257. image_key="image",
  258. colorize_nlabels=None,
  259. monitor=None,
  260. ):
  261. super().__init__()
  262. self.image_key = image_key
  263. self.encoder = Encoder(**ddconfig)
  264. self.decoder = Decoder(**ddconfig)
  265. self.loss = instantiate_from_config(lossconfig)
  266. assert ddconfig["double_z"]
  267. self.quant_conv = torch.nn.Conv2d(2*ddconfig["z_channels"], 2*embed_dim, 1)
  268. self.post_quant_conv = torch.nn.Conv2d(embed_dim, ddconfig["z_channels"], 1)
  269. self.embed_dim = embed_dim
  270. if colorize_nlabels is not None:
  271. assert type(colorize_nlabels)==int
  272. self.register_buffer("colorize", torch.randn(3, colorize_nlabels, 1, 1))
  273. if monitor is not None:
  274. self.monitor = monitor
  275. if ckpt_path is not None:
  276. self.init_from_ckpt(ckpt_path, ignore_keys=ignore_keys)
  277. def init_from_ckpt(self, path, ignore_keys=list()):
  278. sd = torch.load(path, map_location="cpu")["state_dict"]
  279. keys = list(sd.keys())
  280. for k in keys:
  281. for ik in ignore_keys:
  282. if k.startswith(ik):
  283. print("Deleting key {} from state_dict.".format(k))
  284. del sd[k]
  285. self.load_state_dict(sd, strict=False)
  286. print(f"Restored from {path}")
  287. def encode(self, x):
  288. h = self.encoder(x)
  289. moments = self.quant_conv(h)
  290. posterior = DiagonalGaussianDistribution(moments)
  291. return posterior
  292. def decode(self, z):
  293. z = self.post_quant_conv(z)
  294. dec = self.decoder(z)
  295. return dec
  296. def forward(self, input, sample_posterior=True):
  297. posterior = self.encode(input)
  298. if sample_posterior:
  299. z = posterior.sample()
  300. else:
  301. z = posterior.mode()
  302. dec = self.decode(z)
  303. return dec, posterior
  304. def get_input(self, batch, k):
  305. x = batch[k]
  306. if len(x.shape) == 3:
  307. x = x[..., None]
  308. x = x.permute(0, 3, 1, 2).to(memory_format=torch.contiguous_format).float()
  309. return x
  310. def training_step(self, batch, batch_idx, optimizer_idx):
  311. inputs = self.get_input(batch, self.image_key)
  312. reconstructions, posterior = self(inputs)
  313. if optimizer_idx == 0:
  314. # train encoder+decoder+logvar
  315. aeloss, log_dict_ae = self.loss(inputs, reconstructions, posterior, optimizer_idx, self.global_step,
  316. last_layer=self.get_last_layer(), split="train")
  317. self.log("aeloss", aeloss, prog_bar=True, logger=True, on_step=True, on_epoch=True)
  318. self.log_dict(log_dict_ae, prog_bar=False, logger=True, on_step=True, on_epoch=False)
  319. return aeloss
  320. if optimizer_idx == 1:
  321. # train the discriminator
  322. discloss, log_dict_disc = self.loss(inputs, reconstructions, posterior, optimizer_idx, self.global_step,
  323. last_layer=self.get_last_layer(), split="train")
  324. self.log("discloss", discloss, prog_bar=True, logger=True, on_step=True, on_epoch=True)
  325. self.log_dict(log_dict_disc, prog_bar=False, logger=True, on_step=True, on_epoch=False)
  326. return discloss
  327. def validation_step(self, batch, batch_idx):
  328. inputs = self.get_input(batch, self.image_key)
  329. reconstructions, posterior = self(inputs)
  330. aeloss, log_dict_ae = self.loss(inputs, reconstructions, posterior, 0, self.global_step,
  331. last_layer=self.get_last_layer(), split="val")
  332. discloss, log_dict_disc = self.loss(inputs, reconstructions, posterior, 1, self.global_step,
  333. last_layer=self.get_last_layer(), split="val")
  334. self.log("val/rec_loss", log_dict_ae["val/rec_loss"])
  335. self.log_dict(log_dict_ae)
  336. self.log_dict(log_dict_disc)
  337. return self.log_dict
  338. def configure_optimizers(self):
  339. lr = self.learning_rate
  340. opt_ae = torch.optim.Adam(list(self.encoder.parameters())+
  341. list(self.decoder.parameters())+
  342. list(self.quant_conv.parameters())+
  343. list(self.post_quant_conv.parameters()),
  344. lr=lr, betas=(0.5, 0.9))
  345. opt_disc = torch.optim.Adam(self.loss.discriminator.parameters(),
  346. lr=lr, betas=(0.5, 0.9))
  347. return [opt_ae, opt_disc], []
  348. def get_last_layer(self):
  349. return self.decoder.conv_out.weight
  350. @torch.no_grad()
  351. def log_images(self, batch, only_inputs=False, **kwargs):
  352. log = dict()
  353. x = self.get_input(batch, self.image_key)
  354. x = x.to(self.device)
  355. if not only_inputs:
  356. xrec, posterior = self(x)
  357. if x.shape[1] > 3:
  358. # colorize with random projection
  359. assert xrec.shape[1] > 3
  360. x = self.to_rgb(x)
  361. xrec = self.to_rgb(xrec)
  362. log["samples"] = self.decode(torch.randn_like(posterior.sample()))
  363. log["reconstructions"] = xrec
  364. log["inputs"] = x
  365. return log
  366. def to_rgb(self, x):
  367. assert self.image_key == "segmentation"
  368. if not hasattr(self, "colorize"):
  369. self.register_buffer("colorize", torch.randn(3, x.shape[1], 1, 1).to(x))
  370. x = F.conv2d(x, weight=self.colorize)
  371. x = 2.*(x-x.min())/(x.max()-x.min()) - 1.
  372. return x
  373. class IdentityFirstStage(torch.nn.Module):
  374. def __init__(self, *args, vq_interface=False, **kwargs):
  375. self.vq_interface = vq_interface # TODO: Should be true by default but check to not break older stuff
  376. super().__init__()
  377. def encode(self, x, *args, **kwargs):
  378. return x
  379. def decode(self, x, *args, **kwargs):
  380. return x
  381. def quantize(self, x, *args, **kwargs):
  382. if self.vq_interface:
  383. return x, None, [None, None, None]
  384. return x
  385. def forward(self, x, *args, **kwargs):
  386. return x