發(fā)布時(shí)間:2023-12-07 20:27:15 瀏覽量:149次
最近AI繪畫(huà)讓人工智能再次走進(jìn)大眾視野。在人工智能發(fā)展早起,一直認(rèn)為人工智能能實(shí)現(xiàn)的功能非常有限。通常都是些死板的東西,像是下棋、問(wèn)答之類的,不具有創(chuàng)造性。那時(shí)的人們應(yīng)該想不到現(xiàn)在的AI已經(jīng)能夠繪畫(huà)、譜曲、作詩(shī)了。這些曾被認(rèn)為是人類獨(dú)有的東西,如今也被AI涉獵了。今天我們要討論的就是現(xiàn)今大火的AI繪畫(huà),我們來(lái)看看AI是不是真的有了創(chuàng)造力,還是只是不停的搬運(yùn)。
可以實(shí)現(xiàn)AI繪畫(huà)的模型有很多種,這里我們討論Conditional GAN和Stable Diffusion兩種模型?,F(xiàn)在已經(jīng)有了對(duì)應(yīng)的商業(yè)版本,比如昆侖天宮的AI繪圖就是采用了Stable Diffusion分支模型。
這里我們討論Conditional GAN(Generative Adversarial Network)實(shí)現(xiàn)AI的原理。在講Conditional GAN之前,我們來(lái)看看GAN是怎么回事。
生成網(wǎng)絡(luò)一直被認(rèn)為是賦予AI創(chuàng)造力的突破口,生成包括文本生成、圖像生成、音頻生成等。
GAN是一種比較成熟的生成網(wǎng)絡(luò),通常用來(lái)生成圖像。GAN有許多變種,包括DCGAN、CycleGAN等。
GAN的中文名叫生成對(duì)抗網(wǎng)絡(luò),在提到GAN時(shí)經(jīng)常會(huì)用兩個(gè)對(duì)立的角色來(lái)舉例。一個(gè)是造假專家,專門(mén)負(fù)責(zé)制作贗品;另一個(gè)是鑒別專家,專門(mén)負(fù)責(zé)鑒定贗品。他們最開(kāi)始都不是專家,而是在對(duì)抗中學(xué)習(xí),最終造假專家能夠制造出人都難以識(shí)別出來(lái)的贗品。最終我們會(huì)拋棄鑒別專家,讓造假專家為我們服務(wù)。
上面提到的造假專家就是G網(wǎng)絡(luò),也就是Generator;而鑒別專家就是D網(wǎng)絡(luò),也就是Discriminator。它們?cè)诨ハ鄬?duì)抗中學(xué)習(xí),最終成為各自領(lǐng)域的專家,這就是GAN的思想。
下面我們以生成動(dòng)漫頭像的例子來(lái)討論GAN網(wǎng)絡(luò)的Generator和Discriminator。
首先討論Generator,它在GAN中充當(dāng)造假的作用,也是用它來(lái)生成圖像。Generator接收一個(gè)隨機(jī)變量,這個(gè)隨機(jī)變量滿足一種特定的簡(jiǎn)單分布,比如高斯分布。接收輸入的隨機(jī)變量后,網(wǎng)絡(luò)經(jīng)過(guò)運(yùn)算生成一個(gè)非常長(zhǎng)的向量,我們可以把這個(gè)向量reshape成w×h×3,也就是彩色圖像。
Generator的具體結(jié)構(gòu)可以是多種多樣的,通常是以卷積為基礎(chǔ)的網(wǎng)絡(luò)。比如在DCGAN中,Generator由5層反卷積組成,其網(wǎng)絡(luò)結(jié)構(gòu)如下圖:
輸入一個(gè)維度為100的向量,輸出一張64×64×3的圖像,其PyTorch實(shí)現(xiàn)如下:
class Generator(nn.Module):
def __init__(self, ngpu):
super(Generator, self).__init__()
self.ngpu = ngpu
self.main = nn.Sequential(
# input is Z, going into a convolution
nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),
nn.BatchNorm2d(ngf * 8),
nn.ReLU(True),
# state size. (ngf*8) x 4 x 4
nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf * 4),
nn.ReLU(True),
# state size. (ngf*4) x 8 x 8
nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf * 2),
nn.ReLU(True),
# state size. (ngf*2) x 16 x 16
nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
nn.BatchNorm2d(ngf),
nn.ReLU(True),
# state size. (ngf) x 32 x 32
nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
nn.Tanh()
# state size. (nc) x 64 x 64
)
def forward(self, input):
return self.main(input)
Discriminator是GAN中非常重要的一個(gè)角色,它是一個(gè)接受一個(gè)圖片輸入的網(wǎng)絡(luò),輸入的圖像會(huì)包含一部分真實(shí)圖像real(我們收集的動(dòng)漫圖像),還會(huì)包含一部分虛假圖像fake(Generator生成的圖像),然后輸出一個(gè)結(jié)果。這個(gè)結(jié)果可以是fake是真實(shí)圖像的概率,也可以是fake的類別(0表示假,1表示真)。對(duì)于Discriminator而言,它的目的就是調(diào)整網(wǎng)絡(luò)參數(shù),讓網(wǎng)絡(luò)知道fake圖像是假的。
關(guān)于Discriminator的結(jié)構(gòu),并沒(méi)有非常固定的約束,通常是一個(gè)卷積網(wǎng)絡(luò)。這里同樣參考DCGAN,這里實(shí)現(xiàn)PyTorch的一個(gè)實(shí)現(xiàn):
class Discriminator(nn.Module):
def __init__(self, ngpu):
super(Discriminator, self).__init__()
self.ngpu = ngpu
self.main = nn.Sequential(
# input is (nc) x 64 x 64
nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
# state size. (ndf) x 32 x 32
nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 2),
nn.LeakyReLU(0.2, inplace=True),
# state size. (ndf*2) x 16 x 16
nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 4),
nn.LeakyReLU(0.2, inplace=True),
# state size. (ndf*4) x 8 x 8
nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),
nn.BatchNorm2d(ndf * 8),
nn.LeakyReLU(0.2, inplace=True),
# state size. (ndf*8) x 4 x 4
nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
def forward(self, input):
return self.main(input)
這里比較特別的就是LeakyReLU的使用。
有了Generator和Discriminator就可以組成GAN網(wǎng)絡(luò)了。
最開(kāi)始Generator和Discriminator是兩個(gè)懵懂小孩,Generator不知道如何生成,Discriminator也不知道如何辨別。GAN網(wǎng)絡(luò)的訓(xùn)練分為下面幾個(gè)步驟。
· 第一步:訓(xùn)練Discriminator網(wǎng)絡(luò),此時(shí)Generator提供的照片都是噪聲,先訓(xùn)練Discriminator可以讓 Discriminator知道如何區(qū)分真實(shí)圖像和噪聲
· 第二步:固定Discriminator,訓(xùn)練Generator,讓Generator生成的圖像能夠瞞過(guò)Discriminator
· 第三步:再循環(huán)訓(xùn)練Discriminator-Generator,直到Generator生成的圖像能夠滿足我們的需求
· 第四步:用Generator生成圖像
上述步驟可以看作下圖:
以上就是GAN網(wǎng)絡(luò)的訓(xùn)練過(guò)程。其實(shí)就是Generator和Discriminator交替訓(xùn)練的過(guò)程,其PyTorch實(shí)現(xiàn)如下:
# Create the generator
netG = Generator(ngpu).to(device)
if (device.type == 'cuda') and (ngpu > 1):
netG = nn.DataParallel(netG, list(range(ngpu)))
netG.apply(weights_init)
# Create the Discriminator
netD = Discriminator(ngpu).to(device)
if (device.type == 'cuda') and (ngpu > 1):
netD = nn.DataParallel(netD, list(range(ngpu)))
netD.apply(weights_init)
criterion = nn.BCELoss()
fixed_noise = torch.randn(64, nz, 1, 1, device=device)
real_label = 1.
fake_label = 0.
optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))
# Training Loop
# Lists to keep track of progress
img_list = []
G_losses = []
D_losses = []
iters = 0
print("Starting Training Loop...")
# For each epoch
for epoch in range(num_epochs):
# For each batch in the dataloader
for i, data in enumerate(dataloader, 0):
############################
# (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))
###########################
## Train with all-real batch
netD.zero_grad()
# Format batch
real_cpu = data[0].to(device)
b_size = real_cpu.size(0)
label = torch.full((b_size,), real_label, dtype=torch.float, device=device)
# Forward pass real batch through D
output = netD(real_cpu).view(-1)
# Calculate loss on all-real batch
errD_real = criterion(output, label)
# Calculate gradients for D in backward pass
errD_real.backward()
D_x = output.mean().item()
## Train with all-fake batch
# Generate batch of latent vectors
noise = torch.randn(b_size, nz, 1, 1, device=device)
# Generate fake image batch with G
fake = netG(noise)
label.fill_(fake_label)
# Classify all fake batch with D
output = netD(fake.detach()).view(-1)
# Calculate D's loss on the all-fake batch
errD_fake = criterion(output, label)
# Calculate the gradients for this batch, accumulated (summed) with previous gradients
errD_fake.backward()
D_G_z1 = output.mean().item()
# Compute error of D as sum over the fake and the real batches
errD = errD_real + errD_fake
# Update D
optimizerD.step()
############################
# (2) Update G network: maximize log(D(G(z)))
###########################
netG.zero_grad()
label.fill_(real_label) # fake labels are real for generator cost
# Since we just updated D, perform another forward pass of all-fake batch through D
output = netD(fake).view(-1)
# Calculate G's loss based on this output
errG = criterion(output, label)
# Calculate gradients for G
errG.backward()
D_G_z2 = output.mean().item()
# Update G
optimizerG.step()
# Output training stats
if i % 50 == 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))
# Save Losses for plotting later
G_losses.append(errG.item())
D_losses.append(errD.item())
# Check how the generator is doing by saving G's output on fixed_noise
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
經(jīng)過(guò)一段時(shí)間的訓(xùn)練后,我們就可以生成一些動(dòng)漫圖像了。關(guān)于DCGAN的代碼實(shí)現(xiàn)可以參考
https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#
sphx-glr-beginner-dcgan-faces-tutorial-py。
通過(guò)上面的GAN網(wǎng)絡(luò),我們可以生成動(dòng)漫圖像。但是這個(gè)生成是不可控的,我們只知道它生成的是動(dòng)漫圖像,至于圖像內(nèi)容我們無(wú)法得知。我們無(wú)法根據(jù)描述來(lái)生成圖像,這個(gè)是GAN網(wǎng)絡(luò)的局限,因此提出一種變形叫Conditional GAN,這種GAN網(wǎng)絡(luò)可以解決上面的問(wèn)題。
Conditional GAN不同于GAN的地方在于其Generator和Discriminator接收參數(shù)的數(shù)量不同。Generator在接收隨機(jī)變量的同時(shí)還接收一個(gè)“思想向量”,這個(gè)思想向量可以是對(duì)句子的一個(gè)編碼。此時(shí)我們的Generator的結(jié)構(gòu)變成了輸入兩個(gè)向量,輸出一個(gè)圖像的網(wǎng)絡(luò)。
比如上圖,我們將red eyes這個(gè)句子轉(zhuǎn)化成向量交給Generator,然后讓它生成紅眼的動(dòng)漫圖像。通過(guò)修改x我們可以得到不同的圖像,又因?yàn)閦這個(gè)隨機(jī)變量的存在,我們即使給同樣的x也可以得到不同的圖像。
為了能讓網(wǎng)絡(luò)學(xué)習(xí)到文字和描述之間的關(guān)系,我們需要準(zhǔn)備好(文字描述-圖像)這種組合的數(shù)據(jù)集。
Discriminator同樣需要輸入兩個(gè)向量,分別是Generator生成的圖像和輸入到Generator的x,然后輸出是否正確。
交給Generator的訓(xùn)練數(shù)據(jù)需要把(正確描述-正確圖像)作為類別1,把(正確描述,不正確圖像)、(正確描述,正確圖像,但圖像和描述不匹配)作為類別0。
如果不包含(正確描述,正確圖像,但圖像和描述不匹配)作為訓(xùn)練數(shù)據(jù),我們的網(wǎng)絡(luò)得不到很好的結(jié)果。
知道了Generator和Discriminator網(wǎng)絡(luò)后,我們可以使用和GAN類似的方式進(jìn)行訓(xùn)練,最后的Generator就是我們的AI畫(huà)師了。我們給它文字描述,它給我們返回一張對(duì)應(yīng)的圖。
Stable Diffusion和Conditional GAN有很多相似的地方,因?yàn)槎伎梢杂脕?lái)解決Text-to-image的問(wèn)題,因此模型都是接收一個(gè)文本以及影響圖像的高斯噪聲。只不過(guò)使用的網(wǎng)絡(luò)結(jié)構(gòu)有所區(qū)別,而且Stable Diffusion引入了Latent Diffusion,讓訓(xùn)練更加順利。
Latent Diffusion包括了三個(gè)部分,分別是自編碼器、U-Net、Text-Encoder。
其中自編碼器包括編碼器和解碼器兩部分。編碼器的輸出會(huì)交給U-Net進(jìn)行處理。而U-Net得輸出則會(huì)交給解碼器。
U-Net在接收編碼器輸入的同時(shí),還接收一個(gè)句子的向量。這個(gè)句向量由Text-Encoder給出。下圖是U-Net的結(jié)構(gòu)。
因?yàn)閁-Net是在低維空間上工作的,因此Latent Diffusion快速有效。Stable Diffusion的整體流程如下圖:
現(xiàn)在有許多現(xiàn)成的平臺(tái)可以AI繪畫(huà),相比GAN,Stable Diffusion要更擅長(zhǎng)繪畫(huà),這里可以用昆侖天宮的天工巧繪(SkyPaint)來(lái)進(jìn)行一個(gè)簡(jiǎn)單的體驗(yàn),該平臺(tái)使用的就是Stable Diffusion分支模型。下面是幾個(gè)測(cè)試的例子。
1. 戴帽子拿劍的貓
我原本的設(shè)想是得到近似穿長(zhǎng)靴的貓一樣的圖像,下面幾個(gè)結(jié)果有一些穿長(zhǎng)靴的貓的韻味
2. 梵高星空
其中第一個(gè)效果圖和原作場(chǎng)景有幾分相似的地方,而其余幾幅畫(huà)則不太一樣
3. 阿拉斯加千年不化的雪山 一架紅色直升機(jī)正在起飛
這次的描述包含很多細(xì)節(jié),紅色直升機(jī),起飛等。從下面的結(jié)果來(lái)看AI把握了這些細(xì)節(jié),每張圖都沒(méi)有太多違和感,不過(guò)細(xì)看螺旋槳還是有一些不太滿意的地方。
大家可以自己去嘗試一下AI繪圖的效果。
從Conditional GAN的實(shí)現(xiàn)來(lái)AI繪畫(huà)并不是簡(jiǎn)單的照搬,在訓(xùn)練Conditional GAN的時(shí)候,我們?cè)谧龅臅r(shí)學(xué)習(xí)到圖像的分布。對(duì)于一張64×64×3的8bit圖,可以有12288^256種組合,而這么多組合里面只有極小一部分是我們需要的圖像,而Generator網(wǎng)絡(luò)就是把z從一個(gè)簡(jiǎn)單的分布(比如高斯分布),映射一個(gè)復(fù)雜的分布(圖像的分布)。當(dāng)學(xué)習(xí)到這個(gè)分布后,我們只需要從z的分布中采樣一個(gè)點(diǎn),就可以對(duì)應(yīng)到一張圖像。這就是我們Generator在做的事情。
熱門(mén)資訊
1. 照片變漫畫(huà)效果,這4個(gè)方法操作簡(jiǎn)單有效,快來(lái)試試吧!
想將照片變成漫畫(huà)效果?這篇文章分享了4個(gè)方法,包括Photoshop、聰明靈犀、VanceAI Toongineer、醒圖,簡(jiǎn)單操作就能實(shí)現(xiàn),快來(lái)嘗試一下吧!
2. 華為手機(jī)神奇“AI修圖”功能,一鍵消除衣服!原圖變身大V領(lǐng)深V!
最近華為手機(jī)Pura70推出的“AI修圖”功能引發(fā)熱議,通過(guò)簡(jiǎn)單操作可以讓照片中的人物換裝。想了解更多這款神奇功能的使用方法嗎?點(diǎn)擊查看!
3. 四款值得推薦的AI以圖生圖軟件,有需要的趕緊來(lái)試試!
近年來(lái),人工智能逐漸走入公眾視野,其中的AI圖像生成技術(shù)尤為引人注目。只需在特定軟件中輸入關(guān)鍵詞描述語(yǔ)以及上傳參考圖就能智能高效生成符合要求的...
4. AI視頻制作神器Viggle:讓靜態(tài)人物動(dòng)起來(lái),創(chuàng)意無(wú)限!
Viggle AI是一款免費(fèi)制作視頻的AI工具,能讓靜態(tài)人物圖片動(dòng)起來(lái),快來(lái)了解Viggle AI的功能和優(yōu)勢(shì)吧!
5. Logo Diffusion——基于sd繪畫(huà)模型的AI LOGO 生成器
這下LOGO設(shè)計(jì)徹底不用求人了。接下來(lái)詳細(xì)演示一遍操作流程首先進(jìn)入Logo D... 想學(xué)習(xí)更多AI技能,比如說(shuō)關(guān)于怎么樣利用AI來(lái)提高生產(chǎn)效率、還能做什么AI...
6. 零基礎(chǔ)10分鐘生成漫畫(huà),教大家如何用AI生成自己的漫畫(huà)
接下來(lái),我將親自引導(dǎo)你,使用AI工具,創(chuàng)作一本既有趣又能帶來(lái)盈利的漫畫(huà)。我們將一起探索如何利用這個(gè)工具,發(fā)揮你的創(chuàng)意,制作出令人驚嘆的漫畫(huà)作品。讓...
7. AI顯卡繪畫(huà)排行榜:4090無(wú)懸念,最具性價(jià)比出人意料
在AI繪圖領(lǐng)域,Stable Diffusion的顯卡繪圖性能備受關(guān)注。本文整理了Stable Diffusion顯卡的硬件要求和性能表現(xiàn),以及2023年3月顯卡AI繪圖效率排行榜和性價(jià)比排行榜。歡迎查看最新的AI顯卡算力排行榜。
8. 趕緊收藏好!這4個(gè)完全免費(fèi)的AI視頻制作網(wǎng)站和工具
以下是一些免費(fèi)的AI視頻制作網(wǎng)站或工具,幫助您制作各種類型的視頻。 1. Lumen5:Lumen5是一個(gè)基于AI的視頻制作工具,可將文本轉(zhuǎn)換為視頻。 用戶可以使...
就能快速生成一幅極具藝術(shù)效果的作品,讓現(xiàn)實(shí)中不懂繪畫(huà)的人也能參與其中創(chuàng)作!真的超贊噠~趣趣分享幾款超厲害的AI繪畫(huà)軟件,提供詳細(xì)操作!有需要的快來(lái)...
10. 10個(gè)建筑AI工具,從設(shè)計(jì)到施工全覆蓋!肯定有你從來(lái)沒(méi)聽(tīng)過(guò)的
講述了建筑業(yè)比較著名的AI公司小庫(kù)科技做出的探索,在這兒就不多說(shuō)了。今天,我們?cè)囍谝?guī)劃設(shè)計(jì)、建筑方案設(shè)計(jì)、住宅設(shè)計(jì)、管道設(shè)計(jì)、出渲染圖、3D掃...
最新文章
同學(xué)您好!