日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【CV实战】年轻人的第一个GAN项目应该是什么样的(Pytorch框架)?

發布時間:2025/3/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CV实战】年轻人的第一个GAN项目应该是什么样的(Pytorch框架)? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎大家來到咱們的深度學習CV項目實戰專欄,GAN是當下非常熱門的技術,本次我們給大家介紹如何來訓練自己的第1個生成對抗網絡項目。

作者&編輯 | 言有三

本項目結果展示

本文篇幅:4000字

背景要求:會使用Python和Pytorch深度學習開源框架

附帶資料:開源代碼一份,支持Pytorch

數據一份:文末有獲取方法

1 項目背景

GAN無疑是這幾年深度學習領域里最酷的技術,不管是理論的研究,還是GAN在圖像生成,圖像翻譯,語音圖像等基礎領域的應用,都非常的豐富。我們公眾號從很早以前開始就輸出過非常多的GAN相關資源,包括免費與付費的視頻課,知識星球中的GAN模型原理解讀專題,公眾號的GAN付費專欄,大家可以閱讀下面的文章了解詳情。

【總結】從視頻到圖文,代碼實戰,有三AI-GAN學習資料匯總!

2 項目解讀

為了讓大家能夠快速上手,本次我們給大家介紹一個非常適合新手入門的項目,使用DCGAN來進行圖片生成,項目效果如文章開頭的圖片。

2.1?數據獲取

本次我們完成一個人臉表情圖像生成的任務,使用的數據集也是多次在咱們的項目中出現過的數據集,我們選擇了其中一類表情的數據,如下:

數據的讀取非常簡單,直接使用torchvision的ImageFolder接口即可,與我們以前介紹過的圖像分類任務相同,核心代碼如下,不再贅述。

## 讀取數據

dataroot = "mouth/"

dataset = datasets.ImageFolder(root=dataroot,

? ? ? ? ? ? ? ? ? ? ? ? ? ?transform=transforms.Compose([

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?transforms.Resize(image_size),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?transforms.CenterCrop(image_size),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?transforms.ToTensor(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?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=workers)

不熟悉的朋友可以閱讀:【CV實戰】年輕人的第一個深度學習CV項目應該是什么樣的?(支持13大深度學習開源框架)

2.2?判別器定義

接下來我們再看判別器的定義,它就是一個圖像分類模型,與原始DCGAN論文中的參數配置略有差異。

class Discriminator(nn.Module):

? ? def __init__(self, ndf=64, nc=3):

? ? ? ? super(Discriminator, self).__init__()

? ? ? ? self.ndf = ndf

? ? ? ? self.nc = nc

? ? ? ? self.main = nn.Sequential(

? ? ? ? ? ? # 輸入圖片大小 (nc) x 64 x 64,輸出 (ndf) x 32 x 32

? ? ? ? ? ? nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.LeakyReLU(0.2, inplace=True),

? ? ? ? ? ? # 輸入(ndf) x 32 x 32,輸出(ndf*2) x 16 x 16

? ? ? ? ? ? nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ndf * 2),

? ? ? ? ? ? nn.LeakyReLU(0.2, inplace=True),

? ? ? ? ? ? # 輸入(ndf*2) x 16 x 16,輸出 (ndf*4) x 8 x 8

? ? ? ? ? ? nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ndf * 4),

? ? ? ? ? ? nn.LeakyReLU(0.2, inplace=True),

? ? ? ? ? ? # 輸入(ndf*4) x 8 x 8,輸出(ndf*8) x 4 x 4

? ? ? ? ? ? nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ndf * 8),

? ? ? ? ? ? nn.LeakyReLU(0.2, inplace=True),

? ? ? ? ? ? # 輸入(ndf*8) x 4 x 4,輸出1 x 1 x 1

? ? ? ? ? ? nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),

? ? ? ? ? ? nn.Sigmoid()

? ? ? ? )

? ? def forward(self, input):

? ? ? ? return self.main(input)

以上代碼定義了一個包含5層卷積,其中前面4個卷積層的卷積核大小為4×4,寬和高的步長等于2,使用了padding技術,padding大小為1,每經過一次卷積,圖像長寬都降低為原來的1/2。每一個卷積層后都跟隨一個batch normalization層和lrelu層。

????

輸出層也是一個卷積層,其特征圖大小空間尺寸為4×4,卷積核大小也是4×4,所以輸出空間層維度為1,使用sigmoid激活函數,輸出就是一個0到1之間的概率值。

