最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Python用GAN生成對抗性神經(jīng)網(wǎng)絡(luò)判別模型擬合多維數(shù)組、分類識別手寫數(shù)字圖像可視化

2023-09-06 18:40 作者:拓端tecdat  | 我要投稿

全文鏈接:https://tecdat.cn/?p=33566

原文出處:拓端數(shù)據(jù)部落公眾號

生成對抗網(wǎng)絡(luò)(GAN)是一種神經(jīng)網(wǎng)絡(luò),可以生成類似于人類產(chǎn)生的材料,如圖像、音樂、語音或文本。最近我們被客戶要求撰寫關(guān)于GAN生成對抗性神經(jīng)網(wǎng)絡(luò)的研究報告,包括一些圖形和統(tǒng)計輸出。

近年來,GAN一直是研究的熱門話題。Facebook的AI研究總監(jiān)Yann LeCun稱對抗訓練是“過去10年中最有趣的機器學習領(lǐng)域的想法”。

本文將介紹以下內(nèi)容:

  • 什么是生成模型以及它與判別模型的區(qū)別

  • GAN的結(jié)構(gòu)和訓練方式

  • 如何使用PyTorch構(gòu)建GAN

  • 如何使用GPU和PyTorch訓練GAN以實現(xiàn)實際應用

什么是生成對抗網(wǎng)絡(luò)?

生成對抗網(wǎng)絡(luò)是一種可以學習模仿給定數(shù)據(jù)分布的機器學習系統(tǒng)。它們最早是由深度學習專家Ian Goodfellow及其同事在2014年的一篇NeurIPS論文中提出的。

GAN由兩個神經(jīng)網(wǎng)絡(luò)組成,一個網(wǎng)絡(luò)用于生成數(shù)據(jù),另一個網(wǎng)絡(luò)用于區(qū)分真實數(shù)據(jù)和假數(shù)據(jù)(因此模型具有"對抗"的性質(zhì))。雖然生成數(shù)據(jù)的結(jié)構(gòu)并不新鮮,但在圖像和視頻生成方面,GAN取得了令人印象深刻的成果,例如:

  • 使用CycleGAN進行風格轉(zhuǎn)換,可以對圖像進行多種令人信服的風格轉(zhuǎn)換

  • 利用StyleGAN生成人臉,如網(wǎng)站This Person Does Not Exist上所示

判別模型與生成模型

如果您學習過神經(jīng)網(wǎng)絡(luò),那么您接觸到的大多數(shù)應用很可能是使用判別模型實現(xiàn)的。而生成對抗網(wǎng)絡(luò)屬于一類不同的模型,被稱為生成模型。

在訓練過程中,您會使用一個算法來調(diào)整模型的參數(shù)。目標是通過最小化損失函數(shù)使模型學習到給定輸入的輸出的概率分布。在訓練階段之后,您可以使用該模型通過估計輸入最可能對應的數(shù)字來對新的手寫數(shù)字圖像進行分類,如下圖所示:

您可以將用于分類問題的判別模型想象成使用訓練數(shù)據(jù)來學習類別之間邊界的區(qū)塊。然后,它們使用這些邊界來區(qū)分輸入并預測其類別。數(shù)學上來說,判別模型學習輸出y給定輸入x的條件概率P(y|x)。

除了神經(jīng)網(wǎng)絡(luò),其他結(jié)構(gòu)也可以用作判別模型,例如邏輯回歸模型和支持向量機(SVM)。

然而,生成模型(如GAN)被訓練為描述數(shù)據(jù)集的生成方式,以概率模型的形式進行。通過從生成模型中采樣,您可以生成新的數(shù)據(jù)。雖然判別模型常用于有監(jiān)督學習,但生成模型通常與無標簽的數(shù)據(jù)集一起使用,并可被視為一種無監(jiān)督學習的形式。

使用手寫數(shù)字數(shù)據(jù)集,您可以訓練一個生成模型來生成新的數(shù)字。在訓練階段,您會使用某種算法來調(diào)整模型的參數(shù),以最小化損失函數(shù)并學習訓練集的概率分布。然后,通過訓練好的模型,您可以生成新的樣本,如下圖所示:

