图像对抗生成网络 GAN学习01:从头搭建最简单的GAN网络,利用神经网络生成手写体数字数据(tensorflow)
圖像對抗生成網絡 GAN學習01:從頭搭建最簡單的GAN網絡,利用神經網絡生成手寫體數字數據(tensorflow)
文章目錄
- 圖像對抗生成網絡 GAN學習01:從頭搭建最簡單的GAN網絡,利用神經網絡生成手寫體數字數據(tensorflow)
- 1.前言
- 2.GAN網絡主體架構介紹
- 3.模型搭建
- 3.1 生成器的搭建
- 3.2 判別器模型的搭建
- 4.數據預處理
- 5.定義訓練各項參數以及訓練步驟
- 6.訓練以及效果可視化評估
- 結語
1.前言
? 深度學習,中有一個較為成熟并且非常重要的方向,GAN圖像對抗生成網絡,該網絡在圖像生成,圖像增強,風格化領域,以及在藝術的圖像創造(博主也是在看到一個關于中國山水畫的GAN生成上,有了學習GAN的興趣)有重要的作用。
? 那么正所謂柿子要挑軟的捏,學習從最簡單的開始,在GAN方面完全是萌新的博主,今天介紹的自然也不是什么太難的架構,在本篇博客中,我會介紹GAN的大致架構,并用較為簡單的方式從頭到尾 (模型搭建,定義訓練參數,訓練步驟)實現他,如果本篇博客對你有幫助的話,別忘記點個贊。
( ̄▽ ̄)~■干杯□~( ̄▽ ̄)
2.GAN網絡主體架構介紹
GAN的網絡總體架構其實非常簡單,他的中文名字對抗生成網絡,意思是在他模型中包含兩個網絡,生成網絡,對抗網絡,總體結構如下圖:
? 我們可以看到這張圖上包含了兩個網絡Generator圖像生成器和Discriminator圖像分辨器,他的工作原理簡單來說是這樣的:我們的目標是想要一個生成圖片那么我們如何去訓練這個呢,這里GAN的開發者提出了這么一個想法,我們訓練一個判別器,訓練一個生成器,輸入噪聲(也就是我們提前規定好形狀的隨機初始化的向量)然后產生了圖片,然后我們將真實的圖片與虛假圖片一起輸入判別器,判別圖片是否是真實的,利用在這里產生的損失去訓練生成器,與判別器。那么我們可以想想如果這樣的話我們最終產生的理想結果就是,判別器最終無法判別生成器生成的圖片是真是假,最終預測的概率只有0.5(真假 二分類隨機亂猜的概率)。
? 當剛看懂網絡工作方式的時候,我簡直驚呆了,這是多么神奇的思維啊,生成器在訓練中由于損失控制會努力希望生成的圖片被判別為真,而判別器是希望能完全給出正確的判斷(給生成的圖片的判斷全為0,真的圖片判斷全為1),那么在這兩個模型的訓練之間,他們在互相對抗,我們最終得到的將會是一個非常好的圖像生成器,和 自編碼器相比,(直接計算生成圖與原圖的差距)效果會更好(這里我會在之后的mnist數據生成展示中展示編碼器與GAN網絡的差別)。
3.模型搭建
? 那么在介紹完模型之后,我們趁熱打鐵,直接開始模型的搭建,在上文中,我提到了兩個模型負責生成圖片的生成器,負責判別圖片真假的判別器,接下來我開始分別搭建這兩個模型。
3.1 生成器的搭建
? 這里我們要搭建的是一個能夠接收我們產生的隨機初始化的向量,然后產生圖片(這里我們產生的數據是mnist的手寫體數字)的模型,這里我為了簡單化全部采用全連接層來寫模型
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函數來激活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'))#生成能夠調整成我們想要的圖片形狀的向量model.add(layers.BatchNormalization())model.add(layers.Reshape((28,28,1)))#這里進行修改向量的形狀,可以直接使用layers的reshapereturn model可以看到經過全連接層的這樣處理,我們輸出的會是一個形狀大小為(28,28,1)的圖片,那么生成器的任務就是判斷輸入圖片是否是生成的,也就是輸入圖片,輸出0,1一個非常簡單的二分類問題,那么我們就按照這個思路搭建我們的判別器網絡。
3.2 判別器模型的搭建
判別器這里我也使用最基礎的全連接層來創建(一方面是減少計算量,一方面是測試一下Dense層的效果)
def discriminator_model():model=keras.Sequential()model.add(layers.Flatten())#圖片是一個三維數據,要輸入到全連接層之前,先使用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那么定義完組成模型的兩個重要架構之后,我們為了接下來的訓練需要準備處理好的數據,所以這里我們開始處理數據。
4.數據預處理
在本篇最簡單的實戰中,我采用深度學習中使用次數最多,入門級Hello World數據集,mnist手寫體數據集,由數萬張手寫體數字組成
這里的數字都是手寫之后,經過特殊處理最終保存下來的。可以看到這樣生成的圖片是非常帶有個人風格的(這寫的也不太整齊。。),那么利用GAN生成網絡去生成能類似人寫的數據,達到可以欺騙人眼的效果,就是我此次的目的,那么廢話少說,就開始我們此次的數據準備。
(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])擴展完維度后,為了方便模型運算,我們需要將數據進行歸一化,規定數據集的BATCH_SIZE
x_train=tf.cast(x_train,tf.float32) x_train=x_train/255.0 x_train=x_train*2-1#將圖片數據規范到[-1,1] BATCH_SIZE=256 BUFFER_SIZE=60000#每次訓練弄亂的大小 dataset=tf.data.Dataset.from_tensor_slices(x_train) dataset=dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)5.定義訓練各項參數以及訓練步驟
在搭建完模型,預處理好數據之后,接下來就需要定義模型所需優化器,損失計算函數,以及訓練步驟
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 #這里判別器使用的損失是計算我們人為制造的0,1標簽與判別器模型輸出的做計算,最終返回二者相加 def generator_loss(fake_out):fake_loss=loss_object(tf.ones_like(fake_out),fake_out)return fake_loss #生成器計算損失當然是希望判別器都把他當真,所以是與1做計算generator_opt=keras.optimizers.Adam(1e-4) discriminator_opt=keras.optimizers.Adam(1e-4)#定義兩個模型的優化器定義完了在訓練嗎中需要用到的優化器損失函數,我們這里接下來定義模型,訓練步驟并開始訓練(這里我們會在每次訓練后繪畫隨機生成的圖片,來觀察我們圖像生成模型的效果,所以這里我會提前制作一個隨機種子)
EPOCHS=100 noise_dim=100 #輸入噪聲的維度 num=16 #每次隨機繪畫16張圖 seed=tf.random.normal(shape=([num,noise_dim])) #制作用于生成圖片的向量 gen_model=generator_model() dis_model=discriminator_model() #初始化這兩個模型 #定義訓練步驟 @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))#在每次訓練后繪圖 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.訓練以及效果可視化評估
那么我們開始訓練
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我設置為100那么由于我的隨機數種子是固定的,所以這里我們隨機生成的圖片每次都是固定的數字,所以我們是可以看到效果在不斷變好,如下
這是第一次訓練結束后生成的一團漿糊
這是第五次訓練產生的圖像,可以看到已經漸漸產生了有數字的輪廓,
在經過100次訓練后最終我們看到我們的圖像生成器,最后產生的圖片已經非常有手寫數字的輪廓。
雖然效果仍然不是很好,但其實是由于我這里完全使用了全連接層,在圖像處理領域使用卷積神經網絡會更好的效果,下圖是我使用了卷積神經網絡后的效果:
結語
在本篇博客中,我完成了一個非常簡單的GAN生成對抗網絡,并訓練該模型使得他可以生成非常接近的手寫體的真實數據,對本篇博客有疑問或者建議的同學歡迎評論區交流。
總結
以上是生活随笔為你收集整理的图像对抗生成网络 GAN学习01:从头搭建最简单的GAN网络,利用神经网络生成手写体数字数据(tensorflow)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一阶电路暂态响应的结果分析。_【每日电路
- 下一篇: 亚马逊日本站(下)常用工具和运营要点