2.3?生成器定義

接下來我們再看生成器的定義,它輸入一維的噪聲向量,輸出二維的圖像。

## 定義生成器與判別器

class Generator(nn.Module):

? ? def __init__(self, nz=100, ngf=64, nc=3):

? ? ? ? super(Generator, self).__init__()

? ? ? ? self.ngf = ngf

? ? ? ? self.nz = nz

? ? ? ? self.nc = nc

? ? ? ? self.main = nn.Sequential(

? ? ? ? ? ? # 輸入噪聲向量Z,(ngf*8) x 4 x 4特征圖

? ? ? ? ? ? nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ngf * 8),

? ? ? ? ? ? nn.ReLU(True),

? ? ? ? ? ? # 輸入(ngf*8) x 4 x 4特征圖,輸出(ngf*8) x 4 x 4

? ? ? ? ? ? nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ngf * 4),

? ? ? ? ? ? nn.ReLU(True),

? ? ? ? ? ? # 輸入(ngf*4) x 8 x 8,輸出(ngf*2) x 16 x 16

? ? ? ? ? ? nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ngf * 2),

? ? ? ? ? ? nn.ReLU(True),

? ? ? ? ? ? # 輸入(ngf*2) x 16 x 16,輸出(ngf) x 32 x 32

? ? ? ? ? ? nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.BatchNorm2d(ngf),

? ? ? ? ? ? nn.ReLU(True),

? ? ? ? ? ? # 輸入(ngf) x 32 x 32,輸出(nc) x 64 x 64

? ? ? ? ? ? nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),

? ? ? ? ? ? nn.Tanh()

? ? ? ? )

? ? def forward(self, input):

? ? ? ? return self.main(input)

可以看出,總共包含5個上采樣層。其中前4個上采樣層后接有BN層,和ReLU層。第一個上采樣層將輸入的一維噪聲向量經過一個上采樣層生成4×4大小的圖,然后經過后面的4個上采樣層得到輸出。前面4層的激活函數為ReLU,最后一層的激活函數為Tanh。

2.4 優化目標與方法定義

損失函數使用了BCE交叉熵損失,真樣本和假樣本標簽分別為1和0。

# 損失函數

criterion = nn.BCELoss()

# 真假標簽

real_label = 1.0

fake_label = 0.0

判別器和生成器都采用了Adam方法作為優化器,且使用了同樣的配置,定義如下:

lr = 0.0003

beta1 = 0.5

optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))

optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))

?

3?模型訓練

接下來進行模型訓練,添加可視化部分,緩存中間結果,核心的迭代代碼如下:

for epoch in range(num_epochs):

? ? lossG = 0.0

? ? lossD = 0.0

? ? for i, data in enumerate(dataloader, 0):

? ? ? ? ############################

? ? ? ? # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))

? ? ? ? ###########################

? ? ? ? ## 訓練真實圖片

? ? ? ? netD.zero_grad()

? ? ? ? real_data = data[0].to(device)

? ? ? ? b_size = real_data.size(0)

? ? ? ? label = torch.full((b_size,), real_label, device=device)

? ? ? ? output = netD(real_data).view(-1)

? ? ? ? # 計算真實圖片損失,梯度反向傳播

? ? ? ? errD_real = criterion(output, label)

? ? ? ? errD_real.backward()

? ? ? ? D_x = output.mean().item()

? ? ? ? ## 訓練生成圖片

? ? ? ? # 產生latent vectors

? ? ? ? noise = torch.randn(b_size, nz, 1, 1, device=device)

? ? ? ? # 使用G生成圖片

? ? ? ? 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_real + errD_fake

? ? ? ? optimizerD.step()

? ? ? ? ############################

? ? ? ? # (2) Update G network: maximize log(D(G(z)))

? ? ? ? ###########################

? ? ? ? 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()

? ? ? ? # 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))

? ? ? ? # 存儲損失

? ? ? ? nbatch = nbatch + 1

? ? ? ? lossG = lossG + errG.item()

? ? ? ? lossD = lossD + errD.item()

? ? ? ? # 對固定的噪聲向量,存儲生成的結果

? ? ? ? if (iters % 20 == 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))

? ? ? ? ? ? i = vutils.make_grid(fake, padding=2, normalize=True)