為了輸出新的樣本,生成模型通??紤]到一個隨機元素,該隨機元素影響模型生成的樣本。用于驅(qū)動生成器的隨機樣本是從"潛在空間"中獲得的,在該空間中,向量表示一種壓縮形式的生成樣本。

與判別模型不同,生成模型學習輸入數(shù)據(jù)x的概率P(x),通過具有輸入數(shù)據(jù)分布,它們能夠生成新的數(shù)據(jù)實例。

盡管GAN近年來受到了廣泛關(guān)注,但它們并不是唯一可用作生成模型的架構(gòu)。除了GAN,還有其他各種生成模型架構(gòu),例如:

  • 伯勞茲曼機(Boltzmann machines)

  • 變分自編碼器(Variational autoencoders)

  • 隱馬爾可夫模型(Hidden Markov models)

  • 預測序列中的下一個詞的模型,如GPT-2

然而,由于其在圖像和視頻生成方面取得的令人興奮的結(jié)果,GAN最近引起了公眾的最大關(guān)注。

現(xiàn)在您已了解生成模型的基礎(chǔ)知識,接下來將介紹GAN的工作原理和訓練方法。

生成對抗網(wǎng)絡(luò)(GAN)的架構(gòu)

生成對抗網(wǎng)絡(luò)由兩個神經(jīng)網(wǎng)絡(luò)組成,一個稱為"生成器"(generator),另一個稱為"判別器"(discriminator)。

生成器的作用是估計真實樣本的概率分布,以提供類似真實數(shù)據(jù)的生成樣本。而判別器則被訓練來估計給定樣本來自真實數(shù)據(jù)的概率,而不是由生成器提供的。

這些結(jié)構(gòu)被稱為生成對抗網(wǎng)絡(luò),因為生成器和判別器被訓練以相互競爭:生成器試圖在愚弄判別器方面變得更好,而判別器試圖在識別生成樣本方面變得更好。

為了理解GAN的訓練過程,考慮一個示例,包含一個由二維樣本(x?,?x?)組成的數(shù)據(jù)集,其中?x? 在 0 到 2π 的區(qū)間內(nèi),x? = sin(x?),如下圖所示:

可以看到,這個數(shù)據(jù)集由位于正弦曲線上的點(x?,?x?)組成,具有非常特殊的分布。GAN的整體結(jié)構(gòu)用于生成類似數(shù)據(jù)集樣本的(x??,?x??)對,如下圖所示:

生成器G接收來自潛在空間的隨機數(shù)據(jù),并且其作用是生成類似真實樣本的數(shù)據(jù)。在這個示例中,我們有一個二維的潛在空間,因此生成器接收隨機的(z?,?z?)對,并要求將它們轉(zhuǎn)化為類似真實樣本的形式。

生成對抗網(wǎng)絡(luò)(GAN)

作為生成對抗網(wǎng)絡(luò)的初次實驗,你將實現(xiàn)前面一節(jié)中描述的示例。

要運行這個示例,你需要使用PyTorch庫,可以通過Anaconda Python發(fā)行版和conda軟件包和環(huán)境管理系統(tǒng)來安裝。

首先,創(chuàng)建一個conda環(huán)境并激活它:

$ conda create --name gan$ conda activate gan

當你激活conda環(huán)境后,你的命令提示符會顯示環(huán)境的名稱,即gan。然后你可以在該環(huán)境中安裝必要的包:

$ conda install -c pytorch pytorch=1.4.0$ conda install matplotlib jupyter

由于PyTorch是一個非?;钴S的開發(fā)框架,其API可能會在新版本中發(fā)生變化。為了確保示例代碼能夠運行,你需要安裝特定的版本1.4.0。

除了PyTorch,你還將使用Matplotlib進行繪圖,并在Jupyter Notebook中運行交互式代碼。這并不是強制性的,但它有助于進行機器學習項目的工作。

在打開Jupyter Notebook之前,你需要注冊conda環(huán)境gan,以便可以將其作為內(nèi)核來創(chuàng)建Notebook。要做到這一點,在激活gan環(huán)境后,運行以下命令:

$ python -m ipykernel install --user --name gan

現(xiàn)在你可以通過運行jupyter notebook來打開Jupyter Notebook。通過點擊“新建”然后選擇“gan”來創(chuàng)建一個新的Notebook。

在Notebook中,首先導入必要的庫:

