├── .gitignore ├── Diffusion-Model ├── Readme.md └── diffusion model.py ├── GAN & GAN Variations ├── Readme.md ├── acgan.py ├── cgan.py ├── cogan.py ├── dcgan.py ├── gan.py ├── sgan.py ├── wgan-gp.py └── wgan.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /Diffusion-Model/Readme.md: -------------------------------------------------------------------------------- 1 | The code details are visible at https://www.zhihu.com/people/alexgo-25/posts. 2 | -------------------------------------------------------------------------------- /Diffusion-Model/diffusion model.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.Dec.6th 4 | Diffusion model 5 | """ 6 | import matplotlib.pyplot as plt 7 | import numpy as np 8 | from sklearn.datasets import make_s_curve 9 | import torch 10 | import torch 11 | import torch.nn as nn 12 | import io 13 | from PIL import Image 14 | # 生成一万个点,得到s curve 15 | s_curve,_ = make_s_curve(10**4,noise=0.1) 16 | s_curve = s_curve[:,[0,2]]/10.0 17 | 18 | print("shape of s:",np.shape(s_curve)) 19 | 20 | data = s_curve.T 21 | 22 | fig,ax = plt.subplots() 23 | ax.scatter(*data,color='blue',edgecolor='white'); 24 | 25 | ax.axis('off') 26 | #当成一个数据集 27 | dataset = torch.Tensor(s_curve).float() 28 | #画出 s curve 29 | plt.show() 30 | 31 | 32 | #确定超参数的值 33 | num_steps = 100 #可由beta值估算 34 | 35 | #制定每一步的beta,beta按照时间从小到大变化 36 | betas = torch.linspace(-6,6,num_steps) 37 | betas = torch.sigmoid(betas)*(0.5e-2 - 1e-5)+1e-5 38 | 39 | #计算alpha、alpha_prod、alpha_prod_previous、alpha_bar_sqrt等变量的值 40 | alphas = 1-betas 41 | # alpha连乘 42 | alphas_prod = torch.cumprod(alphas,0) 43 | #从第一项开始,第0项另乘1??? 44 | alphas_prod_p = torch.cat([torch.tensor([1]).float(),alphas_prod[:-1]],0) 45 | # alphas_prod开根号 46 | alphas_bar_sqrt = torch.sqrt(alphas_prod) 47 | #之后公式中要用的 48 | one_minus_alphas_bar_log = torch.log(1 - alphas_prod) 49 | one_minus_alphas_bar_sqrt = torch.sqrt(1 - alphas_prod) 50 | # 大小都一样,常数不需要训练 51 | assert alphas.shape==alphas_prod.shape==alphas_prod_p.shape==\ 52 | alphas_bar_sqrt.shape==one_minus_alphas_bar_log.shape\ 53 | ==one_minus_alphas_bar_sqrt.shape 54 | print("all the same shape",betas.shape) 55 | 56 | #给定初始,算出任意时刻采样值——正向扩散 57 | # 计算任意时刻的x采样值,基于x_0和重参数化 58 | def q_x(x_0, t): 59 | """可以基于x[0]得到任意时刻t的x[t]""" 60 | #生成正态分布采样 61 | noise = torch.randn_like(x_0) 62 | #得到均值方差 63 | alphas_t = alphas_bar_sqrt[t] 64 | alphas_1_m_t = one_minus_alphas_bar_sqrt[t] 65 | #根据x0求xt 66 | return (alphas_t * x_0 + alphas_1_m_t * noise) # 在x[0]的基础上添加噪声 67 | 68 | # 演示加噪过程,加噪100步情况 69 | num_shows = 20 70 | fig,axs = plt.subplots(2,10,figsize=(28,3)) 71 | plt.rc('text',color='black') 72 | 73 | #共有10000个点,每个点包含两个坐标 74 | #生成100步以内每隔5步加噪声后的图像,扩散过程散点图演示——基于x0生成条件分布采样得到xt 75 | for i in range(num_shows): 76 | j = i//10 77 | k = i%10 78 | q_i = q_x(dataset,torch.tensor([i*num_steps//num_shows])) # 生成t时刻的采样数据 79 | axs[j,k].scatter(q_i[:,0],q_i[:,1],color='red',edgecolor='white') 80 | axs[j,k].set_axis_off() 81 | axs[j,k].set_title('$q(\mathbf{x}_{'+str(i*num_steps//num_shows)+'})$') 82 | plt.show() 83 | 84 | 85 | # 拟合逆扩散过程高斯分布模型——拟合逆扩散时的噪声 86 | 87 | 88 | #自定义神经网络 89 | class MLPDiffusion(nn.Module): 90 | def __init__(self, n_steps, num_units=128): 91 | super(MLPDiffusion, self).__init__() 92 | 93 | self.linears = nn.ModuleList( 94 | [ 95 | nn.Linear(2, num_units), 96 | nn.ReLU(), 97 | nn.Linear(num_units, num_units), 98 | nn.ReLU(), 99 | nn.Linear(num_units, num_units), 100 | nn.ReLU(), 101 | nn.Linear(num_units, 2), 102 | ] 103 | ) 104 | self.step_embeddings = nn.ModuleList( 105 | [ 106 | nn.Embedding(n_steps, num_units), 107 | nn.Embedding(n_steps, num_units), 108 | nn.Embedding(n_steps, num_units), 109 | ] 110 | ) 111 | 112 | def forward(self, x, t): 113 | # x = x_0 114 | for idx, embedding_layer in enumerate(self.step_embeddings): 115 | t_embedding = embedding_layer(t) 116 | x = self.linears[2 * idx](x) 117 | x += t_embedding 118 | x = self.linears[2 * idx + 1](x) 119 | 120 | x = self.linears[-1](x) 121 | 122 | return x 123 | 124 | #编写训练误差函数 125 | def diffusion_loss_fn(model, x_0, alphas_bar_sqrt, one_minus_alphas_bar_sqrt, n_steps): 126 | """对任意时刻t进行采样计算loss""" 127 | batch_size = x_0.shape[0] 128 | 129 | # 对一个batchsize样本生成随机的时刻t,t变得随机分散一些,一个batch size里面覆盖更多的t 130 | t = torch.randint(0, n_steps, size=(batch_size // 2,)) 131 | t = torch.cat([t, n_steps - 1 - t], dim=0)# t的形状(bz) 132 | t = t.unsqueeze(-1)# t的形状(bz,1) 133 | 134 | # x0的系数,根号下(alpha_bar_t) 135 | a = alphas_bar_sqrt[t] 136 | 137 | # eps的系数,根号下(1-alpha_bar_t) 138 | aml = one_minus_alphas_bar_sqrt[t] 139 | 140 | # 生成随机噪音eps 141 | e = torch.randn_like(x_0) 142 | 143 | # 构造模型的输入 144 | x = x_0 * a + e * aml 145 | 146 | # 送入模型,得到t时刻的随机噪声预测值 147 | output = model(x, t.squeeze(-1)) 148 | 149 | # 与真实噪声一起计算误差,求平均值 150 | return (e - output).square().mean() 151 | 152 | #编写逆扩散采样函数 153 | 154 | #从xt恢复x0 155 | def p_sample_loop(model, shape, n_steps, betas, one_minus_alphas_bar_sqrt): 156 | """从x[T]恢复x[T-1]、x[T-2]|...x[0]""" 157 | cur_x = torch.randn(shape) 158 | x_seq = [cur_x] 159 | for i in reversed(range(n_steps)): 160 | cur_x = p_sample(model, cur_x, i, betas, one_minus_alphas_bar_sqrt) 161 | x_seq.append(cur_x) 162 | return x_seqD 163 | 164 | 165 | def p_sample(model, x, t, betas, one_minus_alphas_bar_sqrt): 166 | """从x[T]采样t时刻的重构值""" 167 | t = torch.tensor([t]) 168 | 169 | coeff = betas[t] / one_minus_alphas_bar_sqrt[t] 170 | 171 | eps_theta = model(x, t) 172 | #得到均值 173 | mean = (1 / (1 - betas[t]).sqrt()) * (x - (coeff * eps_theta)) 174 | 175 | z = torch.randn_like(x) 176 | sigma_t = betas[t].sqrt() 177 | #得到sample的分布 178 | sample = mean + sigma_t * z 179 | 180 | return (sample) 181 | 182 | #开始训练模型,打印loss以及中间的重构效果 183 | seed = 1234 184 | 185 | 186 | class EMA(): 187 | """构建一个参数平滑器""" 188 | 189 | def __init__(self, mu=0.01): 190 | self.mu = mu 191 | self.shadow = {} 192 | 193 | def register(self, name, val): 194 | self.shadow[name] = val.clone() 195 | 196 | def __call__(self, name, x): 197 | assert name in self.shadow 198 | new_average = self.mu * x + (1.0 - self.mu) * self.shadow[name] 199 | self.shadow[name] = new_average.clone() 200 | return new_average 201 | 202 | 203 | print('Training model...') 204 | batch_size = 128 205 | # dataset放到dataloader中 206 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True) 207 | # 迭代周期 208 | num_epoch = 4000 209 | plt.rc('text', color='blue') 210 | #实例化模型,传入一个数 211 | model = MLPDiffusion(num_steps) # 输出维度是2,输入是x和step 212 | optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) 213 | # epoch遍历 214 | for t in range(num_epoch): 215 | # dataloader遍历 216 | for idx, batch_x in enumerate(dataloader): 217 | # 得到loss 218 | loss = diffusion_loss_fn(model, batch_x, alphas_bar_sqrt, one_minus_alphas_bar_sqrt, num_steps) 219 | optimizer.zero_grad() 220 | loss.backward() 221 | #梯度clip,保持稳定性 222 | torch.nn.utils.clip_grad_norm_(model.parameters(), 1.) 223 | optimizer.step() 224 | #每100步打印效果 225 | if (t % 100 == 0): 226 | print(loss) 227 | #根据参数采样一百个步骤的x,每隔十步画出来,迭代了4000个周期,逐渐更接近于原始 228 | x_seq = p_sample_loop(model, dataset.shape, num_steps, betas, one_minus_alphas_bar_sqrt) 229 | 230 | fig, axs = plt.subplots(1, 10, figsize=(28, 3)) 231 | for i in range(1, 11): 232 | cur_x = x_seq[i * 10].detach() 233 | axs[i - 1].scatter(cur_x[:, 0], cur_x[:, 1], color='red', edgecolor='white'); 234 | axs[i - 1].set_axis_off(); 235 | axs[i - 1].set_title('$q(\mathbf{x}_{' + str(i * 10) + '})$') 236 | plt.show() 237 | 238 | # 前向后向过程gif 239 | imgs = [] 240 | for i in range(100): 241 | plt.clf() 242 | q_i = q_x(dataset, torch.tensor([i])) 243 | plt.scatter(q_i[:, 0], q_i[:, 1], color='red', edgecolor='white', s=5); 244 | plt.axis('off'); 245 | 246 | img_buf = io.BytesIO() 247 | plt.savefig(img_buf, format='png') 248 | img = Image.open(img_buf) 249 | imgs.append(img) 250 | plt.show() 251 | reverse = [] 252 | for i in range(100): 253 | plt.clf() 254 | cur_x = x_seq[i].detach() 255 | plt.scatter(cur_x[:, 0], cur_x[:, 1], color='red', edgecolor='white', s=5); 256 | plt.axis('off') 257 | 258 | img_buf = io.BytesIO() 259 | plt.savefig(img_buf, format='png') 260 | img = Image.open(img_buf) 261 | reverse.append(img) 262 | plt.show() 263 | imgs = imgs +reverse 264 | imgs[0].save("diffusion.gif",format='GIF',append_images=imgs,save_all=True,duration=100,loop=0) 265 | -------------------------------------------------------------------------------- /GAN & GAN Variations/Readme.md: -------------------------------------------------------------------------------- 1 | The code details are visible at https://www.zhihu.com/people/alexgo-25/posts. 2 | -------------------------------------------------------------------------------- /GAN & GAN Variations/acgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.June.30th 4 | Auxiliary Classifier GAN 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import torchvision.transforms as transforms 11 | from torchvision.utils import save_image 12 | from torch.utils.data import DataLoader 13 | from torchvision import datasets 14 | from torch.autograd import Variable 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch 18 | 19 | os.makedirs("images", exist_ok=True) 20 | 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 23 | parser.add_argument("--batch_size", type=int, default=256, help="size of the batches") 24 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 25 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 26 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 27 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 28 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 29 | parser.add_argument("--n_classes", type=int, default=10, help="number of classes for dataset") 30 | parser.add_argument("--img_size", type=int, default=32, help="size of each image dimension") 31 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 32 | parser.add_argument("--sample_interval", type=int, default=400, help="interval between image sampling") 33 | opt = parser.parse_args() 34 | print(opt) 35 | 36 | cuda = True if torch.cuda.is_available() else False 37 | 38 | 39 | def weights_init_normal(m): 40 | classname = m.__class__.__name__ 41 | if classname.find("Conv") != -1: 42 | torch.nn.init.normal_(m.weight.data, 0.0, 0.02) 43 | elif classname.find("BatchNorm2d") != -1: 44 | torch.nn.init.normal_(m.weight.data, 1.0, 0.02) 45 | torch.nn.init.constant_(m.bias.data, 0.0) 46 | 47 | 48 | class Generator(nn.Module): 49 | def __init__(self): 50 | super(Generator, self).__init__() 51 | 52 | self.label_emb = nn.Embedding(opt.n_classes, opt.latent_dim) 53 | 54 | self.init_size = opt.img_size // 4 # Initial size before upsampling 55 | self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128 * self.init_size ** 2)) 56 | 57 | self.conv_blocks = nn.Sequential( 58 | nn.BatchNorm2d(128), 59 | nn.Upsample(scale_factor=2), 60 | nn.Conv2d(128, 128, 3, stride=1, padding=1), 61 | nn.BatchNorm2d(128, 0.8), 62 | nn.LeakyReLU(0.2, inplace=True), 63 | nn.Upsample(scale_factor=2), 64 | nn.Conv2d(128, 64, 3, stride=1, padding=1), 65 | nn.BatchNorm2d(64, 0.8), 66 | nn.LeakyReLU(0.2, inplace=True), 67 | nn.Conv2d(64, opt.channels, 3, stride=1, padding=1), 68 | nn.Tanh(), 69 | ) 70 | 71 | def forward(self, noise, labels): 72 | gen_input = torch.mul(self.label_emb(labels), noise) 73 | out = self.l1(gen_input) 74 | out = out.view(out.shape[0], 128, self.init_size, self.init_size) 75 | img = self.conv_blocks(out) 76 | return img 77 | 78 | 79 | class Discriminator(nn.Module): 80 | def __init__(self): 81 | super(Discriminator, self).__init__() 82 | 83 | def discriminator_block(in_filters, out_filters, bn=True): 84 | """Returns layers of each discriminator block""" 85 | block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1), nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)] 86 | if bn: 87 | block.append(nn.BatchNorm2d(out_filters, 0.8)) 88 | return block 89 | 90 | self.conv_blocks = nn.Sequential( 91 | *discriminator_block(opt.channels, 16, bn=False), 92 | *discriminator_block(16, 32), 93 | *discriminator_block(32, 64), 94 | *discriminator_block(64, 128), 95 | ) 96 | 97 | # The height and width of downsampled image 98 | ds_size = opt.img_size // 2 ** 4 99 | 100 | # Output layers 101 | self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid()) 102 | self.aux_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, opt.n_classes), nn.Softmax()) 103 | 104 | def forward(self, img): 105 | out = self.conv_blocks(img) 106 | out = out.view(out.shape[0], -1) 107 | validity = self.adv_layer(out) 108 | label = self.aux_layer(out) 109 | 110 | return validity, label 111 | 112 | 113 | # Loss functions 114 | adversarial_loss = torch.nn.BCELoss() 115 | auxiliary_loss = torch.nn.CrossEntropyLoss() 116 | 117 | # Initialize generator and discriminator 118 | generator = Generator() 119 | discriminator = Discriminator() 120 | 121 | if cuda: 122 | generator.cuda() 123 | discriminator.cuda() 124 | adversarial_loss.cuda() 125 | auxiliary_loss.cuda() 126 | 127 | # Initialize weights 128 | generator.apply(weights_init_normal) 129 | discriminator.apply(weights_init_normal) 130 | 131 | # Configure data loader 132 | os.makedirs("../../data/mnist", exist_ok=True) 133 | dataloader = torch.utils.data.DataLoader( 134 | datasets.MNIST( 135 | "../../data/mnist", 136 | train=True, 137 | download=True, 138 | transform=transforms.Compose( 139 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 140 | ), 141 | ), 142 | batch_size=opt.batch_size, 143 | shuffle=True, 144 | ) 145 | 146 | # Optimizers 147 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 148 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 149 | 150 | FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 151 | LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor 152 | 153 | 154 | def sample_image(n_row, batches_done): 155 | """Saves a grid of generated digits ranging from 0 to n_classes""" 156 | # Sample noise 157 | z = Variable(FloatTensor(np.random.normal(0, 1, (n_row ** 2, opt.latent_dim)))) 158 | # Get labels ranging from 0 to n_classes for n rows 159 | labels = np.array([num for _ in range(n_row) for num in range(n_row)]) 160 | labels = Variable(LongTensor(labels)) 161 | gen_imgs = generator(z, labels) 162 | save_image(gen_imgs.data, "images/%d.png" % batches_done, nrow=n_row, normalize=True) 163 | 164 | 165 | # ---------- 166 | # Training 167 | # ---------- 168 | 169 | for epoch in range(opt.n_epochs): 170 | for i, (imgs, labels) in enumerate(dataloader): 171 | 172 | batch_size = imgs.shape[0] 173 | 174 | # Adversarial ground truths 175 | valid = Variable(FloatTensor(batch_size, 1).fill_(1.0), requires_grad=False) 176 | fake = Variable(FloatTensor(batch_size, 1).fill_(0.0), requires_grad=False) 177 | 178 | # Configure input 179 | real_imgs = Variable(imgs.type(FloatTensor)) 180 | labels = Variable(labels.type(LongTensor)) 181 | 182 | # ----------------- 183 | # Train Generator 184 | # ----------------- 185 | 186 | optimizer_G.zero_grad() 187 | 188 | # Sample noise and labels as generator input 189 | z = Variable(FloatTensor(np.random.normal(0, 1, (batch_size, opt.latent_dim)))) 190 | gen_labels = Variable(LongTensor(np.random.randint(0, opt.n_classes, batch_size))) 191 | 192 | # Generate a batch of images 193 | gen_imgs = generator(z, gen_labels) 194 | 195 | # Loss measures generator's ability to fool the discriminator 196 | validity, pred_label = discriminator(gen_imgs) 197 | g_loss = 0.5 * (adversarial_loss(validity, valid) + auxiliary_loss(pred_label, gen_labels)) 198 | 199 | g_loss.backward() 200 | optimizer_G.step() 201 | 202 | # --------------------- 203 | # Train Discriminator 204 | # --------------------- 205 | 206 | optimizer_D.zero_grad() 207 | 208 | # Loss for real images 209 | real_pred, real_aux = discriminator(real_imgs) 210 | d_real_loss = (adversarial_loss(real_pred, valid) + auxiliary_loss(real_aux, labels)) / 2 211 | 212 | # Loss for fake images 213 | fake_pred, fake_aux = discriminator(gen_imgs.detach()) 214 | d_fake_loss = (adversarial_loss(fake_pred, fake) + auxiliary_loss(fake_aux, gen_labels)) / 2 215 | 216 | # Total discriminator loss 217 | d_loss = (d_real_loss + d_fake_loss) / 2 218 | 219 | # Calculate discriminator accuracy 220 | pred = np.concatenate([real_aux.data.cpu().numpy(), fake_aux.data.cpu().numpy()], axis=0) 221 | gt = np.concatenate([labels.data.cpu().numpy(), gen_labels.data.cpu().numpy()], axis=0) 222 | d_acc = np.mean(np.argmax(pred, axis=1) == gt) 223 | 224 | d_loss.backward() 225 | optimizer_D.step() 226 | 227 | print( 228 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %d%%] [G loss: %f]" 229 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), 100 * d_acc, g_loss.item()) 230 | ) 231 | batches_done = epoch * len(dataloader) + i 232 | if batches_done % opt.sample_interval == 0: 233 | sample_image(n_row=10, batches_done=batches_done) 234 | -------------------------------------------------------------------------------- /GAN & GAN Variations/cgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.June.30th 4 | Conditional GAN 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import torchvision.transforms as transforms 11 | from torchvision.utils import save_image 12 | from torch.utils.data import DataLoader 13 | from torchvision import datasets 14 | from torch.autograd import Variable 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch 18 | 19 | os.makedirs("images", exist_ok=True) 20 | 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 23 | parser.add_argument("--batch_size", type=int, default=256, help="size of the batches") 24 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 25 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 26 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 27 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 28 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 29 | parser.add_argument("--n_classes", type=int, default=10, help="number of classes for dataset") 30 | parser.add_argument("--img_size", type=int, default=32, help="size of each image dimension") 31 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 32 | parser.add_argument("--sample_interval", type=int, default=400, help="interval between image sampling") 33 | opt = parser.parse_args() 34 | print(opt) 35 | 36 | img_shape = (opt.channels, opt.img_size, opt.img_size) 37 | 38 | cuda = True if torch.cuda.is_available() else False 39 | 40 | 41 | class Generator(nn.Module): 42 | def __init__(self): 43 | super(Generator, self).__init__() 44 | 45 | self.label_emb = nn.Embedding(opt.n_classes, opt.n_classes) 46 | 47 | def block(in_feat, out_feat, normalize=True): 48 | layers = [nn.Linear(in_feat, out_feat)] 49 | if normalize: 50 | layers.append(nn.BatchNorm1d(out_feat, 0.8)) 51 | layers.append(nn.LeakyReLU(0.2, inplace=True)) 52 | return layers 53 | 54 | self.model = nn.Sequential( 55 | *block(opt.latent_dim + opt.n_classes, 128, normalize=False), 56 | *block(128, 256), 57 | *block(256, 512), 58 | *block(512, 1024), 59 | nn.Linear(1024, int(np.prod(img_shape))), 60 | nn.Tanh() 61 | ) 62 | 63 | def forward(self, noise, labels): 64 | # Concatenate label embedding and image to produce input 65 | gen_input = torch.cat((self.label_emb(labels), noise), -1) 66 | img = self.model(gen_input) 67 | img = img.view(img.size(0), *img_shape) 68 | return img 69 | 70 | 71 | class Discriminator(nn.Module): 72 | def __init__(self): 73 | super(Discriminator, self).__init__() 74 | 75 | self.label_embedding = nn.Embedding(opt.n_classes, opt.n_classes) 76 | 77 | self.model = nn.Sequential( 78 | nn.Linear(opt.n_classes + int(np.prod(img_shape)), 512), 79 | nn.LeakyReLU(0.2, inplace=True), 80 | nn.Linear(512, 512), 81 | nn.Dropout(0.4), 82 | nn.LeakyReLU(0.2, inplace=True), 83 | nn.Linear(512, 512), 84 | nn.Dropout(0.4), 85 | nn.LeakyReLU(0.2, inplace=True), 86 | nn.Linear(512, 1), 87 | ) 88 | 89 | def forward(self, img, labels): 90 | # Concatenate label embedding and image to produce input 91 | d_in = torch.cat((img.view(img.size(0), -1), self.label_embedding(labels)), -1) 92 | validity = self.model(d_in) 93 | return validity 94 | 95 | 96 | # Loss functions 97 | adversarial_loss = torch.nn.MSELoss() 98 | 99 | # Initialize generator and discriminator 100 | generator = Generator() 101 | discriminator = Discriminator() 102 | 103 | if cuda: 104 | generator.cuda() 105 | discriminator.cuda() 106 | adversarial_loss.cuda() 107 | 108 | # Configure data loader 109 | os.makedirs("../../data/mnist", exist_ok=True) 110 | dataloader = torch.utils.data.DataLoader( 111 | datasets.MNIST( 112 | "../../data/mnist", 113 | train=True, 114 | download=True, 115 | transform=transforms.Compose( 116 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 117 | ), 118 | ), 119 | batch_size=opt.batch_size, 120 | shuffle=True, 121 | ) 122 | 123 | # Optimizers 124 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 125 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 126 | 127 | FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 128 | LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor 129 | 130 | 131 | def sample_image(n_row, batches_done): 132 | """Saves a grid of generated digits ranging from 0 to n_classes""" 133 | # Sample noise 134 | z = Variable(FloatTensor(np.random.normal(0, 1, (n_row ** 2, opt.latent_dim)))) 135 | # Get labels ranging from 0 to n_classes for n rows 136 | labels = np.array([num for _ in range(n_row) for num in range(n_row)]) 137 | labels = Variable(LongTensor(labels)) 138 | gen_imgs = generator(z, labels) 139 | save_image(gen_imgs.data, "images/%d.png" % batches_done, nrow=n_row, normalize=True) 140 | 141 | 142 | # ---------- 143 | # Training 144 | # ---------- 145 | 146 | for epoch in range(opt.n_epochs): 147 | for i, (imgs, labels) in enumerate(dataloader): 148 | 149 | batch_size = imgs.shape[0] 150 | 151 | # Adversarial ground truths 152 | valid = Variable(FloatTensor(batch_size, 1).fill_(1.0), requires_grad=False) 153 | fake = Variable(FloatTensor(batch_size, 1).fill_(0.0), requires_grad=False) 154 | 155 | # Configure input 156 | real_imgs = Variable(imgs.type(FloatTensor)) 157 | labels = Variable(labels.type(LongTensor)) 158 | 159 | # ----------------- 160 | # Train Generator 161 | # ----------------- 162 | 163 | optimizer_G.zero_grad() 164 | 165 | # Sample noise and labels as generator input 166 | z = Variable(FloatTensor(np.random.normal(0, 1, (batch_size, opt.latent_dim)))) 167 | gen_labels = Variable(LongTensor(np.random.randint(0, opt.n_classes, batch_size))) 168 | 169 | # Generate a batch of images 170 | gen_imgs = generator(z, gen_labels) 171 | 172 | # Loss measures generator's ability to fool the discriminator 173 | validity = discriminator(gen_imgs, gen_labels) 174 | g_loss = adversarial_loss(validity, valid) 175 | print(g_loss) 176 | g_loss.backward() 177 | optimizer_G.step() 178 | 179 | # --------------------- 180 | # Train Discriminator 181 | # --------------------- 182 | 183 | optimizer_D.zero_grad() 184 | 185 | # Loss for real images 186 | validity_real = discriminator(real_imgs, labels) 187 | d_real_loss = adversarial_loss(validity_real, valid) 188 | 189 | # Loss for fake images 190 | validity_fake = discriminator(gen_imgs.detach(), gen_labels) 191 | d_fake_loss = adversarial_loss(validity_fake, fake) 192 | 193 | # Total discriminator loss 194 | d_loss = (d_real_loss + d_fake_loss) / 2 195 | 196 | d_loss.backward() 197 | optimizer_D.step() 198 | 199 | print( 200 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 201 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item()) 202 | ) 203 | 204 | batches_done = epoch * len(dataloader) + i 205 | if batches_done % opt.sample_interval == 0: 206 | sample_image(n_row=10, batches_done=batches_done) 207 | -------------------------------------------------------------------------------- /GAN & GAN Variations/cogan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.July.4th 4 | Coupled Generative Adversarial Networks 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import scipy 11 | import itertools 12 | import mnistm 13 | import torchvision.transforms as transforms 14 | from torchvision.utils import save_image 15 | from torch.utils.data import DataLoader 16 | from torchvision import datasets 17 | from torch.autograd import Variable 18 | import torch.nn as nn 19 | import torch.nn.functional as F 20 | import torch 21 | 22 | os.makedirs("images", exist_ok=True) 23 | 24 | parser = argparse.ArgumentParser() 25 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 26 | parser.add_argument("--batch_size", type=int, default=32, help="size of the batches") 27 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 28 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 29 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 30 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 31 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 32 | parser.add_argument("--img_size", type=int, default=32, help="size of each image dimension") 33 | parser.add_argument("--channels", type=int, default=3, help="number of image channels") 34 | parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples") 35 | opt = parser.parse_args() 36 | print(opt) 37 | 38 | img_shape = (opt.channels, opt.img_size, opt.img_size) 39 | 40 | cuda = True if torch.cuda.is_available() else False 41 | 42 | 43 | def weights_init_normal(m): 44 | classname = m.__class__.__name__ 45 | if classname.find("Linear") != -1: 46 | torch.nn.init.normal_(m.weight.data, 0.0, 0.02) 47 | elif classname.find("BatchNorm") != -1: 48 | torch.nn.init.normal_(m.weight.data, 1.0, 0.02) 49 | torch.nn.init.constant_(m.bias.data, 0.0) 50 | 51 | 52 | class CoupledGenerators(nn.Module): 53 | def __init__(self): 54 | super(CoupledGenerators, self).__init__() 55 | 56 | self.init_size = opt.img_size // 4 57 | self.fc = nn.Sequential(nn.Linear(opt.latent_dim, 128 * self.init_size ** 2)) 58 | 59 | self.shared_conv = nn.Sequential( 60 | nn.BatchNorm2d(128), 61 | nn.Upsample(scale_factor=2), 62 | nn.Conv2d(128, 128, 3, stride=1, padding=1), 63 | nn.BatchNorm2d(128, 0.8), 64 | nn.LeakyReLU(0.2, inplace=True), 65 | nn.Upsample(scale_factor=2), 66 | ) 67 | self.G1 = nn.Sequential( 68 | nn.Conv2d(128, 64, 3, stride=1, padding=1), 69 | nn.BatchNorm2d(64, 0.8), 70 | nn.LeakyReLU(0.2, inplace=True), 71 | nn.Conv2d(64, opt.channels, 3, stride=1, padding=1), 72 | nn.Tanh(), 73 | ) 74 | self.G2 = nn.Sequential( 75 | nn.Conv2d(128, 64, 3, stride=1, padding=1), 76 | nn.BatchNorm2d(64, 0.8), 77 | nn.LeakyReLU(0.2, inplace=True), 78 | nn.Conv2d(64, opt.channels, 3, stride=1, padding=1), 79 | nn.Tanh(), 80 | ) 81 | 82 | def forward(self, noise): 83 | out = self.fc(noise) 84 | out = out.view(out.shape[0], 128, self.init_size, self.init_size) 85 | img_emb = self.shared_conv(out) 86 | img1 = self.G1(img_emb) 87 | img2 = self.G2(img_emb) 88 | return img1, img2 89 | 90 | 91 | class CoupledDiscriminators(nn.Module): 92 | def __init__(self): 93 | super(CoupledDiscriminators, self).__init__() 94 | 95 | def discriminator_block(in_filters, out_filters, bn=True): 96 | block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1)] 97 | if bn: 98 | block.append(nn.BatchNorm2d(out_filters, 0.8)) 99 | block.extend([nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)]) 100 | return block 101 | 102 | self.shared_conv = nn.Sequential( 103 | *discriminator_block(opt.channels, 16, bn=False), 104 | *discriminator_block(16, 32), 105 | *discriminator_block(32, 64), 106 | *discriminator_block(64, 128), 107 | ) 108 | # The height and width of downsampled image 109 | ds_size = opt.img_size // 2 ** 4 110 | self.D1 = nn.Linear(128 * ds_size ** 2, 1) 111 | self.D2 = nn.Linear(128 * ds_size ** 2, 1) 112 | 113 | def forward(self, img1, img2): 114 | # Determine validity of first image 115 | out = self.shared_conv(img1) 116 | out = out.view(out.shape[0], -1) 117 | validity1 = self.D1(out) 118 | # Determine validity of second image 119 | out = self.shared_conv(img2) 120 | out = out.view(out.shape[0], -1) 121 | validity2 = self.D2(out) 122 | 123 | return validity1, validity2 124 | 125 | 126 | # Loss function 127 | adversarial_loss = torch.nn.MSELoss() 128 | 129 | # Initialize models 130 | coupled_generators = CoupledGenerators() 131 | coupled_discriminators = CoupledDiscriminators() 132 | 133 | if cuda: 134 | coupled_generators.cuda() 135 | coupled_discriminators.cuda() 136 | 137 | # Initialize weights 138 | coupled_generators.apply(weights_init_normal) 139 | coupled_discriminators.apply(weights_init_normal) 140 | 141 | # Configure data loader 142 | os.makedirs("../../data/mnist", exist_ok=True) 143 | dataloader1 = torch.utils.data.DataLoader( 144 | datasets.MNIST( 145 | "../../data/mnist", 146 | train=True, 147 | download=True, 148 | transform=transforms.Compose( 149 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 150 | ), 151 | ), 152 | batch_size=opt.batch_size, 153 | shuffle=True, 154 | ) 155 | 156 | os.makedirs("../../data/mnistm", exist_ok=True) 157 | dataloader2 = torch.utils.data.DataLoader( 158 | mnistm.MNISTM( 159 | "../../data/mnistm", 160 | train=True, 161 | download=True, 162 | transform=transforms.Compose( 163 | [ 164 | transforms.Resize(opt.img_size), 165 | transforms.ToTensor(), 166 | transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), 167 | ] 168 | ), 169 | ), 170 | batch_size=opt.batch_size, 171 | shuffle=True, 172 | ) 173 | 174 | # Optimizers 175 | optimizer_G = torch.optim.Adam(coupled_generators.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 176 | optimizer_D = torch.optim.Adam(coupled_discriminators.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 177 | 178 | Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 179 | 180 | # ---------- 181 | # Training 182 | # ---------- 183 | 184 | for epoch in range(opt.n_epochs): 185 | for i, ((imgs1, _), (imgs2, _)) in enumerate(zip(dataloader1, dataloader2)): 186 | 187 | batch_size = imgs1.shape[0] 188 | 189 | # Adversarial ground truths 190 | valid = Variable(Tensor(batch_size, 1).fill_(1.0), requires_grad=False) 191 | fake = Variable(Tensor(batch_size, 1).fill_(0.0), requires_grad=False) 192 | 193 | # Configure input 194 | imgs1 = Variable(imgs1.type(Tensor).expand(imgs1.size(0), 3, opt.img_size, opt.img_size)) 195 | imgs2 = Variable(imgs2.type(Tensor)) 196 | 197 | # ------------------ 198 | # Train Generators 199 | # ------------------ 200 | 201 | optimizer_G.zero_grad() 202 | 203 | # Sample noise as generator input 204 | z = Variable(Tensor(np.random.normal(0, 1, (batch_size, opt.latent_dim)))) 205 | 206 | # Generate a batch of images 207 | gen_imgs1, gen_imgs2 = coupled_generators(z) 208 | # Determine validity of generated images 209 | validity1, validity2 = coupled_discriminators(gen_imgs1, gen_imgs2) 210 | 211 | g_loss = (adversarial_loss(validity1, valid) + adversarial_loss(validity2, valid)) / 2 212 | 213 | g_loss.backward() 214 | optimizer_G.step() 215 | 216 | # ---------------------- 217 | # Train Discriminators 218 | # ---------------------- 219 | 220 | optimizer_D.zero_grad() 221 | 222 | # Determine validity of real and generated images 223 | validity1_real, validity2_real = coupled_discriminators(imgs1, imgs2) 224 | validity1_fake, validity2_fake = coupled_discriminators(gen_imgs1.detach(), gen_imgs2.detach()) 225 | 226 | d_loss = ( 227 | adversarial_loss(validity1_real, valid) 228 | + adversarial_loss(validity1_fake, fake) 229 | + adversarial_loss(validity2_real, valid) 230 | + adversarial_loss(validity2_fake, fake) 231 | ) / 4 232 | 233 | d_loss.backward() 234 | optimizer_D.step() 235 | 236 | print( 237 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 238 | % (epoch, opt.n_epochs, i, len(dataloader1), d_loss.item(), g_loss.item()) 239 | ) 240 | 241 | batches_done = epoch * len(dataloader1) + i 242 | if batches_done % opt.sample_interval == 0: 243 | gen_imgs = torch.cat((gen_imgs1.data, gen_imgs2.data), 0) 244 | save_image(gen_imgs, "images/%d.png" % batches_done, nrow=8, normalize=True) 245 | -------------------------------------------------------------------------------- /GAN & GAN Variations/dcgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.Oct.30th 4 | Deep Convolutional Generative Adversarial Networks 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import torchvision.transforms as transforms 11 | from torchvision.utils import save_image 12 | from torch.utils.data import DataLoader 13 | from torchvision import datasets 14 | from torch.autograd import Variable 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch 18 | 19 | os.makedirs("images", exist_ok=True) 20 | 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 23 | parser.add_argument("--batch_size", type=int, default=256, help="size of the batches") 24 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 25 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 26 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 27 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 28 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 29 | parser.add_argument("--img_size", type=int, default=32, help="size of each image dimension") 30 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 31 | parser.add_argument("--sample_interval", type=int, default=400, help="interval between image sampling") 32 | opt = parser.parse_args() 33 | print(opt) 34 | 35 | cuda = True if torch.cuda.is_available() else False 36 | 37 | 38 | def weights_init_normal(m): 39 | classname = m.__class__.__name__ 40 | print(classname) 41 | if classname.find("Conv") != -1: 42 | torch.nn.init.normal_(m.weight.data, 0.0, 0.02) 43 | elif classname.find("BatchNorm2d") != -1: 44 | torch.nn.init.normal_(m.weight.data, 1.0, 0.02) 45 | torch.nn.init.constant_(m.bias.data, 0.0) 46 | 47 | 48 | class Generator(nn.Module): 49 | def __init__(self): 50 | super(Generator, self).__init__() 51 | 52 | self.init_size = opt.img_size // 4 53 | self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128 * self.init_size ** 2)) 54 | def conv_blocks(): 55 | x1 = nn.BatchNorm2d(128) 56 | self.conv_blocks = nn.Sequential( 57 | nn.BatchNorm2d(128), 58 | nn.Upsample(scale_factor=2), 59 | nn.Conv2d(128, 128, 3, stride=1, padding=1), 60 | nn.BatchNorm2d(128, 0.8), 61 | nn.LeakyReLU(0.2, inplace=True), 62 | nn.Upsample(scale_factor=2), 63 | nn.Conv2d(128, 64, 3, stride=1, padding=1), 64 | nn.BatchNorm2d(64, 0.8), 65 | nn.LeakyReLU(0.2, inplace=True), 66 | nn.Conv2d(64, opt.channels, 3, stride=1, padding=1), 67 | nn.Tanh(), 68 | ) 69 | 70 | def forward(self, z): 71 | out = self.l1(z) 72 | out = out.view(out.shape[0], 128, self.init_size, self.init_size) 73 | img = self.conv_blocks(out) 74 | return img 75 | 76 | 77 | class Discriminator(nn.Module): 78 | def __init__(self): 79 | super(Discriminator, self).__init__() 80 | 81 | def discriminator_block(in_filters, out_filters, bn=True): 82 | block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1), nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)] 83 | if bn: 84 | block.append(nn.BatchNorm2d(out_filters, 0.8)) 85 | return block 86 | 87 | self.model = nn.Sequential( 88 | *discriminator_block(opt.channels, 16, bn=False), 89 | *discriminator_block(16, 32), 90 | *discriminator_block(32, 64), 91 | *discriminator_block(64, 128), 92 | ) 93 | 94 | # The height and width of downsampled image 95 | ds_size = opt.img_size // 2 ** 4 96 | self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid()) 97 | 98 | def forward(self, img): 99 | out = self.model(img) 100 | out = out.view(out.shape[0], -1) 101 | validity = self.adv_layer(out) 102 | 103 | return validity 104 | 105 | 106 | # Loss function 107 | adversarial_loss = torch.nn.BCELoss() 108 | 109 | # Initialize generator and discriminator 110 | generator = Generator() 111 | discriminator = Discriminator() 112 | 113 | if cuda: 114 | generator.cuda() 115 | discriminator.cuda() 116 | adversarial_loss.cuda() 117 | 118 | # Initialize weights 119 | generator.apply(weights_init_normal) 120 | discriminator.apply(weights_init_normal) 121 | 122 | # Configure data loader 123 | os.makedirs("../../data/mnist", exist_ok=True) 124 | dataloader = torch.utils.data.DataLoader( 125 | datasets.MNIST( 126 | "../../data/mnist", 127 | train=True, 128 | download=True, 129 | transform=transforms.Compose( 130 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 131 | ), 132 | ), 133 | batch_size=opt.batch_size, 134 | shuffle=True, 135 | ) 136 | 137 | # Optimizers 138 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 139 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 140 | 141 | Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 142 | 143 | # ---------- 144 | # Training 145 | # ---------- 146 | 147 | for epoch in range(opt.n_epochs): 148 | for i, (imgs, _) in enumerate(dataloader): 149 | 150 | # Adversarial ground truths 151 | valid = Variable(Tensor(imgs.shape[0], 1).fill_(1.0), requires_grad=False) 152 | fake = Variable(Tensor(imgs.shape[0], 1).fill_(0.0), requires_grad=False) 153 | 154 | # Configure input 155 | real_imgs = Variable(imgs.type(Tensor)) 156 | 157 | # ----------------- 158 | # Train Generator 159 | # ----------------- 160 | 161 | optimizer_G.zero_grad() 162 | 163 | # Sample noise as generator input 164 | z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim)))) 165 | 166 | # Generate a batch of images 167 | gen_imgs = generator(z) 168 | 169 | # Loss measures generator's ability to fool the discriminator 170 | g_loss = adversarial_loss(discriminator(gen_imgs), valid) 171 | 172 | g_loss.backward() 173 | optimizer_G.step() 174 | 175 | # --------------------- 176 | # Train Discriminator 177 | # --------------------- 178 | 179 | optimizer_D.zero_grad() 180 | 181 | # Measure discriminator's ability to classify real from generated samples 182 | real_loss = adversarial_loss(discriminator(real_imgs), valid) 183 | fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake) 184 | d_loss = (real_loss + fake_loss) / 2 185 | 186 | d_loss.backward() 187 | optimizer_D.step() 188 | 189 | print( 190 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 191 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item()) 192 | ) 193 | 194 | batches_done = epoch * len(dataloader) + i 195 | if batches_done % opt.sample_interval == 0: 196 | save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True) 197 | -------------------------------------------------------------------------------- /GAN & GAN Variations/gan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.Oct.20th 4 | Generative Adversarial Networks 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import torchvision.transforms as transforms 11 | from torchvision.utils import save_image 12 | from torch.utils.data import DataLoader 13 | from torchvision import datasets 14 | from torch.autograd import Variable 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch 18 | 19 | # 创建文件夹 20 | os.makedirs("images", exist_ok=True) 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 24 | parser.add_argument("--batch_size", type=int, default=128, help="size of the batches") 25 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 26 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 27 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 28 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 29 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 30 | parser.add_argument("--img_size", type=int, default=28, help="size of each image dimension") 31 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 32 | parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples") 33 | opt = parser.parse_args() 34 | print(opt) 35 | 36 | # (1, 28, 28) 37 | img_shape = (opt.channels, opt.img_size, opt.img_size) 38 | 39 | cuda = True if torch.cuda.is_available() else False 40 | 41 | 42 | class Generator(nn.Module): 43 | def __init__(self): 44 | super(Generator, self).__init__() 45 | 46 | def block(in_feat, out_feat, normalize=True): 47 | layers = [nn.Linear(in_feat, out_feat)] 48 | if normalize: 49 | layers.append(nn.BatchNorm1d(out_feat, 0.8)) 50 | layers.append(nn.LeakyReLU(0.2, inplace=True)) # SeLU, GeLU, ReLU, Tanh, 51 | return layers 52 | 53 | self.model = nn.Sequential( 54 | *block(opt.latent_dim, 128, normalize=False), 55 | *block(128, 256), 56 | *block(256, 512), 57 | *block(512, 1024), 58 | nn.Linear(1024, int(np.prod(img_shape))), 59 | nn.Tanh() 60 | ) 61 | 62 | def forward(self, z): 63 | img = self.model(z) 64 | img = img.view(img.size(0), *img_shape) 65 | return img 66 | 67 | 68 | class Discriminator(nn.Module): 69 | def __init__(self): 70 | super(Discriminator, self).__init__() 71 | # sequential不能做端到端(这个输出是另外一个的输入)架构,只能用函数做端到端 72 | self.model = nn.Sequential( 73 | nn.Linear(int(np.prod(img_shape)), 512), 74 | nn.LeakyReLU(0.2, inplace=True), 75 | nn.Linear(512, 256), 76 | nn.LeakyReLU(0.2, inplace=True), 77 | nn.Linear(256, 1), 78 | nn.Sigmoid(), 79 | ) 80 | 81 | def forward(self, img): 82 | img_flat = img.view(img.size(0), -1) 83 | validity = self.model(img_flat) 84 | 85 | return validity 86 | 87 | 88 | # Loss function 89 | adversarial_loss = torch.nn.BCELoss() 90 | 91 | # Initialize generator and discriminator 92 | generator = Generator() 93 | discriminator = Discriminator() 94 | 95 | if cuda: 96 | generator.cuda() 97 | discriminator.cuda() 98 | adversarial_loss.cuda() 99 | 100 | # Configure data loader 101 | os.makedirs("../../data/mnist", exist_ok=True) 102 | print(transforms.Resize(opt.img_size)) 103 | dataloader = torch.utils.data.DataLoader( 104 | datasets.MNIST( 105 | "../../data/mnist", 106 | train=True, 107 | download=True, 108 | transform=transforms.Compose( 109 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 110 | ), 111 | ), 112 | batch_size=opt.batch_size, 113 | shuffle=True, 114 | ) 115 | 116 | # Optimizers 117 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 118 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 119 | 120 | Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 121 | 122 | # ---------- 123 | # Training 124 | # ---------- 125 | 126 | for epoch in range(opt.n_epochs): 127 | for i, (imgs, _) in enumerate(dataloader): 128 | 129 | # Adversarial ground truths 130 | # 标准值不能更新权重——做BCE LOSS 131 | valid = Variable(Tensor(imgs.size(0), 1).fill_(1.0), requires_grad=False) 132 | fake = Variable(Tensor(imgs.size(0), 1).fill_(0.0), requires_grad=False) 133 | # print(valid) 134 | # Configure input 135 | real_imgs = Variable(imgs.type(Tensor)) 136 | 137 | # ----------------- 138 | # Train Generator 139 | # ----------------- 140 | 141 | optimizer_G.zero_grad() 142 | 143 | # Sample noise as generator input 144 | z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim)))) 145 | 146 | # Generate a batch of images 147 | gen_imgs = generator(z) 148 | 149 | # Loss measures generator's ability to fool the discriminator 150 | g_loss = adversarial_loss(discriminator(gen_imgs), valid) 151 | 152 | g_loss.backward() 153 | optimizer_G.step() 154 | 155 | # --------------------- 156 | # Train Discriminator 157 | # --------------------- 158 | 159 | optimizer_D.zero_grad() 160 | 161 | # Measure discriminator's ability to classify real from generated samples 162 | real_loss = adversarial_loss(discriminator(real_imgs), valid) 163 | fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake) 164 | d_loss = (real_loss + fake_loss) / 2 165 | 166 | d_loss.backward() 167 | optimizer_D.step() 168 | 169 | print( 170 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 171 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item()) 172 | ) 173 | 174 | batches_done = epoch * len(dataloader) + i 175 | if batches_done % opt.sample_interval == 0: 176 | save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True) 177 | -------------------------------------------------------------------------------- /GAN & GAN Variations/sgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.Dec.12th 4 | Semi-Supervised Learning with Generative Adversarial Networks 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import torchvision.transforms as transforms 11 | from torchvision.utils import save_image 12 | from torch.utils.data import DataLoader 13 | from torchvision import datasets 14 | from torch.autograd import Variable 15 | import torch.nn as nn 16 | import torch.nn.functional as F 17 | import torch 18 | 19 | os.makedirs("images", exist_ok=True) 20 | 21 | parser = argparse.ArgumentParser() 22 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 23 | parser.add_argument("--batch_size", type=int, default=64, help="size of the batches") 24 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 25 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 26 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 27 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 28 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 29 | parser.add_argument("--num_classes", type=int, default=10, help="number of classes for dataset") 30 | parser.add_argument("--img_size", type=int, default=32, help="size of each image dimension") 31 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 32 | parser.add_argument("--sample_interval", type=int, default=400, help="interval between image sampling") 33 | opt = parser.parse_args() 34 | print(opt) 35 | 36 | cuda = True if torch.cuda.is_available() else False 37 | 38 | 39 | def weights_init_normal(m): 40 | classname = m.__class__.__name__ 41 | if classname.find("Conv") != -1: 42 | torch.nn.init.normal_(m.weight.data, 0.0, 0.02) 43 | elif classname.find("BatchNorm") != -1: 44 | torch.nn.init.normal_(m.weight.data, 1.0, 0.02) 45 | torch.nn.init.constant_(m.bias.data, 0.0) 46 | 47 | 48 | class Generator(nn.Module): 49 | def __init__(self): 50 | super(Generator, self).__init__() 51 | 52 | self.label_emb = nn.Embedding(opt.num_classes, opt.latent_dim) 53 | 54 | self.init_size = opt.img_size // 4 # Initial size before upsampling 55 | self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128 * self.init_size ** 2)) 56 | 57 | self.conv_blocks = nn.Sequential( 58 | nn.BatchNorm2d(128), 59 | nn.Upsample(scale_factor=2), 60 | nn.Conv2d(128, 128, 3, stride=1, padding=1), 61 | nn.BatchNorm2d(128, 0.8), 62 | nn.LeakyReLU(0.2, inplace=True), 63 | nn.Upsample(scale_factor=2), 64 | nn.Conv2d(128, 64, 3, stride=1, padding=1), 65 | nn.BatchNorm2d(64, 0.8), 66 | nn.LeakyReLU(0.2, inplace=True), 67 | nn.Conv2d(64, opt.channels, 3, stride=1, padding=1), 68 | nn.Tanh(), 69 | ) 70 | 71 | def forward(self, noise): 72 | out = self.l1(noise) 73 | out = out.view(out.shape[0], 128, self.init_size, self.init_size) 74 | img = self.conv_blocks(out) 75 | return img 76 | 77 | 78 | class Discriminator(nn.Module): 79 | def __init__(self): 80 | super(Discriminator, self).__init__() 81 | 82 | def discriminator_block(in_filters, out_filters, bn=True): 83 | """Returns layers of each discriminator block""" 84 | block = [nn.Conv2d(in_filters, out_filters, 3, 2, 1), nn.LeakyReLU(0.2, inplace=True), nn.Dropout2d(0.25)] 85 | if bn: 86 | block.append(nn.BatchNorm2d(out_filters, 0.8)) 87 | return block 88 | 89 | self.conv_blocks = nn.Sequential( 90 | *discriminator_block(opt.channels, 16, bn=False), 91 | *discriminator_block(16, 32), 92 | *discriminator_block(32, 64), 93 | *discriminator_block(64, 128), 94 | ) 95 | 96 | # The height and width of downsampled image 97 | ds_size = opt.img_size // 2 ** 4 98 | 99 | # Output layers 100 | self.adv_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, 1), nn.Sigmoid()) 101 | self.aux_layer = nn.Sequential(nn.Linear(128 * ds_size ** 2, opt.num_classes + 1), nn.Softmax()) 102 | 103 | def forward(self, img): 104 | out = self.conv_blocks(img) 105 | out = out.view(out.shape[0], -1) 106 | validity = self.adv_layer(out) 107 | label = self.aux_layer(out) 108 | 109 | return validity, label 110 | 111 | 112 | # Loss functions 113 | adversarial_loss = torch.nn.BCELoss() 114 | auxiliary_loss = torch.nn.CrossEntropyLoss() 115 | 116 | # Initialize generator and discriminator 117 | generator = Generator() 118 | discriminator = Discriminator() 119 | 120 | if cuda: 121 | generator.cuda() 122 | discriminator.cuda() 123 | adversarial_loss.cuda() 124 | auxiliary_loss.cuda() 125 | 126 | # Initialize weights 127 | generator.apply(weights_init_normal) 128 | discriminator.apply(weights_init_normal) 129 | 130 | # Configure data loader 131 | os.makedirs("../../data/mnist", exist_ok=True) 132 | dataloader = torch.utils.data.DataLoader( 133 | datasets.MNIST( 134 | "../../data/mnist", 135 | train=True, 136 | download=True, 137 | transform=transforms.Compose( 138 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 139 | ), 140 | ), 141 | batch_size=opt.batch_size, 142 | shuffle=True, 143 | ) 144 | 145 | # Optimizers 146 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 147 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 148 | 149 | FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 150 | LongTensor = torch.cuda.LongTensor if cuda else torch.LongTensor 151 | 152 | # ---------- 153 | # Training 154 | # ---------- 155 | 156 | for epoch in range(opt.n_epochs): 157 | for i, (imgs, labels) in enumerate(dataloader): 158 | 159 | batch_size = imgs.shape[0] 160 | 161 | # Adversarial ground truths 162 | valid = Variable(FloatTensor(batch_size, 1).fill_(1.0), requires_grad=False) 163 | fake = Variable(FloatTensor(batch_size, 1).fill_(0.0), requires_grad=False) 164 | fake_aux_gt = Variable(LongTensor(batch_size).fill_(opt.num_classes), requires_grad=False) 165 | 166 | # Configure input 167 | real_imgs = Variable(imgs.type(FloatTensor)) 168 | labels = Variable(labels.type(LongTensor)) 169 | 170 | # ----------------- 171 | # Train Generator 172 | # ----------------- 173 | 174 | optimizer_G.zero_grad() 175 | 176 | # Sample noise and labels as generator input 177 | z = Variable(FloatTensor(np.random.normal(0, 1, (batch_size, opt.latent_dim)))) 178 | 179 | # Generate a batch of images 180 | gen_imgs = generator(z) 181 | 182 | # Loss measures generator's ability to fool the discriminator 183 | validity, _ = discriminator(gen_imgs) 184 | g_loss = adversarial_loss(validity, valid) 185 | 186 | g_loss.backward() 187 | optimizer_G.step() 188 | 189 | # --------------------- 190 | # Train Discriminator 191 | # --------------------- 192 | 193 | optimizer_D.zero_grad() 194 | 195 | # Loss for real images 196 | real_pred, real_aux = discriminator(real_imgs) 197 | d_real_loss = (adversarial_loss(real_pred, valid) + auxiliary_loss(real_aux, labels)) / 2 198 | 199 | # Loss for fake images 200 | fake_pred, fake_aux = discriminator(gen_imgs.detach()) 201 | d_fake_loss = (adversarial_loss(fake_pred, fake) + auxiliary_loss(fake_aux, fake_aux_gt)) / 2 202 | 203 | # Total discriminator loss 204 | d_loss = (d_real_loss + d_fake_loss) / 2 205 | 206 | # Calculate discriminator accuracy 207 | pred = np.concatenate([real_aux.data.cpu().numpy(), fake_aux.data.cpu().numpy()], axis=0) 208 | gt = np.concatenate([labels.data.cpu().numpy(), fake_aux_gt.data.cpu().numpy()], axis=0) 209 | d_acc = np.mean(np.argmax(pred, axis=1) == gt) 210 | 211 | d_loss.backward() 212 | optimizer_D.step() 213 | 214 | print( 215 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %d%%] [G loss: %f]" 216 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), 100 * d_acc, g_loss.item()) 217 | ) 218 | 219 | batches_done = epoch * len(dataloader) + i 220 | if batches_done % opt.sample_interval == 0: 221 | save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True) 222 | -------------------------------------------------------------------------------- /GAN & GAN Variations/wgan-gp.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.July.4th 4 | Wasserstein GANs with gradient penalty 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import sys 11 | import torchvision.transforms as transforms 12 | from torchvision.utils import save_image 13 | from torch.utils.data import DataLoader 14 | from torchvision import datasets 15 | from torch.autograd import Variable 16 | import torch.nn as nn 17 | import torch.nn.functional as F 18 | import torch.autograd as autograd 19 | import torch 20 | os.makedirs("images", exist_ok=True) 21 | 22 | 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 25 | parser.add_argument("--batch_size", type=int, default=256, help="size of the batches") 26 | parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") 27 | parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") 28 | parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") 29 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 30 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 31 | parser.add_argument("--img_size", type=int, default=28, help="size of each image dimension") 32 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 33 | parser.add_argument("--n_critic", type=int, default=5, help="number of training steps for discriminator per iter") 34 | parser.add_argument("--clip_value", type=float, default=0.01, help="lower and upper clip value for disc. weights") 35 | parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples") 36 | opt = parser.parse_args() 37 | print(opt) 38 | 39 | 40 | img_shape = (opt.channels, opt.img_size, opt.img_size) 41 | cuda = True if torch.cuda.is_available() else False 42 | 43 | 44 | class Generator(nn.Module): 45 | def __init__(self): 46 | super(Generator, self).__init__() 47 | 48 | def block(in_feat, out_feat, normalize=True): 49 | layers = [nn.Linear(in_feat, out_feat)] 50 | if normalize: 51 | layers.append(nn.BatchNorm1d(out_feat, 0.8)) 52 | layers.append(nn.LeakyReLU(0.2, inplace=True)) 53 | return layers 54 | 55 | self.model = nn.Sequential( 56 | *block(opt.latent_dim, 128, normalize=False), 57 | *block(128, 256), 58 | *block(256, 512), 59 | *block(512, 1024), 60 | nn.Linear(1024, int(np.prod(img_shape))), 61 | nn.Tanh() 62 | ) 63 | 64 | def forward(self, z): 65 | img = self.model(z) 66 | img = img.view(img.shape[0], *img_shape) 67 | return img 68 | 69 | 70 | class Discriminator(nn.Module): 71 | def __init__(self): 72 | super(Discriminator, self).__init__() 73 | 74 | self.model = nn.Sequential( 75 | nn.Linear(int(np.prod(img_shape)), 512), 76 | nn.LeakyReLU(0.2, inplace=True), 77 | nn.Linear(512, 256), 78 | nn.LeakyReLU(0.2, inplace=True), 79 | nn.Linear(256, 1), 80 | ) 81 | 82 | def forward(self, img): 83 | img_flat = img.view(img.shape[0], -1) 84 | validity = self.model(img_flat) 85 | return validity 86 | 87 | 88 | # Loss weight for gradient penalty 89 | lambda_gp = 10 90 | 91 | # Initialize generator and discriminator 92 | generator = Generator() 93 | discriminator = Discriminator() 94 | 95 | if cuda: 96 | generator.cuda() 97 | discriminator.cuda() 98 | 99 | # Configure data loader 100 | os.makedirs("../../data/mnist", exist_ok=True) 101 | dataloader = torch.utils.data.DataLoader( 102 | datasets.MNIST( 103 | "../../data/mnist", 104 | train=True, 105 | download=True, 106 | transform=transforms.Compose( 107 | [transforms.Resize(opt.img_size), transforms.ToTensor(), transforms.Normalize([0.5], [0.5])] 108 | ), 109 | ), 110 | batch_size=opt.batch_size, 111 | shuffle=True, 112 | ) 113 | 114 | # Optimizers 115 | optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 116 | optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2)) 117 | 118 | Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 119 | 120 | 121 | def compute_gradient_penalty(D, real_samples, fake_samples): 122 | """Calculates the gradient penalty loss for WGAN GP""" 123 | # Random weight term for interpolation between real and fake samples 124 | alpha = Tensor(np.random.random((real_samples.size(0), 1, 1, 1))) 125 | # Get random interpolation between real and fake samples 126 | interpolates = (alpha * real_samples + ((1 - alpha) * fake_samples)).requires_grad_(True) 127 | d_interpolates = D(interpolates) 128 | fake = Variable(Tensor(real_samples.shape[0], 1).fill_(1.0), requires_grad=False) 129 | # Get gradient w.r.t. interpolates 130 | gradients = autograd.grad( 131 | outputs=d_interpolates, 132 | inputs=interpolates, 133 | grad_outputs=fake, 134 | create_graph=True, 135 | retain_graph=True, 136 | only_inputs=True, 137 | )[0] 138 | gradients = gradients.view(gradients.size(0), -1) 139 | gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean() 140 | return gradient_penalty 141 | 142 | 143 | # ---------- 144 | # Training 145 | # ---------- 146 | 147 | batches_done = 0 148 | for epoch in range(opt.n_epochs): 149 | for i, (imgs, _) in enumerate(dataloader): 150 | 151 | # Configure input 152 | real_imgs = Variable(imgs.type(Tensor)) 153 | 154 | # --------------------- 155 | # Train Discriminator 156 | # --------------------- 157 | 158 | optimizer_D.zero_grad() 159 | 160 | # Sample noise as generator input 161 | z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim)))) 162 | 163 | # Generate a batch of images 164 | fake_imgs = generator(z) 165 | 166 | # Real images 167 | real_validity = discriminator(real_imgs) 168 | # Fake images 169 | fake_validity = discriminator(fake_imgs) 170 | # Gradient penalty 171 | gradient_penalty = compute_gradient_penalty(discriminator, real_imgs.data, fake_imgs.data) 172 | # Adversarial loss 173 | d_loss = -torch.mean(real_validity) + torch.mean(fake_validity) + lambda_gp * gradient_penalty 174 | 175 | d_loss.backward() 176 | optimizer_D.step() 177 | 178 | optimizer_G.zero_grad() 179 | 180 | # Train the generator every n_critic steps 181 | if i % opt.n_critic == 0: 182 | 183 | # ----------------- 184 | # Train Generator 185 | # ----------------- 186 | 187 | # Generate a batch of images 188 | fake_imgs = generator(z) 189 | # Loss measures generator's ability to fool the discriminator 190 | # Train on fake images 191 | fake_validity = discriminator(fake_imgs) 192 | g_loss = -torch.mean(fake_validity) 193 | 194 | g_loss.backward() 195 | optimizer_G.step() 196 | 197 | print( 198 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 199 | % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item()) 200 | ) 201 | 202 | if batches_done % opt.sample_interval == 0: 203 | save_image(fake_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True) 204 | 205 | batches_done += opt.n_critic 206 | -------------------------------------------------------------------------------- /GAN & GAN Variations/wgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @Author: Alex 3 | @Date: 2022.June.30th 4 | Wasserstein GANs 5 | """ 6 | import argparse 7 | import os 8 | import numpy as np 9 | import math 10 | import sys 11 | import torchvision.transforms as transforms 12 | from torchvision.utils import save_image 13 | from torch.utils.data import DataLoader 14 | from torchvision import datasets 15 | from torch.autograd import Variable 16 | import torch.nn as nn 17 | import torch.nn.functional as F 18 | import torch 19 | 20 | os.makedirs("images", exist_ok=True) 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training") 24 | parser.add_argument("--batch_size", type=int, default=256, help="size of the batches") 25 | parser.add_argument("--lr", type=float, default=0.00005, help="learning rate") 26 | parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") 27 | parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 28 | parser.add_argument("--img_size", type=int, default=28, help="size of each image dimension") 29 | parser.add_argument("--channels", type=int, default=1, help="number of image channels") 30 | parser.add_argument("--n_critic", type=int, default=5, help="number of training steps for discriminator per iter") 31 | parser.add_argument("--clip_value", type=float, default=0.01, help="lower and upper clip value for disc. weights") 32 | parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples") 33 | opt = parser.parse_args() 34 | print(opt) 35 | 36 | img_shape = (opt.channels, opt.img_size, opt.img_size) 37 | 38 | cuda = True if torch.cuda.is_available() else False 39 | 40 | 41 | class Generator(nn.Module): 42 | def __init__(self): 43 | super(Generator, self).__init__() 44 | 45 | def block(in_feat, out_feat, normalize=True): 46 | layers = [nn.Linear(in_feat, out_feat)] 47 | if normalize: 48 | layers.append(nn.BatchNorm1d(out_feat, 0.8)) 49 | layers.append(nn.LeakyReLU(0.2, inplace=True)) 50 | return layers 51 | 52 | self.model = nn.Sequential( 53 | *block(opt.latent_dim, 128, normalize=False), 54 | *block(128, 256), 55 | *block(256, 512), 56 | *block(512, 1024), 57 | nn.Linear(1024, int(np.prod(img_shape))), 58 | nn.Tanh() 59 | ) 60 | 61 | def forward(self, z): 62 | img = self.model(z) 63 | img = img.view(img.shape[0], *img_shape) 64 | return img 65 | 66 | 67 | class Discriminator(nn.Module): 68 | def __init__(self): 69 | super(Discriminator, self).__init__() 70 | # 判别器输出不经过一个sigmoid 71 | self.model = nn.Sequential( 72 | nn.Linear(int(np.prod(img_shape)), 512), 73 | nn.LeakyReLU(0.2, inplace=True), 74 | nn.Linear(512, 256), 75 | nn.LeakyReLU(0.2, inplace=True), 76 | nn.Linear(256, 1), 77 | ) 78 | 79 | def forward(self, img): 80 | img_flat = img.view(img.shape[0], -1) 81 | validity = self.model(img_flat) 82 | return validity 83 | 84 | 85 | # Initialize generator and discriminator 86 | generator = Generator() 87 | discriminator = Discriminator() 88 | 89 | if cuda: 90 | generator.cuda() 91 | discriminator.cuda() 92 | 93 | # Configure data loader 94 | os.makedirs("../../data/mnist", exist_ok=True) 95 | dataloader = torch.utils.data.DataLoader( 96 | datasets.MNIST( 97 | "../../data/mnist", 98 | train=True, 99 | download=True,# 原始图片像素值归一化,均值0.5方差0.5,数字在0~1之间的数 100 | transform=transforms.Compose([transforms.ToTensor(), transforms.Normalize([0.5], [0.5])]), 101 | ), 102 | batch_size=opt.batch_size, 103 | shuffle=True, 104 | ) 105 | 106 | # Optimizers 优化函数改成了RMSprop 107 | optimizer_G = torch.optim.RMSprop(generator.parameters(), lr=opt.lr) 108 | optimizer_D = torch.optim.RMSprop(discriminator.parameters(), lr=opt.lr) 109 | 110 | Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor 111 | 112 | # ---------- 113 | # Training 114 | # ---------- 115 | # for name, p in discriminator.named_parameters(): 116 | # print(name) 117 | 118 | batches_done = 0 119 | for epoch in range(opt.n_epochs): 120 | # image无label,已经划分了batch的dataloader,看看预先设定的batchsize,运行完所有的batch,才进行下一个epoch 121 | # batch ,每一批里面有128个图片,一共469个batch 122 | for i, (imgs, _) in enumerate(dataloader): 123 | # Configure input,从dataloader里面得到的image 124 | real_imgs = Variable(imgs.type(Tensor)) 125 | 126 | # --------------------- 127 | # Train Discriminator 128 | # --------------------- 129 | # 每次把上一次的梯度归零重新计算 130 | optimizer_D.zero_grad() 131 | 132 | # Sample noise as generator input,均值0,方差1 133 | z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim)))) 134 | 135 | # Generate a batch of images,detach相当于flatten 136 | fake_imgs = generator(z).detach() 137 | # Adversarial loss,越小越好,两个分布越接近 138 | '''这个地方怎么控制loss反向传播向小的地方的? 139 | ''' 140 | loss_D = -torch.mean(discriminator(real_imgs)) + torch.mean(discriminator(fake_imgs)) 141 | 142 | loss_D.backward() 143 | # 网络参数更新,每个batch的每张图片都进行更新 144 | optimizer_D.step() 145 | 146 | # Clip weights of discriminator 147 | '''怎么看都有什么parameters?,clip both weights and bias 148 | ''' 149 | 150 | 151 | for p in discriminator.parameters(): 152 | # 在范围中间的不变,否则变成最大值或者最小值——clamp 153 | # print(p.data.type) 154 | p.data.clamp_(-opt.clip_value, opt.clip_value) 155 | 156 | # Train the generator every n_critic iterations 157 | # 每五张图片更新一次生成器的参数 158 | if i % opt.n_critic == 0: 159 | 160 | # ----------------- 161 | # Train Generator 162 | # ----------------- 163 | 164 | optimizer_G.zero_grad() 165 | 166 | # Generate a batch of images 167 | gen_imgs = generator(z) 168 | # Adversarial loss 169 | loss_G = -torch.mean(discriminator(gen_imgs)) 170 | 171 | loss_G.backward() 172 | optimizer_G.step() 173 | 174 | print( 175 | "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]" 176 | % (epoch, opt.n_epochs, batches_done % len(dataloader), len(dataloader), loss_D.item(), loss_G.item()) 177 | ) 178 | 179 | # If at save interval => save generated image samples 180 | # # 如果在保证图像间隔 => 保存生成的图像样本 181 | if batches_done % opt.sample_interval == 0: 182 | save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True) 183 | batches_done += 1 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generative Models 2 | 3 | This repository is dedicated to sharing open-source implementations of fundamental generative models in artificial general intelligence (AGI). The goal is to provide a comprehensive resource for researchers and practitioners interested in exploring and experimenting with these models. 4 | 5 | ## Models Included 6 | 7 | Currently, this repository includes the following generative models: 8 | 9 | - Variational Autoencoder (VAE) 10 | - Generative Adversarial Network (GAN) 11 | - Autoregressive models 12 | - Normalizing Flows 13 | - Boltzmann Machines 14 | - Hopfield Networks 15 | - Diffusion Model 16 | 17 | Each model has a separate directory containing the implementation code and a brief description of the model. 18 | 19 | ## Usage 20 | 21 | The implementations are provided in Python using PyTorch. To use these models, clone this repository and install the required dependencies specified in the `requirements.txt` file. Each model has its own script for training and generating samples. The script can be run using the command `python _train.py` and `python _generate.py`. 22 | 23 | ## Contributions 24 | 25 | Contributions are welcome in the form of new models, bug fixes, or improved implementations. If you wish to contribute, please follow the guidelines provided in the `CONTRIBUTING.md` file. 26 | 27 | ## License 28 | 29 | This repository is licensed under the MIT License. See the `LICENSE` file for more details. 30 | 31 | ## References 32 | 33 | The implementations in this repository are based on the following papers: 34 | 35 | - [Kingma, D. P., & Welling, M. (2013). Auto-encoding variational bayes. arXiv preprint arXiv:1312.6114.](https://arxiv.org/abs/1312.6114) 36 | - [Goodfellow, I., Pouget-Abadie, J., Mirza, M., Xu, B., Warde-Farley, D., Ozair, S., ... & Bengio, Y. (2014). Generative adversarial nets. In Advances in neural information processing systems (pp. 2672-2680).](https://arxiv.org/abs/1406.2661) 37 | - [Oord, A. van den, Kalchbrenner, N., & Kavukcuoglu, K. (2016). Pixel recurrent neural networks. arXiv preprint arXiv:1601.06759.](https://arxiv.org/abs/1601.06759) 38 | - [Dinh, L., Sohl-Dickstein, J., & Bengio, S. (2017). Density estimation using real NVP. arXiv preprint arXiv:1605.08803.](https://arxiv.org/abs/1605.08803) 39 | - [Hinton, G. E. (2002). Training products of experts by minimizing contrastive divergence. Neural computation, 14(8), 1771-1800.](https://www.cs.toronto.edu/~hinton/absps/hinton_techreport.pdf) 40 | - [Hopfield, J. J. (1982). Neural networks and physical systems with emergent collective computational abilities. Proceedings of the national academy of sciences, 79(8), 2554-2558.](https://www.pnas.org/content/79/8/2554) 41 | --------------------------------------------------------------------------------