图像对抗生成网络 GAN学习01:从头搭建最简单的GAN网络,利用神经网络生成手写体数字数据(tensorflow)
圖像對抗生成網(wǎng)絡(luò) GAN學(xué)習(xí)01:從頭搭建最簡單的GAN網(wǎng)絡(luò),利用神經(jīng)網(wǎng)絡(luò)生成手寫體數(shù)字?jǐn)?shù)據(jù)(tensorflow)
文章目錄
- 圖像對抗生成網(wǎng)絡(luò) GAN學(xué)習(xí)01:從頭搭建最簡單的GAN網(wǎng)絡(luò),利用神經(jīng)網(wǎng)絡(luò)生成手寫體數(shù)字?jǐn)?shù)據(jù)(tensorflow)
- 1.前言
- 2.GAN網(wǎng)絡(luò)主體架構(gòu)介紹
- 3.模型搭建
- 3.1 生成器的搭建
- 3.2 判別器模型的搭建
- 4.數(shù)據(jù)預(yù)處理
- 5.定義訓(xùn)練各項參數(shù)以及訓(xùn)練步驟
- 6.訓(xùn)練以及效果可視化評估
- 結(jié)語
1.前言
? 深度學(xué)習(xí),中有一個較為成熟并且非常重要的方向,GAN圖像對抗生成網(wǎng)絡(luò),該網(wǎng)絡(luò)在圖像生成,圖像增強,風(fēng)格化領(lǐng)域,以及在藝術(shù)的圖像創(chuàng)造(博主也是在看到一個關(guān)于中國山水畫的GAN生成上,有了學(xué)習(xí)GAN的興趣)有重要的作用。
? 那么正所謂柿子要挑軟的捏,學(xué)習(xí)從最簡單的開始,在GAN方面完全是萌新的博主,今天介紹的自然也不是什么太難的架構(gòu),在本篇博客中,我會介紹GAN的大致架構(gòu),并用較為簡單的方式從頭到尾 (模型搭建,定義訓(xùn)練參數(shù),訓(xùn)練步驟)實現(xiàn)他,如果本篇博客對你有幫助的話,別忘記點個贊。
( ̄▽ ̄)~■干杯□~( ̄▽ ̄)
2.GAN網(wǎng)絡(luò)主體架構(gòu)介紹
GAN的網(wǎng)絡(luò)總體架構(gòu)其實非常簡單,他的中文名字對抗生成網(wǎng)絡(luò),意思是在他模型中包含兩個網(wǎng)絡(luò),生成網(wǎng)絡(luò),對抗網(wǎng)絡(luò),總體結(jié)構(gòu)如下圖:
? 我們可以看到這張圖上包含了兩個網(wǎng)絡(luò)Generator圖像生成器和Discriminator圖像分辨器,他的工作原理簡單來說是這樣的:我們的目標(biāo)是想要一個生成圖片那么我們?nèi)绾稳ビ?xùn)練這個呢,這里GAN的開發(fā)者提出了這么一個想法,我們訓(xùn)練一個判別器,訓(xùn)練一個生成器,輸入噪聲(也就是我們提前規(guī)定好形狀的隨機初始化的向量)然后產(chǎn)生了圖片,然后我們將真實的圖片與虛假圖片一起輸入判別器,判別圖片是否是真實的,利用在這里產(chǎn)生的損失去訓(xùn)練生成器,與判別器。那么我們可以想想如果這樣的話我們最終產(chǎn)生的理想結(jié)果就是,判別器最終無法判別生成器生成的圖片是真是假,最終預(yù)測的概率只有0.5(真假 二分類隨機亂猜的概率)。
? 當(dāng)剛看懂網(wǎng)絡(luò)工作方式的時候,我簡直驚呆了,這是多么神奇的思維啊,生成器在訓(xùn)練中由于損失控制會努力希望生成的圖片被判別為真,而判別器是希望能完全給出正確的判斷(給生成的圖片的判斷全為0,真的圖片判斷全為1),那么在這兩個模型的訓(xùn)練之間,他們在互相對抗,我們最終得到的將會是一個非常好的圖像生成器,和 自編碼器相比,(直接計算生成圖與原圖的差距)效果會更好(這里我會在之后的mnist數(shù)據(jù)生成展示中展示編碼器與GAN網(wǎng)絡(luò)的差別)。
3.模型搭建
? 那么在介紹完模型之后,我們趁熱打鐵,直接開始模型的搭建,在上文中,我提到了兩個模型負責(zé)生成圖片的生成器,負責(zé)判別圖片真假的判別器,接下來我開始分別搭建這兩個模型。
3.1 生成器的搭建
? 這里我們要搭建的是一個能夠接收我們產(chǎn)生的隨機初始化的向量,然后產(chǎn)生圖片(這里我們產(chǎn)生的數(shù)據(jù)是mnist的手寫體數(shù)字)的模型,這里我為了簡單化全部采用全連接層來寫模型
import tensorflow as tf keras=tf.keras layers=keras.layers def generator_model():model=keras.Sequential()#model.add(layers.Dense(256,input_shape=(100,),use_bias=False))#輸入形狀100是我輸入噪聲的形狀,生成器一般都不使用BIASmodel.add(layers.BatchNormalization())model.add(layers.LeakyReLU())#GAN中一般使用LeakyRelu函數(shù)來激活model.add(layers.Dense(512,use_bias=False))#生成器一般都不使用BIASmodel.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dense(28*28*1,use_bias=False,activation='tanh'))#生成能夠調(diào)整成我們想要的圖片形狀的向量model.add(layers.BatchNormalization())model.add(layers.Reshape((28,28,1)))#這里進行修改向量的形狀,可以直接使用layers的reshapereturn model可以看到經(jīng)過全連接層的這樣處理,我們輸出的會是一個形狀大小為(28,28,1)的圖片,那么生成器的任務(wù)就是判斷輸入圖片是否是生成的,也就是輸入圖片,輸出0,1一個非常簡單的二分類問題,那么我們就按照這個思路搭建我們的判別器網(wǎng)絡(luò)。
3.2 判別器模型的搭建
判別器這里我也使用最基礎(chǔ)的全連接層來創(chuàng)建(一方面是減少計算量,一方面是測試一下Dense層的效果)
def discriminator_model():model=keras.Sequential()model.add(layers.Flatten())#圖片是一個三維數(shù)據(jù),要輸入到全連接層之前,先使用flatten層壓平為一維的model.add(layers.Dense(512,use_bias=False))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dense(256,use_bias=False))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dense(1))#最后輸出為0,1只需要一層return model那么定義完組成模型的兩個重要架構(gòu)之后,我們?yōu)榱私酉聛淼挠?xùn)練需要準(zhǔn)備處理好的數(shù)據(jù),所以這里我們開始處理數(shù)據(jù)。
4.數(shù)據(jù)預(yù)處理
在本篇最簡單的實戰(zhàn)中,我采用深度學(xué)習(xí)中使用次數(shù)最多,入門級Hello World數(shù)據(jù)集,mnist手寫體數(shù)據(jù)集,由數(shù)萬張手寫體數(shù)字組成
這里的數(shù)字都是手寫之后,經(jīng)過特殊處理最終保存下來的。可以看到這樣生成的圖片是非常帶有個人風(fēng)格的(這寫的也不太整齊。。),那么利用GAN生成網(wǎng)絡(luò)去生成能類似人寫的數(shù)據(jù),達到可以欺騙人眼的效果,就是我此次的目的,那么廢話少說,就開始我們此次的數(shù)據(jù)準(zhǔn)備。
(x_train,y_train),_=keras.datasets.mnist.load_data() x_train=tf.expand_dims(x_train,axis=-1)#這里由于輸入的手寫體是只有兩個維度的,所以這里我擴展最后一個維度 x_train.shape TensorShape([60000, 28, 28, 1])擴展完維度后,為了方便模型運算,我們需要將數(shù)據(jù)進行歸一化,規(guī)定數(shù)據(jù)集的BATCH_SIZE
x_train=tf.cast(x_train,tf.float32) x_train=x_train/255.0 x_train=x_train*2-1#將圖片數(shù)據(jù)規(guī)范到[-1,1] BATCH_SIZE=256 BUFFER_SIZE=60000#每次訓(xùn)練弄亂的大小 dataset=tf.data.Dataset.from_tensor_slices(x_train) dataset=dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)5.定義訓(xùn)練各項參數(shù)以及訓(xùn)練步驟
在搭建完模型,預(yù)處理好數(shù)據(jù)之后,接下來就需要定義模型所需優(yōu)化器,損失計算函數(shù),以及訓(xùn)練步驟
loss_object=keras.losses.BinaryCrossentropy(from_logits=True)#損失這里使用二分類交叉熵損失,沒有激活是logits def discriminator_loss(real_out,fake_out): real_loss=loss_object(tf.ones_like(real_out), real_out)fake_loss=loss_object(tf.zeros_like(fake_out),fake_out)return real_loss+fake_loss #這里判別器使用的損失是計算我們?nèi)藶橹圃斓?,1標(biāo)簽與判別器模型輸出的做計算,最終返回二者相加 def generator_loss(fake_out):fake_loss=loss_object(tf.ones_like(fake_out),fake_out)return fake_loss #生成器計算損失當(dāng)然是希望判別器都把他當(dāng)真,所以是與1做計算generator_opt=keras.optimizers.Adam(1e-4) discriminator_opt=keras.optimizers.Adam(1e-4)#定義兩個模型的優(yōu)化器定義完了在訓(xùn)練嗎中需要用到的優(yōu)化器損失函數(shù),我們這里接下來定義模型,訓(xùn)練步驟并開始訓(xùn)練(這里我們會在每次訓(xùn)練后繪畫隨機生成的圖片,來觀察我們圖像生成模型的效果,所以這里我會提前制作一個隨機種子)
EPOCHS=100 noise_dim=100 #輸入噪聲的維度 num=16 #每次隨機繪畫16張圖 seed=tf.random.normal(shape=([num,noise_dim])) #制作用于生成圖片的向量 gen_model=generator_model() dis_model=discriminator_model() #初始化這兩個模型 #定義訓(xùn)練步驟 @tf.function def train_step(images):noise=tf.random.normal([BATCH_SIZE,noise_dim])with tf.GradientTape() as gentape, tf.GradientTape() as disctape:real_output=dis_model(images,training=True)fake_image=gen_model(noise,training=True)fake_output=dis_model(fake_image,training=True)gen_loss=generator_loss(fake_output)dis_loss=discriminator_loss(real_output,fake_output)grad_gen=gentape.gradient(gen_loss,gen_model.trainable_variables)grad_dis=disctape.gradient(dis_loss,dis_model.trainable_variables)generator_opt.apply_gradients(zip(grad_gen,gen_model.trainable_variables))discriminator_opt.apply_gradients(zip(grad_dis,dis_model.trainable_variables))#在每次訓(xùn)練后繪圖 def generate_plot_img(gen_model,test_noise):pre_img=gen_model(test_noise,training=False)fig=plt.figure(figsize=(4,4))for i in range(pre_img.shape[0]):plt.subplot(4,4,i+1)plt.imshow((pre_img[i, :, :, 0]+1)/2,cmap='gray')#這里cmap限定繪圖的顏色空間,灰度圖plt.axis('off')plt.show()#將16張圖片一起顯示出來6.訓(xùn)練以及效果可視化評估
那么我們開始訓(xùn)練
def train(dataset, epochs):for epoch in range(epochs):for img in dataset:train_step(img)print('-',end='')generate_plot_img(gen_model,seed)#繪制圖片 train(dataset,EPOCHS)#這里EPOCHS我設(shè)置為100那么由于我的隨機數(shù)種子是固定的,所以這里我們隨機生成的圖片每次都是固定的數(shù)字,所以我們是可以看到效果在不斷變好,如下
這是第一次訓(xùn)練結(jié)束后生成的一團漿糊
這是第五次訓(xùn)練產(chǎn)生的圖像,可以看到已經(jīng)漸漸產(chǎn)生了有數(shù)字的輪廓,
在經(jīng)過100次訓(xùn)練后最終我們看到我們的圖像生成器,最后產(chǎn)生的圖片已經(jīng)非常有手寫數(shù)字的輪廓。
雖然效果仍然不是很好,但其實是由于我這里完全使用了全連接層,在圖像處理領(lǐng)域使用卷積神經(jīng)網(wǎng)絡(luò)會更好的效果,下圖是我使用了卷積神經(jīng)網(wǎng)絡(luò)后的效果:
結(jié)語
在本篇博客中,我完成了一個非常簡單的GAN生成對抗網(wǎng)絡(luò),并訓(xùn)練該模型使得他可以生成非常接近的手寫體的真實數(shù)據(jù),對本篇博客有疑問或者建議的同學(xué)歡迎評論區(qū)交流。
總結(jié)
以上是生活随笔為你收集整理的图像对抗生成网络 GAN学习01:从头搭建最简单的GAN网络,利用神经网络生成手写体数字数据(tensorflow)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一阶电路暂态响应的结果分析。_【每日电路
- 下一篇: 亚马逊日本站(下)常用工具和运营要点