import torchfrom torch import nnimport mathimport matplotlib.pyplot as plt

在這里,你使用torch導入了PyTorch庫。你還導入nn,為了能夠以更簡潔的方式設(shè)置神經(jīng)網(wǎng)絡(luò)。然后你導入math來獲取pi常數(shù)的值,并按照慣例導入Matplotlib繪圖工具為plt

為了使實驗在任何機器上都能完全復現(xiàn),最好設(shè)置一個隨機生成器種子。在PyTorch中,可以通過運行以下代碼來實現(xiàn):

torch.manual_seed(111)

數(shù)字111代表用于初始化隨機數(shù)生成器的隨機種子,它用于初始化神經(jīng)網(wǎng)絡(luò)的權(quán)重。盡管實驗具有隨機性,但只要使用相同的種子,它應該產(chǎn)生相同的結(jié)果。

現(xiàn)在環(huán)境已經(jīng)設(shè)置好,可以準備訓練數(shù)據(jù)了。

準備訓練數(shù)據(jù)

訓練數(shù)據(jù)由一對(x?,x?)組成,其中x?是x?在區(qū)間從0到2π上的正弦值。你可以按照以下方式實現(xiàn)它:

train_data_length = 1024train_set = [ ? ?(train_data[i], train_labels[i]) for i in range(train_data_length)]

在這里,你創(chuàng)建了一個包含1024對(x?,x?)的訓練集。在第2行,你初始化了train_data,它是一個具有1024行和2列的張量,所有元素都為零。張量是一個類似于NumPy數(shù)組的多維數(shù)組。

在第3行,你使用train_data的第一列來存儲在0區(qū)間內(nèi)的隨機值。然后,在第4行,你計算了張量的第二列,即第一列的正弦值。

接下來,你需要一個標簽張量,PyTorch的數(shù)據(jù)加載器需要使用它。由于GAN使用無監(jiān)督學習技術(shù),標簽可以是任何值。畢竟,它們不會被使用。

在第5行,你創(chuàng)建了一個填充了零的train_labels張量。最后,在第6到8行,你將train_set創(chuàng)建為元組列表,其中每個元組代表train_datatrain_labels的每一行,正如PyTorch的數(shù)據(jù)加載器所期望的那樣。

你可以通過繪制每個點(x?,x?)來查看訓練數(shù)據(jù):

plt.plot(train_data[:, 0], train_data[:, 1], ".")

輸出應該類似于以下圖形:

使用train_set,您可以創(chuàng)建一個PyTorch數(shù)據(jù)加載器:

batch_size = 32)

在這里,您創(chuàng)建了一個名為train_loader的數(shù)據(jù)加載器,它將對train_set中的數(shù)據(jù)進行洗牌,并返回大小為32的樣本批次,您將使用這些批次來訓練神經(jīng)網(wǎng)絡(luò)。

設(shè)置訓練數(shù)據(jù)后,您需要為判別器和生成器創(chuàng)建神經(jīng)網(wǎng)絡(luò),它們將組成GAN。在下一節(jié)中,您將實現(xiàn)判別器。

實現(xiàn)判別器

在PyTorch中,神經(jīng)網(wǎng)絡(luò)模型由繼承自nn.Module的類表示,因此您需要定義一個類來創(chuàng)建判別器。

判別別器是一個具有二維輸入和一維輸出的模型。它將接收來自真實數(shù)據(jù)或生成器的樣本,并提供樣本屬于真實訓練數(shù)據(jù)的概率。下面的代碼展示了如何創(chuàng)建判別器:

class Discriminator(nn.Module): ? ?def __init__(self): ? ? ? ? ? ? ?nn.Linear(64, 1), ? ? ? ? ? ?nn.Sigmoid(), ? ? ? ?) ? ?def forward(self, x): ? ? ? ?output = self.model(x) ? ? ? ?return output

您使用. __init __()來構(gòu)建模型。首先,您需要調(diào)用super().__init __()來運行nn.Module中的.__init __()。您使用的判別器是在nn.Sequential()中以順序方式定義的MLP神經(jīng)網(wǎng)絡(luò)。它具有以下特點:

  • **第5和第6行:**輸入為二維,第一個隱藏層由256個神經(jīng)元組成,并使用ReLU激活函數(shù)。

  • **第8、9、11和12行:**第二個和第三個隱藏層分別由128個和64個神經(jīng)元組成,并使用ReLU激活函數(shù)。

  • **第14和第15行:**輸出由一個神經(jīng)元組成,并使用sigmoidal激活函數(shù)表示概率。

  • **第7、10和13行:**在第一個、第二個和第三個隱藏層之后,您使用dropout來避免過擬合。

