style-transfer-adain / src /lightning_module.py
Michal-Raszkowski's picture
Upload 11 files
8e1e3ba verified
Raw
History Blame
5.89 kB
# import torch
# import torch.nn as nn
# import lightning as L
# from src.models.net import VGGEncoder, Decoder, adain, calc_mean_std
# class StyleTransferModule(L.LightningModule):
# def __init__(
# self,
# content_weight=1.0,
# style_weight=10.0,
# learning_rate=1e-4
# ):
# super().__init__()
# self.save_hyperparameters()
# self.encoder = VGGEncoder()
# self.decoder = Decoder()
# self.mse_loss = nn.MSELoss()
# self.register_buffer('vgg_mean', torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1))
# self.register_buffer('vgg_std', torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1))
# def normalize_vgg(self, x):
# return (x - self.vgg_mean) / self.vgg_std
# def forward(self, content_img, style_img, alpha=1.0, return_last=False):
# # 1. Liczymy cechy RAZ
# c_feats = self.encoder(self.normalize_vgg(content_img))
# s_feats = self.encoder(self.normalize_vgg(style_img))
# c_feat = c_feats[3]
# s_feat = s_feats[3]
# # 2. AdaIN
# t = adain(c_feat, s_feat)
# # 3. Alpha blending
# if alpha < 1.0: # (lub bez ifa, jak ustaliliśmy wcześniej)
# t = alpha * t + (1 - alpha) * c_feat
# g_img = self.decoder(t)
# # 4. Zwracamy też s_feats jeśli jesteśmy w treningu
# if return_last:
# return g_img, t, s_feats
# return g_img, t
# def training_step(self, batch, batch_idx):
# content_img, style_img = batch
# g_img, t, s_feats = self(content_img, style_img, return_last=True)
# g_img_norm = self.normalize_vgg(g_img)
# g_feats = self.encoder(g_img_norm)
# content_loss = self.mse_loss(g_feats[3], t)
# style_loss = 0.0
# for g_f, s_f in zip(g_feats, s_feats):
# g_mean, g_std = calc_mean_std(g_f)
# s_mean, s_std = calc_mean_std(s_f)
# style_loss += self.mse_loss(g_mean, s_mean) + self.mse_loss(g_std, s_std)
# loss = (self.hparams.content_weight * content_loss) + \
# (self.hparams.style_weight * style_loss)
# self.log("loss/train", loss, prog_bar=True)
# self.log("loss/content", content_loss)
# self.log("loss/style", style_loss)
# return loss
# def configure_optimizers(self):
# return torch.optim.Adam(self.decoder.parameters(), lr=self.hparams.learning_rate)
import torch
import torch.nn as nn
import lightning as L
from src.models import VGGEncoder, Decoder, adain, calc_mean_std
from torchmetrics.image import StructuralSimilarityIndexMeasure
class StyleTransferModule(L.LightningModule):
def __init__(self, content_weight=1.0, style_weight=10.0, learning_rate=1e-4):
super().__init__()
self.save_hyperparameters()
self.encoder = VGGEncoder()
self.decoder = Decoder()
self.mse_loss = nn.MSELoss()
self.register_buffer('vgg_mean', torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1))
self.register_buffer('vgg_std', torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1))
self.metric_ssim = StructuralSimilarityIndexMeasure(data_range=1.0)
def normalize_vgg(self, x):
return (x - self.vgg_mean) / self.vgg_std
def forward(self, content_img, style_img, alpha=1.0):
content_feats = self.encoder(self.normalize_vgg(content_img))
style_feats = self.encoder(self.normalize_vgg(style_img))
content_feat = content_feats[3]
style_feat = style_feats[3]
target = adain(content_feat, style_feat)
if alpha < 1.0:
target = alpha * target + (1 - alpha) * content_feat
generated_img = self.decoder(target)
return generated_img, target
def calculate_loss(self, content_img, style_img):
generated_img, target = self(content_img, style_img)
g_img_norm = self.normalize_vgg(generated_img)
g_feats = self.encoder(g_img_norm)
content_loss = self.mse_loss(g_feats[3], target)
s_feats = self.encoder(self.normalize_vgg(style_img))
style_loss = 0.0
for g_f, s_f in zip(g_feats, s_feats):
g_mean, g_std = calc_mean_std(g_f)
s_mean, s_std = calc_mean_std(s_f)
style_loss += self.mse_loss(g_mean, s_mean) + self.mse_loss(g_std, s_std)
total_loss = (self.hparams.content_weight * content_loss) + \
(self.hparams.style_weight * style_loss)
return total_loss, content_loss, style_loss
def training_step(self, batch, batch_idx):
loss, c_loss, s_loss = self.calculate_loss(*batch)
self.log("train/loss", loss, prog_bar=True)
self.log("train/content", c_loss)
self.log("train/style", s_loss)
return loss
def validation_step(self, batch, batch_idx):
c, s = batch
generated_img, _ = self(c, s)
ssim_score = self.metric_ssim(
torch.clamp(generated_img, 0, 1),
torch.clamp(c, 0, 1)
)
self.log("val/ssim", ssim_score, on_step=False, on_epoch=True, prog_bar=True)
loss, c_loss, s_loss = self.calculate_loss(*batch)
self.log("val/loss", loss, prog_bar=True)
self.log("val/content", c_loss)
self.log("val/style", s_loss)
return loss
def test_step(self, batch, batch_idx):
loss, c_loss, s_loss = self.calculate_loss(*batch)
self.log("test/loss", loss)
self.log("test/content", c_loss)
self.log("test/style", s_loss)
return loss
def configure_optimizers(self):
return torch.optim.Adam(self.decoder.parameters(), lr=self.hparams.learning_rate)