repos
/ ai-art master

ai-art

mirror archived upstream

Art generation with VQGAN + CLIP in Docker, with a simple web UI for anyone with a GPU. A simplified and expanded take on Kevin Costa's work.

aiai-artclipdockerdocker-composegpuhandcodedimagenetpythonpytorchtorchtorchvisionvqganvqgan-clip

3.6 KB · 103 lines · Python Raw History
  1import torch
  2import torch.nn as nn
  3
  4import numpy as np
  5
  6from core.taming.utils import Normalize, nonlinearity
  7
  8from core.taming.modules.diffusion import AttnBlock, ResnetBlock, Upsample
  9
 10
 11class Decoder(nn.Module):
 12    def __init__(self, *, ch, out_ch, ch_mult=(1, 2, 4, 8), num_res_blocks,
 13                 attn_resolutions, dropout=0.0, resamp_with_conv=True, in_channels,
 14                 resolution, z_channels, give_pre_end=False, **ignorekwargs):
 15        super().__init__()
 16        self.ch = ch
 17        self.temb_ch = 0
 18        self.num_resolutions = len(ch_mult)
 19        self.num_res_blocks = num_res_blocks
 20        self.resolution = resolution
 21        self.in_channels = in_channels
 22        self.give_pre_end = give_pre_end
 23
 24        # compute in_ch_mult, block_in and curr_res at lowest res
 25        # in_ch_mult = (1,)+tuple(ch_mult)
 26        block_in = ch * ch_mult[self.num_resolutions - 1]
 27        curr_res = resolution // 2**(self.num_resolutions - 1)
 28        self.z_shape = (1, z_channels, curr_res, curr_res)
 29        print("Working with z of shape {} = {} dimensions.".format(
 30            self.z_shape, np.prod(self.z_shape)))
 31
 32        # z to block_in
 33        self.conv_in = torch.nn.Conv2d(z_channels, block_in, kernel_size=3, stride=1, padding=1)
 34
 35        # middle
 36        self.mid = nn.Module()
 37        self.mid.block_1 = ResnetBlock(
 38            in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout
 39        )
 40        self.mid.attn_1 = AttnBlock(block_in)
 41        self.mid.block_2 = ResnetBlock(
 42            in_channels=block_in, out_channels=block_in, temb_channels=self.temb_ch, dropout=dropout
 43        )
 44
 45        # upsampling
 46        self.up = nn.ModuleList()
 47        for i_level in reversed(range(self.num_resolutions)):
 48            block = nn.ModuleList()
 49            attn = nn.ModuleList()
 50            block_out = ch * ch_mult[i_level]
 51            for i_block in range(self.num_res_blocks + 1):
 52                block.append(ResnetBlock(in_channels=block_in,
 53                                         out_channels=block_out,
 54                                         temb_channels=self.temb_ch,
 55                                         dropout=dropout))
 56                block_in = block_out
 57                if curr_res in attn_resolutions:
 58                    attn.append(AttnBlock(block_in))
 59            up = nn.Module()
 60            up.block = block
 61            up.attn = attn
 62            if i_level != 0:
 63                up.upsample = Upsample(block_in, resamp_with_conv)
 64                curr_res = curr_res * 2
 65            self.up.insert(0, up)  # prepend to get consistent order
 66
 67        # end
 68        self.norm_out = Normalize(block_in)
 69        self.conv_out = torch.nn.Conv2d(block_in, out_ch, kernel_size=3, stride=1, padding=1)
 70
 71    def forward(self, z):
 72        # assert z.shape[1:] == self.z_shape[1:]
 73        self.last_z_shape = z.shape
 74
 75        # timestep embedding
 76        temb = None
 77
 78        # z to block_in
 79        h = self.conv_in(z)
 80
 81        # middle
 82        h = self.mid.block_1(h, temb)
 83        h = self.mid.attn_1(h)
 84        h = self.mid.block_2(h, temb)
 85
 86        # upsampling
 87        for i_level in reversed(range(self.num_resolutions)):
 88            for i_block in range(self.num_res_blocks + 1):
 89                h = self.up[i_level].block[i_block](h, temb)
 90                if len(self.up[i_level].attn) > 0:
 91                    h = self.up[i_level].attn[i_block](h)
 92            if i_level != 0:
 93                h = self.up[i_level].upsample(h)
 94
 95        # end
 96        if self.give_pre_end:
 97            return h
 98
 99        h = self.norm_out(h)
100        h = nonlinearity(h)
101        h = self.conv_out(h)
102        return h