最后,您使用.forward()來描述如何計算模型的輸出。這里,x表示模型的輸入,它是一個二維張量。在此實現(xiàn)中,通過將輸入x饋送到您定義的模型中而不進行任何其他處理來獲得輸出。

聲明判別器類后,您應該實例化一個Discriminator對象:

discriminator = Discriminator()

discriminator代表您定義的神經(jīng)網(wǎng)絡(luò)的一個實例,準備好進行訓練。但是,在實現(xiàn)訓練循環(huán)之前,您的GAN還需要一個生成器。您將在下一節(jié)中實現(xiàn)一個生成器。

實現(xiàn)生成器

在生成對抗網(wǎng)絡(luò)中,生成器是一個以潛在空間中的樣本作為輸入,并生成類似于訓練集中數(shù)據(jù)的模型。在這種情況下,它是一個具有二維輸入的模型,將接收隨機點(z?,z?),并提供類似于訓練數(shù)據(jù)中的(x??,x??)點的二維輸出。

實現(xiàn)類似于您為判別器所做的操作。首先,您必須創(chuàng)建一個從nn.Module繼承并定義神經(jīng)網(wǎng)絡(luò)架構(gòu)的Generator類,然后需要實例化一個Generator對象:

class Generator(nn.Module): ? ?def __init__(self): ? ? ? ?super().__init__() ?generator = Generator()

在這里,generator代表生成器神經(jīng)網(wǎng)絡(luò)。它由兩個具有16個和32個神經(jīng)元的隱藏層組成,兩者都使用ReLU激活函數(shù),以及一個具有2個神經(jīng)元的線性激活層作為輸出。這樣,輸出將由一個包含兩個元素的向量組成,可以是從負無窮大到正無窮大的任何值,這些值將表示(x??,x??)。

現(xiàn)在,您已定義了判別器和生成器的模型,可以開始進行訓練了!

訓練模型

在訓練模型之前,您需要設(shè)置一些參數(shù)來在訓練過程中使用:

lr = 0.001num_epochs = 300

在這里,您設(shè)置了以下參數(shù):

  • 第1行設(shè)置學習率(lr),您將使用它來調(diào)整網(wǎng)絡(luò)權(quán)重。

  • 第2行設(shè)置了周期數(shù)(num_epochs),定義了對整個訓練集進行訓練的重復次數(shù)。

  • 第3行將變量loss_function賦值為二進制交叉熵函數(shù)BCELoss(),這是您將用于訓練模型的損失函數(shù)。

二進制交叉熵函數(shù)是訓練判別器的適用損失函數(shù),因為它考慮了二元分類任務。它也適用于訓練生成器,因為它將其輸出饋送給判別器,后者提供一個二進制的可觀測輸出。

PyTorch在torch.optim中實現(xiàn)了各種權(quán)重更新規(guī)則用于模型訓練。您將使用Adam算法來訓練判別器和生成器模型。要使用torch.optim創(chuàng)建優(yōu)化器,請運行以下代碼:

optimizer_generator = torch.optim.Adam(generator.parameters(), lr=lr)

最后,你需要實現(xiàn)一個訓練循環(huán),在該循環(huán)中,將訓練樣本輸入模型,并更新其權(quán)重以最小化損失函數(shù):

for epoch in range(num_epochs): ? ?for n, (real_samples, _) in enumerate(train_loader): ? ? ? ?# 訓練判別器的數(shù)據(jù) ? ? ? ?real_samples_labels = torch.ones((batch_size, 1)) ? ? ? ? ? ?# 訓練判別器 ? ? ? ?discriminator.zero_grad() ? ? ? ? ? ?# 訓練生成器的數(shù)據(jù) ? ? ? ?latent_space_samples = torch.randn((batch_size, 2)) ? ? ? ?# 訓練生成器 ? ? ? ?generator.zero_grad() ? ? ? ? ? ? ? ?# 顯示損失 ? ? ? ?if epoch % 10 == 0 and n == batch_size - 1: ? ? ? ? ? ? ? ?

