怎么用b2b網(wǎng)站做排名快速優(yōu)化工具
深度學(xué)習(xí)訓(xùn)練營(yíng)之DCGAN網(wǎng)絡(luò)學(xué)習(xí)
- 原文鏈接
- 環(huán)境介紹
- DCGAN簡(jiǎn)單介紹
- 生成器(Generator)
- 判別器(Discriminator)
- 對(duì)抗訓(xùn)練
- 前置工作
- 導(dǎo)入第三方庫(kù)
- 導(dǎo)入數(shù)據(jù)
- 數(shù)據(jù)查看
- 定義模型
- 初始化權(quán)重
- 定義生成器generator
- 定義判別器
- 模型訓(xùn)練
- 定義參數(shù)
- 模型訓(xùn)練
- 結(jié)果可視化
原文鏈接
- 🍨 本文為🔗365天深度學(xué)習(xí)訓(xùn)練營(yíng) 中的學(xué)習(xí)記錄博客
- 🍦 參考文章:365天深度學(xué)習(xí)訓(xùn)練營(yíng)-第G2周:深度學(xué)習(xí)訓(xùn)練營(yíng)之DCGAN網(wǎng)絡(luò)學(xué)習(xí)
- 🍖 原作者:K同學(xué)啊|接輔導(dǎo)、項(xiàng)目定制
環(huán)境介紹
- 語(yǔ)言環(huán)境:Python3.11.4
- 編譯器:jupyter notebook
- 深度學(xué)習(xí)環(huán)境:TensorFlow2
DCGAN簡(jiǎn)單介紹
DCGAN(Deep Convolutional Generative Adversarial Network)是一種基于生成對(duì)抗網(wǎng)絡(luò)(GAN)的深度學(xué)習(xí)模型,用于生成逼真的圖像。它通過(guò)將生成器和判別器兩個(gè)網(wǎng)絡(luò)相互對(duì)抗地訓(xùn)練,以實(shí)現(xiàn)生成高質(zhì)量圖像的目標(biāo)。
DCGAN 的核心思想是使用卷積神經(jīng)網(wǎng)絡(luò)(CNN)作為生成器和判別器的網(wǎng)絡(luò)結(jié)構(gòu)。下面是 DCGAN 的一般工作原理:
生成器(Generator)
生成器接受一個(gè)隨機(jī)噪聲向量作為輸入,并使用反卷積層(或稱(chēng)為轉(zhuǎn)置卷積層)將其逐漸放大和轉(zhuǎn)換為圖像。
通過(guò)層層上采樣處理和卷積操作,生成器逐漸學(xué)習(xí)到將低分辨率噪聲向量轉(zhuǎn)化為高分辨率逼真圖像的映射。
生成器的目標(biāo)是盡可能接近真實(shí)圖像的分布,從而生成看起來(lái)真實(shí)的圖像。
判別器(Discriminator)
判別器是一個(gè)二分類(lèi)的CNN網(wǎng)絡(luò),用于區(qū)分真實(shí)圖像和生成器生成的假圖像。
判別器接受輸入圖像并輸出一個(gè)概率,表示輸入圖像是真實(shí)圖像的概率。
判別器通過(guò)對(duì)真實(shí)圖像分配較高的概率值,并對(duì)生成器生成的假圖像分配較低的概率值,來(lái)辨別真實(shí)和假的圖像。
對(duì)抗訓(xùn)練
DCGAN 的核心是通過(guò)對(duì)抗訓(xùn)練生成器和判別器來(lái)提升它們的性能(屬于是無(wú)監(jiān)督的學(xué)習(xí))。
在訓(xùn)練過(guò)程中,生成器試圖生成逼真的圖像以欺騙判別器,而判別器則努力區(qū)分真實(shí)和生成的圖像。
這里就可以理解為生成器通過(guò)盡可能地生成逼近于真實(shí)圖片的圖像來(lái)嘗試騙過(guò)判別器,而判別器就是通過(guò)盡可能地將假圖片和真圖片進(jìn)行區(qū)分,當(dāng)兩種之間發(fā)生沖突的時(shí)候,就會(huì)進(jìn)行進(jìn)一步的優(yōu)化,直到達(dá)到平衡,在后續(xù)的代碼當(dāng)中我們也可以看到生成器和判別器之間的網(wǎng)絡(luò)價(jià)格正好是相反的
生成器和判別器相互對(duì)抗地進(jìn)行訓(xùn)練,通過(guò)最小化生成器生成圖像被判別為假的概率(對(duì)抗損失)和最大化真實(shí)圖像被判別為真的概率(真實(shí)損失)來(lái)優(yōu)化網(wǎng)絡(luò)。
通過(guò)反復(fù)訓(xùn)練生成器和判別器,并使它們相互對(duì)抗地提升,最終可以得到一個(gè)生成器能夠生成高質(zhì)量逼真圖像的模型。
前置工作
導(dǎo)入第三方庫(kù)
import torch,random,os
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML
manualSeed=999#隨機(jī)數(shù)種子
print("Random Seed:",manualSeed)
random.seed(manualSeed)
torch.manual_seed(manualSeed)
torch.use_deterministic_algorithms(True)
999
導(dǎo)入數(shù)據(jù)
導(dǎo)入數(shù)據(jù)并設(shè)置超參數(shù)
dataroot="./DCGAN/"
# 數(shù)據(jù)集和上一周的一樣,所以就放在一起了
batch_size=128
image_size=64
nz=100 #z潛在的向量大小(生成器generator的尺寸)
ngf=64 #生成器中的特征圖大小
ndf=64
num_epochs=50
lr=0.00002
beta1=0.5
print(dataroot)
數(shù)據(jù)查看
進(jìn)行數(shù)據(jù)的導(dǎo)入,
-
用
ImageFolder
類(lèi)來(lái)創(chuàng)建數(shù)據(jù)集對(duì)象, -
Transforms.Compose
組合成一系列的圖像變換操作來(lái)對(duì)圖像進(jìn)行預(yù)處理 -
DataLoder
類(lèi)來(lái)創(chuàng)建一個(gè)數(shù)據(jù)加載器的對(duì)象 -
Matplotlib
庫(kù)來(lái)繪制這些圖像
dataset=dset.ImageFolder(root=dataroot,transform=transforms.Compose([transforms.Resize(image_size),transforms.CenterCrop(image_size),transforms.ToTensor(),#轉(zhuǎn)換成張量transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)),]))
dataloader=torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True,num_workers=5#使用多個(gè)線程加載數(shù)據(jù)的工作進(jìn)程數(shù))
device=torch.device=("cuda:0"if (torch.cuda.is_available())else "cpu")
print("使用的設(shè)備為 " +device)real_batch=next(iter(dataloader))
plt.figure(figsize=(8,8))
plt.axis("off")
plt.title("Training Images")
plt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:24],padding=2,normalize=True).cpu(),(1,2,0)))
定義模型
初始化權(quán)重
def weights_init(m):#獲取當(dāng)前層類(lèi)名classname=m.__class__.__name__#包含conv,表示當(dāng)前層是卷積層if classname.find('Conv')!=-1:#j均值設(shè)為0.0,標(biāo)準(zhǔn)差為0.02nn.init.normal_(m.weight.data,0.0,0.02)#直接在張量上進(jìn)行參數(shù)初始化elif classname.find('BatchNorm')!=-1:nn.init.normal_(m.weight.data,1.0,0.02)nn.init.constant_(m.bias.data,0)
定義生成器generator
class Generator(nn.Module):def __init__(self):super(Generator, self).__init__()## 模型中間塊兒self.main=nn.Sequential(nn.ConvTranspose2d(nz,ngf*8,4,1,0,bias=False),nn.BatchNorm2d(ngf*8),nn.ReLU(True),nn.ConvTranspose2d(ngf*8,ngf*4,4,2,1,bias=False),nn.BatchNorm2d(ngf*4),nn.ReLU(True),nn.ConvTranspose2d(ngf*4,ngf*2,4,2,1,bias=False),nn.BatchNorm2d(ngf*2),nn.ReLU(True),nn.ConvTranspose2d(ngf*2,ngf,4,2,1,bias=False),nn.BatchNorm2d(ngf),nn.ReLU(True),nn.ConvTranspose2d(ngf,3,4,2,1,bias=False),nn.Tanh()#Tanh激活函數(shù))def forward(self, input): return self.main(input)
#創(chuàng)建生成器
netG=Generator().to(device)
netG.apply(weights_init)
print(netG)
大家可以注意一下這個(gè)網(wǎng)絡(luò)的架構(gòu),會(huì)和后面的判別器是相反的
定義判別器
class Discriminator(nn.Module):def __init__(self):super(Discriminator,self).__init__()self.main=nn.Sequential(nn.Conv2d(3,ndf,4,2,1,bias=False),nn.LeakyReLU(0.2,inplace=True),nn.Conv2d(ndf,ndf*2,4,2,1,bias=False),nn.BatchNorm2d(ndf*2),nn.LeakyReLU(0.2,inplace=True),nn.Conv2d(ndf*2,ndf*4,4,2,1,bias=False),nn.BatchNorm2d(ndf*4),nn.LeakyReLU(0.2,inplace=True),nn.Conv2d(ndf*4,ndf*8,4,2,1,bias=False),nn.BatchNorm2d(ndf*8),nn.LeakyReLU(0.2,inplace=True),nn.Conv2d(ndf*8,1,4,1,0,bias=False),nn.Sigmoid()#Sigmoid激活函數(shù))def forward(self, input):return self.main(input)
#創(chuàng)建判別器
netD=Discriminator().to(device)
netD.apply(weights_init)#weights_init初始化所有權(quán)重
print(netD)
模型訓(xùn)練
定義參數(shù)
criterion=nn.BCELoss()
fixed_noise=torch.randn(64,nz,1,1,device=device)
real_label=1.#1表示真實(shí)
fake_label=0.#0表示虛假生成#設(shè)置優(yōu)化器
optimizerD=optim.Adam(netD.parameters(),lr=lr,betas=(beta1,0.999))
optimizerG=optim.Adam(netG.parameters(),lr=lr,betas=(beta1,0.999))
模型訓(xùn)練
img_list=[]#用存儲(chǔ)生成的圖像列表
G_losses=[]
D_losses=[]
iters=0#迭代次數(shù)
print("開(kāi)始訓(xùn)練Starting Training Loop..")
for epoch in range(num_epochs):#dataloader中的每個(gè)batchfor i,data in enumerate(dataloader,0):#####最大化log(D(x))+log(1-D(G(z)))####netD.zero_grad()#清除判別器網(wǎng)絡(luò)的梯度 real_cpu=data[0].to(device)b_size=real_cpu.size(0)label=torch.full((b_size,),real_label,dtype=torch.float,device=device) #輸入判別器進(jìn)行前向傳播output=netD(real_cpu).view(-1)errD_real=criterion(output,label)errD_real.backward()D_x=output.mean().item()#計(jì)算批判別器對(duì)真實(shí)圖像樣本的輸出平均值'''使用生成圖像樣本進(jìn)行訓(xùn)練'''noise=torch.randn(b_size,nz,1,1,device=device)fake=netG(noise)label.fill_(fake_label)output=netD(fake.detach()).view(-1)errD_fake=criterion(output,label)errD_fake.backward()D_G_z1=output.mean().item()errD=errD_fake+errD_realoptimizerD.step()'''更新生成網(wǎng)絡(luò)'''netG.zero_grad()label.fill_(real_label)output=netD(fake).view(-1)errG=criterion(output,label)errG.backward()D_G_z2=output.mean().item()optimizerG.step()if i % 400 == 0:print('[%d/%d][%d/%d]\tLoss_D:%.4f\tLoss_G:%.4f\tD(x):%.4f\tD(G(z)):%.4f / %.4f'% (epoch, num_epochs, i, len(dataloader), errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))#保存損失值G_losses.append(errG.item())D_losses.append(errD.item())#保存固定噪聲上的輸出來(lái)檢查生成器的性能 if(iters%500==0)or((epoch==num_epochs-1)and(i==len(dataloader)-1)):with torch.no_grad():fake=netG(fixed_noise).detach().cpu()img_list.append(vutils.make_grid(fake,padding=2,normalize=True))iters+=1
開(kāi)始訓(xùn)練Starting Training Loop..
[0/50][0/36] Loss_D:1.3728 Loss_G:1.0315 D(x):0.6877 D(G(z)):0.5443 / 0.4221
[1/50][0/36] Loss_D:0.3502 Loss_G:2.3366 D(x):0.9120 D(G(z)):0.1921 / 0.1283
[2/50][0/36] Loss_D:0.1925 Loss_G:3.2138 D(x):0.9384 D(G(z)):0.0957 / 0.0582
[3/50][0/36] Loss_D:0.1281 Loss_G:3.6822 D(x):0.9570 D(G(z)):0.0674 / 0.0370
[4/50][0/36] Loss_D:0.1669 Loss_G:4.0574 D(x):0.9308 D(G(z)):0.0563 / 0.0262
[5/50][0/36] Loss_D:0.1337 Loss_G:4.2146 D(x):0.9428 D(G(z)):0.0551 / 0.0209
[6/50][0/36] Loss_D:0.0729 Loss_G:4.5967 D(x):0.9696 D(G(z)):0.0344 / 0.0138
[7/50][0/36] Loss_D:0.0770 Loss_G:4.6592 D(x):0.9747 D(G(z)):0.0344 / 0.0133
[8/50][0/36] Loss_D:0.0932 Loss_G:4.8994 D(x):0.9742 D(G(z)):0.0303 / 0.0105
[9/50][0/36] Loss_D:0.0790 Loss_G:5.0675 D(x):0.9819 D(G(z)):0.0269 / 0.0083
[10/50][0/36] Loss_D:0.0496 Loss_G:5.0618 D(x):0.9807 D(G(z)):0.0278 / 0.0085
[11/50][0/36] Loss_D:0.0452 Loss_G:5.2256 D(x):0.9800 D(G(z)):0.0221 / 0.0069
[12/50][0/36] Loss_D:0.0332 Loss_G:5.4038 D(x):0.9833 D(G(z)):0.0148 / 0.0058
[13/50][0/36] Loss_D:0.0370 Loss_G:5.2032 D(x):0.9815 D(G(z)):0.0171 / 0.0064
[14/50][0/36] Loss_D:0.0326 Loss_G:5.5015 D(x):0.9838 D(G(z)):0.0149 / 0.0053
[15/50][0/36] Loss_D:0.0368 Loss_G:5.4651 D(x):0.9872 D(G(z)):0.0162 / 0.0055
[16/50][0/36] Loss_D:0.0349 Loss_G:5.6891 D(x):0.9849 D(G(z)):0.0186 / 0.0047
[17/50][0/36] Loss_D:0.0214 Loss_G:5.5402 D(x):0.9925 D(G(z)):0.0133 / 0.0048
[18/50][0/36] Loss_D:0.0216 Loss_G:5.6668 D(x):0.9912 D(G(z)):0.0123 / 0.0041
[19/50][0/36] Loss_D:0.0219 Loss_G:5.6475 D(x):0.9919 D(G(z)):0.0132 / 0.0046
[20/50][0/36] Loss_D:0.0165 Loss_G:5.7313 D(x):0.9956 D(G(z)):0.0118 / 0.0040
[21/50][0/36] Loss_D:0.0203 Loss_G:5.7859 D(x):0.9939 D(G(z)):0.0138 / 0.0040
[22/50][0/36] Loss_D:0.0266 Loss_G:5.7094 D(x):0.9850 D(G(z)):0.0104 / 0.0040
[23/50][0/36] Loss_D:0.0207 Loss_G:5.7429 D(x):0.9899 D(G(z)):0.0101 / 0.0038
...
[46/50][0/36] Loss_D:0.0100 Loss_G:6.6160 D(x):0.9945 D(G(z)):0.0044 / 0.0024
[47/50][0/36] Loss_D:0.0114 Loss_G:7.1434 D(x):0.9927 D(G(z)):0.0025 / 0.0017
[48/50][0/36] Loss_D:0.0039 Loss_G:7.2856 D(x):0.9980 D(G(z)):0.0019 / 0.0012
[49/50][0/36] Loss_D:0.0198 Loss_G:6.2926 D(x):0.9882 D(G(z)):0.0048 / 0.0029
結(jié)果可視化
plt.figure(figsize=(10, 5))
plt.title('Generator and Discriminator Loss During Training')
plt.plot(G_losses, label='G')
plt.plot(D_losses, label='D')
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.legend()
plt.show()
阿哲,訓(xùn)練效果好差,不知道是不是硬件的問(wèn)題
fig = plt.figure(figsize=(8, 8))
plt.axis('off')ims = [[plt.imshow(np.transpose(i, (1, 2, 0)), animated=True)] for i in img_list]
ani = animation.ArtistAnimation(fig, ims, interval=1000, repeat_delay=1000, blit=True)HTML(ani.to_jshtml())