? ? ? ? ? ? fig = plt.figure(figsize=(8, 8))

? ? ? ? ? ? plt.imshow(np.transpose(i, (1, 2, 0)))

? ? ? ? ? ? plt.axis('off')? # 關閉坐標軸

? ? ? ? ? ? plt.savefig("out/%d_%d.png" % (epoch, iters))

? ? ? ? ? ? plt.close(fig)

? ? ? ? iters += 1

? ? writer.add_scalar('data/lossG', lossG, epoch)

? ? writer.add_scalar('data/lossD', lossD, epoch)

torch.save(netG.state_dict(),'models/netG.pt')

訓練結果曲線如下:

由于標準GAN的損失與模型的生成結果之間的關系不像以前介紹的任務那么直觀,我們應該以實際生成的圖片結果為準,下面從左到右分別是第0,10,100個epoch的生成結果。

從圖結果來看,隨著訓練的進行,逐漸生成了許多有意義且非常逼真的樣本,在10個epoch的時候生成圖片都有明顯的瑕疵,到100個epoch時已經開始生成一些逼真的樣本。不過最終生成的圖像仍然有一部分效果很差,這是因為DCGAN本身模型性能所限,后續可以使用更好的模型進行改進。

4 模型測試

上面已經訓練好了模型,我們接下來的目標,就是要用它來做推理,真正把模型用起來。

import torch

import torch.nn as nn

import torchvision.utils as vutils

import matplotlib.pyplot as plt

from net import Generator

device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu")

netG = Generator().to(device)

## 載入模型權重

modelpath = sys.argv[1]?

savepath = sys.argv[2]?

netG.load_state_dict(torch.load(modelpath,map_location=lambda storage,loc: storage))

netG.eval() ## 設置推理模式,使得dropout和batchnorm等網絡層在train和val模式間切換

torch.no_grad() ## 停止autograd模塊的工作,以起到加速和節省顯存

nz = 100

for i in range(0,100):

? ? noise = torch.randn(64, nz, 1, 1, device=device)

? ? fake = netG(noise).detach().cpu()

? ? rows = vutils.make_grid(fake, padding=2, normalize=True)

? ? fig = plt.figure(figsize=(8, 8))

? ? plt.imshow(np.transpose(rows, (1, 2, 0)))

? ? plt.axis('off')? # 關閉坐標軸

? ? plt.savefig(os.path.join(savepath,"%d.png" % (i)))

? ? plt.close(fig)

推理的核心代碼就是使用torch.load函數載入生成器模型,然后輸入隨機的噪聲向量,得到生成的結果。

下面展示了一些結果。

從圖中我們可以看到,總體的生成結果還是不錯的,不過本次的任務還有許多可以提升的空間,包括但不限于:(1) 做更多的數據增強。(2) 改進模型。這些就留給讀者去進行實驗。

?5?資源獲取和拓展學習

本文的完整代碼,可以在我們的開源項目中獲取,項目地址如下。

https://github.com/longpeng2008/yousan.ai

由于數據集較大,如果想要獲得數據集,請到有三AI知識星球中下載,當然你也完全可以將其替換成自己的數據集:

有三AI知識星球鏈接與介紹如下:

【雜談】有三AI知識星球指導手冊出爐!和公眾號相比又有哪些內容?

如果想要學習更多GAN的內容,請閱讀下面的文章了解生態的相關資料。

【總結】從視頻到圖文,代碼實戰,有三AI-GAN學習資料匯總!

總結

本次我們完成了一個GAN圖像生成項目的全部流程,本次任務和前面的CV分類實戰與分割實戰是一脈相承的,使用了相同的數據集,大家可以一起閱讀學習。

轉載文章請后臺聯系

侵權必究

往期文章

  • 【CV夏季劃】2021年有三AI-CV夏季劃出爐,沖刺秋招,從CV基礎到模型優化徹底掌握

  • 【CV秋季劃】模型優化很重要,如何循序漸進地學習好?

  • 【CV秋季劃】人臉算法那么多,如何循序漸進地學習好?

  • 【CV秋季劃】圖像質量提升與編輯有哪些研究和應用,如何循序漸進地學習好?

  • 【CV秋季劃】生成對抗網絡GAN有哪些研究和應用,如何循序漸進地學習好?

總結

以上是生活随笔為你收集整理的【CV实战】年轻人的第一个GAN项目应该是什么样的(Pytorch框架)?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。