對于生成對抗網(wǎng)絡(luò)(GANs),您需要在每個訓練迭代中更新判別器和生成器的參數(shù)。與所有神經(jīng)網(wǎng)絡(luò)一樣,訓練過程包括兩個循環(huán),一個用于訓練周期,另一個用于每個周期的批處理。在內(nèi)部循環(huán)中,您開始準備用于訓練判別器的數(shù)據(jù):

  • 第2行:?從數(shù)據(jù)加載器中獲取當前批次的真實樣本,并將其賦值給real_samples。請注意,張量的第一個維度具有與batch_size相等的元素數(shù)量。這是在PyTorch中組織數(shù)據(jù)的標準方式,張量的每一行表示批次中的一個樣本。

  • 第4行:?使用torch.ones()為真實樣本創(chuàng)建標簽,并將標簽賦給real_samples_labels。

  • 第5和第6行:?通過在latent_space_samples中存儲隨機數(shù)據(jù),創(chuàng)建生成的樣本,然后將其輸入生成器以獲得generated_samples

  • 第7行:?使用torch.zeros()將標簽值0分配給生成的樣本的標簽,然后將標簽存儲在generated_samples_labels中。

  • 第8到11行:?將真實樣本和生成的樣本以及標簽連接起來,并將其存儲在all_samplesall_samples_labels中,您將使用它們來訓練判別器。

接下來,在第14到19行,您訓練了判別器:

  • 第14行:?在PyTorch中,每個訓練步驟都需要清除梯度,以避免積累。您可以使用.zero_grad()來實現(xiàn)這一點。

  • 第15行:?您使用訓練數(shù)據(jù)all_samples計算判別器的輸出。

  • 第16和17行:?您使用模型的輸出output_discriminator和標簽all_samples_labels來計算損失函數(shù)。

  • 第18行:?您使用loss_discriminator.backward()計算梯度以更新權(quán)重。

  • 第19行:?您通過調(diào)用optimizer_discriminator.step()來更新判別器的權(quán)重。

接下來,在第22行,您準備用于訓練生成器的數(shù)據(jù)。您將隨機數(shù)據(jù)存儲在latent_space_samples中,行數(shù)與batch_size相等。由于您將二維數(shù)據(jù)作為輸入提供給生成器,因此使用了兩列。

然后,在第25到32行,您訓練了生成器:

  • 第25行:?使用.zero_grad()清除梯度。

  • 第26行:?將latent_space_samples提供給生成器,并將其輸出存儲在generated_samples中。

  • 第27行:?將生成器的輸出輸入判別器,并將其輸出存儲在output_discriminator_generated中,您將使用其作為整個模型的輸出。

  • 第28到30行:?使用分類系統(tǒng)的輸出output_discriminator_generated和標簽real_samples_labels計算損失函數(shù),這些標簽都等于1

  • 第31和32行:?計算梯度并更新生成器的權(quán)重。請記住,當訓練生成器時,保持判別器權(quán)重凍結(jié),因為您創(chuàng)建了optimizer_generator,其第一個參數(shù)等于generator.parameters()。

最后,在第35到37行,您顯示了每十個周期結(jié)束時判別器和生成器損失函數(shù)的值。

由于此示例中使用的模型參數(shù)較少,訓練將在幾分鐘內(nèi)完成。在接下來的部分中,您將使用訓練的GAN生成一些樣本。

檢查GAN生成的樣本

生成對抗網(wǎng)絡(luò)被設(shè)計用于生成數(shù)據(jù)。因此,在訓練過程結(jié)束后,您可以從潛在空間中獲取一些隨機樣本,并將它們提供給生成器以獲得一些生成的樣本:

latent_space_samples = torch.randn(100, 2)

然后,您可以繪制生成的樣本,并檢查它們是否類似于訓練數(shù)據(jù)。在繪制generated_samples數(shù)據(jù)之前,您需要使用.detach()從PyTorch計算圖中返回一個張量,然后使用它來計算梯度:

generated_samples = generated_samples.detach()

輸出應類似于以下圖像:

您可以看到,生成的數(shù)據(jù)分布類似于真實數(shù)據(jù)。通過使用固定的潛在空間樣本張量,并在訓練過程的每個周期結(jié)束時將其提供給生成器,您可以可視化訓練的演變。

手寫數(shù)字圖像與GAN

生成對抗網(wǎng)絡(luò)可以生成高維樣本,例如圖像。在此示例中,您將使用GAN生成手寫數(shù)字圖像。為此,您將使用包含手寫數(shù)字的MNIST數(shù)據(jù)集,該數(shù)據(jù)集已包含在torchvision包中。

首先,您需要在已激活的gan?conda環(huán)境中安裝torchvision

$ conda install -c pytorch torchvision=0.5.0

與前面一樣,您使用特定版本的torchvision來確保示例代碼可以運行,就像您在pytorch上所做的一樣。設(shè)置好環(huán)境后,您可以在Jupyter Notebook中開始實現(xiàn)模型。

與之前的示例一樣,首先導入必要的庫:

import torchfrom torch import nn

除了之前導入的庫外,您還將需要torchvisiontransforms來獲取訓練數(shù)據(jù)并執(zhí)行圖像轉(zhuǎn)換。

同樣,設(shè)置隨機生成器種子以便能夠復制實驗:

torch.manual_seed(111)

由于此示例在訓練集中使用圖像,所以模型需要更復雜,并且具有更多的參數(shù)。這使得訓練過程變慢,當在CPU上運行時,每個周期需要大約兩分鐘。您需要大約50個周期才能獲得相關(guān)結(jié)果,因此在使用CPU時的總訓練時間約為100分鐘。

為了減少訓練時間,如果您有可用的GPU,可以使用它來訓練模型。但是,您需要手動將張量和模型移動到GPU上,以便在訓練過程中使用它們。

您可以通過創(chuàng)建一個指向CPU或(如果有)GPU的device對象來確保您的代碼將在任何一種設(shè)置上運行:

device = "" ? ?device = torch.device("cpu")

稍后,您將使用此device在可用的情況下使用GPU來設(shè)置張量和模型的創(chuàng)建位置。

現(xiàn)在基本環(huán)境已經(jīng)設(shè)置好了,您可以準備訓練數(shù)據(jù)。

準備訓練數(shù)據(jù)

MNIST數(shù)據(jù)集由28×28像素的灰度手寫數(shù)字圖像組成,范圍從0到9。為了在PyTorch中使用它們,您需要進行一些轉(zhuǎn)換。為此,您定義了一個名為transform的函數(shù)來加載數(shù)據(jù)時使用:

transform = transforms.Compose()

該函數(shù)分為兩個部分:

  1. transforms.ToTensor()將數(shù)據(jù)轉(zhuǎn)換為PyTorch張量。

  2. transforms.Normalize()轉(zhuǎn)換張量系數(shù)的范圍。

transforms.ToTensor()產(chǎn)生的原始系數(shù)范圍從0到1,而且由于圖像背景是黑色,當使用此范圍表示時,大多數(shù)系數(shù)都等于0。

transforms.Normalize()通過從原始系數(shù)中減去0.5并將結(jié)果除以0.5,將系數(shù)的范圍更改為-1到1。通過這種轉(zhuǎn)換,輸入樣本中為0的元素數(shù)量大大減少,有助于訓練模型。

transforms.Normalize()的參數(shù)是兩個元組(M?, ..., M?)(S?, ..., S?),其中n表示圖像的通道數(shù)量。MNIST數(shù)據(jù)集中的灰度圖像只有一個通道,因此元組只有一個值。因此,對于圖像的每個通道i,transforms.Normalize()從系數(shù)中減去M?并將結(jié)果除以S?。

現(xiàn)在,您可以使用torchvision.datasets.MNIST加載訓練數(shù)據(jù),并使用transform進行轉(zhuǎn)換:

train_set = torchvision.datasets.MNIST()

參數(shù)download=True確保您第一次運行上述代碼時,MNIST數(shù)據(jù)集將會被下載并存儲在當前目錄中,如參數(shù)root所指示的位置。

現(xiàn)在您已經(jīng)創(chuàng)建了train_set,可以像之前一樣創(chuàng)建數(shù)據(jù)加載器:

batch_size = 32train_loader = torch.utils.data.DataLoader()

您可以使用Matplotlib繪制一些訓練數(shù)據(jù)的樣本。為了改善可視化效果,您可以使用cmap=gray_r來反轉(zhuǎn)顏色映射,并以黑色數(shù)字在白色背景上繪制:

real_samples, mnist_labels = next(iter(train_loader))for i in range(16): ? ?

輸出應該類似于以下內(nèi)容:

如您所見,有不同的手寫風格的數(shù)字。隨著GAN學習數(shù)據(jù)的分布,它還會生成具有不同手寫風格的數(shù)字。

現(xiàn)在您已經(jīng)準備好了訓練數(shù)據(jù),可以實現(xiàn)判別器和生成器模型。

實現(xiàn)判別器和生成器

本例中判別器是一個MLP神經(jīng)網(wǎng)絡(luò),它接收一個28 × 28像素的圖像,并提供圖像屬于真實訓練數(shù)據(jù)的概率。

您可以使用以下代碼定義模型:

class Discriminator(nn.Module): ? ?def __init__(self): ? ? ? ? ? ?def forward(self, x): ? ? ? ? ? ? ? ? ? ?return output

為了將圖像系數(shù)輸入到MLP神經(jīng)網(wǎng)絡(luò)中,可以將它們進行向量化,使得神經(jīng)網(wǎng)絡(luò)接收具有784個系數(shù)的向量。

矢量化發(fā)生在.forward()的第一行,因為調(diào)用x.view()可以轉(zhuǎn)換輸入張量的形狀。在這種情況下,輸入x的原始形狀是32×1×28×28,其中32是您設(shè)置的批量大小。轉(zhuǎn)換后,x的形狀變?yōu)?2×784,每行表示訓練集中圖像的系數(shù)。

要使用GPU運行判別器模型,您必須實例化它并使用.to()將其發(fā)送到GPU。要在有可用GPU時使用GPU,可以將模型發(fā)送到先前創(chuàng)建的device對象:

discriminator = Discriminator().to(device=device)

由于生成器將生成更復雜的數(shù)據(jù),因此需要增加來自潛在空間的輸入維數(shù)。在這種情況下,生成器將接收一個100維的輸入,并提供一個由784個系數(shù)組成的輸出,這些系數(shù)將以28×28的張量表示為圖像。

下面是完整的生成器模型代碼:

class Generator(nn.Module): ? ?def __init__(self): ? ? ? ?super().__init__() ? ? ? ?self.model = nn.Sequential( ? ?

在第12行,使用雙曲正切函數(shù)Tanh()作為輸出層的激活函數(shù),因為輸出系數(shù)應該在-1到1的區(qū)間內(nèi)。在第20行,實例化生成器并將其發(fā)送到device以使用可用的GPU。

現(xiàn)在您已經(jīng)定義了模型,可以使用訓練數(shù)據(jù)對它們進行訓練。

訓練模型

要訓練模型,需要定義訓練參數(shù)和優(yōu)化器,就像在之前的示例中所做的那樣:

lr = 0.0001num_epochs = 50loss_function = nn.BCELoss()optimizer_generator = torch.optim.Adam(generator.parameters(), lr=lr)

為了獲得更好的結(jié)果,將學習率從先前的示例中降低。還將將epoch數(shù)設(shè)置為50,以減少訓練時間。

訓練循環(huán)與之前的示例非常相似。在突出顯示的行中,將訓練數(shù)據(jù)發(fā)送到device以在有GPU可用時使用:

for epoch in range(num_epochs): ? ?for n, (real_samples, mnist_labels) in enumerate(train_loader): ? ? ? ?e, 100)).to( ? ? ? ? ? ?device=device ? ? ? ?) ? ? ? ? ? ?loss_generator = loss_function( ? ? ? ? ? ?output_discriminator_generated, real_samples_labels ? ? ? ?) ? ? ? ?loss_generator.backward() ? ? ? ?optimizer_generator.step().: {loss_generator}")

某些張量不需要使用device顯式地發(fā)送到GPU。這適用于第11行中的generated_samples,它將已經(jīng)被發(fā)送到可用GPU,因為latent_space_samplesgenerator先前已被發(fā)送到GPU。

由于此示例具有更復雜的模型,訓練可能需要更長時間。訓練完成后,您可以通過生成一些手寫數(shù)字樣本來檢查結(jié)果。

檢查GAN生成的樣本

要生成手寫數(shù)字,您需要從潛在空間中隨機采樣一些樣本并將其提供給生成器:

latent_space_samples = torch.randn(batch_size, 100).to(device=device)

要繪制generated_samples,您需要將數(shù)據(jù)移回GPU上運行時,以便在使用Matplotlib繪制數(shù)據(jù)之前,可以簡單地調(diào)用.cpu()。與之前一樣,還需要在使用Matplotlib繪制數(shù)據(jù)之前調(diào)用.detach()

generated_samples = generated_samples.cpu().detach()for i in range(16):

輸出應該是類似訓練數(shù)據(jù)的數(shù)字,如以下圖片所示:

?經(jīng)過50個epoch的訓練后,生成了一些類似真實數(shù)字的生成數(shù)字。通過增加訓練epoch次數(shù),可以改善結(jié)果。

與之前的示例一樣,通過在訓練過程的每個周期結(jié)束時使用固定的潛在空間樣本張量并將其提供給生成器,可以可視化訓練的演變。

總結(jié)

您已經(jīng)學會了如何實現(xiàn)自己的生成對抗網(wǎng)絡(luò)。在深入探討生成手寫數(shù)字圖像的實際應用之前,您首先通過一個簡單的示例了解了GAN的結(jié)構(gòu)。

您看到,盡管GAN的復雜性很高,但像PyTorch這樣的機器學習框架通過提供自動微分和簡便的GPU設(shè)置,使其實現(xiàn)更加簡單直觀。

在本文中,您學到了:

  • 判別模型和生成模型的區(qū)別

  • 如何結(jié)構(gòu)化和訓練生成對抗網(wǎng)絡(luò)

  • 如何使用PyTorch等工具和GPU來實現(xiàn)和訓練GAN模型

GAN是一個非?;钴S的研究課題,近年來提出了幾個令人興奮的應用。如果您對此主題感興趣,請密切關(guān)注技術(shù)和科學文獻,以獲取新的應用想法。

最受歡迎的見解

1.R語言實現(xiàn)CNN(卷積神經(jīng)網(wǎng)絡(luò))模型進行回歸

2.r語言實現(xiàn)擬合神經(jīng)網(wǎng)絡(luò)預測和結(jié)果可視化

3.python用遺傳算法-神經(jīng)網(wǎng)絡(luò)-模糊邏輯控制算法對樂透分析

4.R語言結(jié)合新冠疫情COVID-19股票價格預測:ARIMA,KNN和神經(jīng)網(wǎng)絡(luò)時間序列分析

5.Python TensorFlow循環(huán)神經(jīng)網(wǎng)絡(luò)RNN-LSTM神經(jīng)網(wǎng)絡(luò)預測股票市場價格時間序列和MSE評估準確性

6.Matlab用深度學習長短期記憶(LSTM)神經(jīng)網(wǎng)絡(luò)對文本數(shù)據(jù)進行分類

7.用于NLP的seq2seq模型實例用Keras實現(xiàn)神經(jīng)機器翻譯

8.R語言用FNN-LSTM假近鄰長短期記憶人工神經(jīng)網(wǎng)絡(luò)模型進行時間序列深度學習預測

9.Python用RNN循環(huán)神經(jīng)網(wǎng)絡(luò):LSTM長期記憶、GRU門循環(huán)單元、回歸和ARIMA對COVID-19新冠疫情新增人數(shù)時間序列預測


Python用GAN生成對抗性神經(jīng)網(wǎng)絡(luò)判別模型擬合多維數(shù)組、分類識別手寫數(shù)字圖像可視化的評論 (共 條)

分享到微博請遵守國家法律
龙岩市| 宣城市| 大兴区| 安仁县| 保亭| 翁源县| 台中市| 泸州市| 公安县| 怀远县| 密云县| 伊金霍洛旗| 枞阳县| 奎屯市| 晴隆县| 集贤县| 三台县| 砚山县| 嘉义县| 蕲春县| 隆德县| 罗甸县| 巴东县| 定边县| 江华| 南乐县| 德阳市| 舒兰市| 措美县| 红河县| 抚顺县| 五莲县| 玉山县| 淳安县| 枞阳县| 洛川县| 喜德县| 南汇区| 鲁山县| 兴仁县| 曲靖市|