自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用TensorFlow和自編碼器模型生成手寫數(shù)字

人工智能 深度學(xué)習(xí) 后端
自編碼器是一種能夠用來學(xué)習(xí)對輸入數(shù)據(jù)高效編碼的神經(jīng)網(wǎng)絡(luò)。若給定一些輸入,神經(jīng)網(wǎng)絡(luò)首先會(huì)使用一系列的變換來將數(shù)據(jù)映射到低維空間,這部分神經(jīng)網(wǎng)絡(luò)就被稱為編碼器。

[[209419]]

自編碼器是一種能夠用來學(xué)習(xí)對輸入數(shù)據(jù)高效編碼的神經(jīng)網(wǎng)絡(luò)。若給定一些輸入,神經(jīng)網(wǎng)絡(luò)首先會(huì)使用一系列的變換來將數(shù)據(jù)映射到低維空間,這部分神經(jīng)網(wǎng)絡(luò)就被稱為編碼器。

然后,網(wǎng)絡(luò)會(huì)使用被編碼的低維數(shù)據(jù)去嘗試重建輸入,這部分網(wǎng)絡(luò)稱之為解碼器。我們可以使用編碼器將數(shù)據(jù)壓縮為神經(jīng)網(wǎng)絡(luò)可以理解的類型。然而自編碼器很少用做這個(gè)目的,因?yàn)橥ǔ4嬖诒人鼮橛行У氖止ぞ帉懙乃惴?例如 jpg 壓縮)。

此外,自編碼器還被經(jīng)常用來執(zhí)行降噪任務(wù),它能夠?qū)W會(huì)如何重建原始圖像。

什么是變分自編碼器?

有很多與自編碼器相關(guān)的有趣應(yīng)用。

其中之一被稱為變分自編碼器(variational autoencoder)。使用變分自編碼器不僅可以壓縮數(shù)據(jù)–還能生成自編碼器曾經(jīng)遇到過的新對象。

使用通用自編碼器的時(shí)候,我們根本不知道網(wǎng)絡(luò)所生成的編碼具體是什么。雖然我們可以對比不同的編碼對象,但是要理解它內(nèi)部編碼的方式幾乎是不可能的。這也就意味著我們不能使用編碼器來生成新的對象。我們甚至連輸入應(yīng)該是什么樣子的都不知道。

而我們用相反的方法使用變分自編碼器。我們不會(huì)嘗試著去關(guān)注隱含向量所服從的分布,只需要告訴網(wǎng)絡(luò)我們想讓這個(gè)分布轉(zhuǎn)換為什么樣子就行了。

通常情況,我們會(huì)限制網(wǎng)絡(luò)來生成具有單位正態(tài)分布性質(zhì)的隱含向量。然后,在嘗試生成數(shù)據(jù)的時(shí)候,我們只需要從這種分布中進(jìn)行采樣,然后把樣本喂給解碼器就行,解碼器會(huì)返回新的對象,看上去就和我們用來訓(xùn)練網(wǎng)絡(luò)的對象一樣。

下面我們將介紹如何使用 Python 和 TensorFlow 實(shí)現(xiàn)這一過程,我們要教會(huì)我們的網(wǎng)絡(luò)來畫 MNIST 字符。

第一步加載訓(xùn)練數(shù)據(jù)

首先我們來執(zhí)行一些基本的導(dǎo)入操作。TensorFlow 具有非常便利的函數(shù)來讓我們能夠很容易地訪問 MNIST 數(shù)據(jù)集。

  1. import tensorflow as tfimport numpy as npimport matplotlib.pyplot as plt 
  2.  
  3. %matplotlib inlinefrom tensorflow.examples.tutorials.mnist import input_data 
  4.  
  5. mnist = input_data.read_data_sets('MNIST_data' 

定義輸入數(shù)據(jù)和輸出數(shù)據(jù)

MNIST 圖像的維度是 28*28 像素,只有單色通道。我們的輸入數(shù)據(jù) X_in 是一批一批的 MNIST 字符,網(wǎng)絡(luò)會(huì)學(xué)習(xí)如何重建它們。然后在一個(gè)占位符 Y 中輸出它們,輸出和輸入具有相同的維度。

Y_flat 將會(huì)在后面計(jì)算損失函數(shù)的時(shí)候用到,keep_prob 將會(huì)在應(yīng)用 dropout 的時(shí)候用到(作為一種正則化的方法)。在訓(xùn)練的過程中,它的值會(huì)設(shè)為 0.8,當(dāng)生成新數(shù)據(jù)的時(shí)候,我們不使用 dropout,所以它的值會(huì)變成 1。

lrelu 函數(shù)需要自及定義,因?yàn)?TensorFlow 中并沒有預(yù)定義一個(gè) Leaky ReLU 函數(shù)。

  1. tf.reset_default_graph() 
  2.  
  3. batch_size = 64X_in = tf.placeholder(dtype=tf.float32, shape=[None, 28, 28], name='X'
  4. Y    = tf.placeholder(dtype=tf.float32, shape=[None, 28, 28], name='Y'
  5. Y_flat = tf.reshape(Y, shape=[-1, 28 * 28]) 
  6. keep_prob = tf.placeholder(dtype=tf.float32, shape=(), name='keep_prob'
  7.  
  8. dec_in_channels = 1n_latent = 8reshaped_dim = [-1, 7, 7, dec_in_channels] 
  9. inputs_decoder = 49 * dec_in_channels / 2def lrelu(x, alpha=0.3):    return tf.maximum(x, tf.multiply(x, alpha))  

定義編碼器

因?yàn)槲覀兊妮斎胧菆D像,所以使用一些卷積變換會(huì)更加合理。最值得注意的是我們在編碼器中創(chuàng)建了兩個(gè)向量,因?yàn)榫幋a器應(yīng)該創(chuàng)建服從高斯分布的對象。

  • 一個(gè)是均值向量
  • 一個(gè)是標(biāo)準(zhǔn)差向量

在后面你會(huì)看到,我們是如何「強(qiáng)制」編碼器來保證它確實(shí)生成 了服從正態(tài)分布的數(shù)據(jù)點(diǎn),我們可以把將會(huì)被輸入到解碼器中的編碼值表示為 z。在計(jì)算損失函數(shù)的時(shí)候,我們會(huì)需要我們所選分布的均值和標(biāo)準(zhǔn)差。

  1. def encoder(X_in, keep_prob): 
  2.     activation = lrelu    with tf.variable_scope("encoder", reuse=None): 
  3.         X = tf.reshape(X_in, shape=[-1, 28, 28, 1]) 
  4.         x = tf.layers.conv2d(X, filters=64, kernel_size=4, strides=2, padding='same', activation=activation) 
  5.         x = tf.nn.dropout(x, keep_prob) 
  6.         x = tf.layers.conv2d(x, filters=64, kernel_size=4, strides=2, padding='same', activation=activation) 
  7.         x = tf.nn.dropout(x, keep_prob) 
  8.         x = tf.layers.conv2d(x, filters=64, kernel_size=4, strides=1, padding='same', activation=activation) 
  9.         x = tf.nn.dropout(x, keep_prob) 
  10.         x = tf.contrib.layers.flatten(x) 
  11.         mn = tf.layers.dense(x, units=n_latent) 
  12.         sd       = 0.5 * tf.layers.dense(x, units=n_latent)             
  13.         epsilon = tf.random_normal(tf.stack([tf.shape(x)[0], n_latent]))  
  14.         z  = mn + tf.multiply(epsilon, tf.exp(sd))         
  15.         return z, mn, sd  

定義解碼器

解碼器不會(huì)關(guān)心輸入值是不是從我們定義的某個(gè)特定分布中采樣得到的。它僅僅會(huì)嘗試重建輸入圖像。最后,我們使用了一系列的轉(zhuǎn)置卷積(transpose convolution)。

  1. def decoder(sampled_z, keep_prob):    with tf.variable_scope("decoder", reuse=None): 
  2.         x = tf.layers.dense(sampled_z, units=inputs_decoder, activation=lrelu) 
  3.         x = tf.layers.dense(x, units=inputs_decoder * 2 + 1, activation=lrelu) 
  4.         x = tf.reshape(x, reshaped_dim) 
  5.         x = tf.layers.conv2d_transpose(x, filters=64, kernel_size=4, strides=2, padding='same', activation=tf.nn.relu) 
  6.         x = tf.nn.dropout(x, keep_prob) 
  7.         x = tf.layers.conv2d_transpose(x, filters=64, kernel_size=4, strides=1, padding='same', activation=tf.nn.relu) 
  8.         x = tf.nn.dropout(x, keep_prob) 
  9.         x = tf.layers.conv2d_transpose(x, filters=64, kernel_size=4, strides=1, padding='same', activation=tf.nn.relu) 
  10.          
  11.         x = tf.contrib.layers.flatten(x) 
  12.         x = tf.layers.dense(x, units=28*28, activation=tf.nn.sigmoid) 
  13.         img = tf.reshape(x, shape=[-1, 28, 28])        return img  

現(xiàn)在,我們將兩部分連在一起。

  1. sampled, mn, sd = encoder(X_in, keep_prob) 
  2.  
  3. dec = decoder(sampled, keep_prob)  

計(jì)算損失函數(shù),并實(shí)施一個(gè)高斯隱藏分布

為了計(jì)算圖像重構(gòu)的損失函數(shù),我們簡單地使用了平方差(這有時(shí)候會(huì)使圖像變得有些模糊)。這個(gè)損失函數(shù)還結(jié)合了 KL 散度,這確保了我們的隱藏值將會(huì)從一個(gè)標(biāo)準(zhǔn)分布中采樣。關(guān)于這個(gè)主題,如果想要了解更多,可以看一下這篇文章(https://jaan.io/what-is-variational-autoencoder-vae-tutorial/)。

  1. unreshaped = tf.reshape(dec, [-1, 28*28]) 
  2. img_loss = tf.reduce_sum(tf.squared_difference(unreshaped, Y_flat), 1) 
  3. latent_loss = -0.5 * tf.reduce_sum(1.0 + 2.0 * sd - tf.square(mn) - tf.exp(2.0 * sd), 1) 
  4. loss = tf.reduce_mean(img_loss + latent_loss) 
  5. optimizer = tf.train.AdamOptimizer(0.0005).minimize(loss) 
  6. sess = tf.Session() 
  7. sess.run(tf.global_variables_initializer())  

訓(xùn)練網(wǎng)絡(luò)

現(xiàn)在我們終于可以訓(xùn)練我們的 VAE 了!

每隔 200 步,我們會(huì)看一下當(dāng)前的重建是什么樣子的。大約在處理了 2000 次迭代后,大多數(shù)重建看上去是挺合理的。

  1. for i in range(30000): 
  2.     batch = [np.reshape(b, [28, 28]) for b in mnist.train.next_batch(batch_size=batch_size)[0]] 
  3.     sess.run(optimizer, feed_dict = {X_in: batch, Y: batch, keep_prob: 0.8})         
  4.     if not i % 200: 
  5.         ls, d, i_ls, d_ls, mu, sigm = sess.run([loss, dec, img_loss, dst_loss, mn, sd], feed_dict = {X_in: batch, Y: batch, keep_prob: 1.0}) 
  6.         plt.imshow(np.reshape(batch[0], [28, 28]), cmap='gray'
  7.         plt.show() 
  8.         plt.imshow(d[0], cmap='gray'
  9.         plt.show() 
  10.         print(i, ls, np.mean(i_ls), np.mean(d_ls))  

生成新數(shù)據(jù)

最驚人的是我們現(xiàn)在可以生成新的字符了。最后,我們僅僅是從一個(gè)單位正態(tài)分布里面采集了一個(gè)值,輸入到解碼器。生成的大多數(shù)字符都和人類手寫的是一樣的。

  1. randoms = [np.random.normal(0, 1, n_latent) for _ in range(10)] 
  2. imgs = sess.run(dec, feed_dict = {sampled: randoms, keep_prob: 1.0}) 
  3. imgs = [np.reshape(imgs[i], [28, 28]) for i in range(len(imgs))]for img in imgs: 
  4.     plt.figure(figsize=(1,1)) 
  5.     plt.axis('off'
  6.     plt.imshow(img, cmap='gray' 

一些自動(dòng)生成的字符。

總結(jié)

這是關(guān)于 VAE 應(yīng)用一個(gè)相當(dāng)簡單的例子。但是可以想象一下更多的可能性!神經(jīng)網(wǎng)絡(luò)可以學(xué)習(xí)譜寫音樂,它們可以自動(dòng)地創(chuàng)建對書籍、游戲的描述。借用創(chuàng)新思維,VAE 可以為一些新穎的項(xiàng)目開創(chuàng)空間。 

責(zé)任編輯:龐桂玉 來源: 36大數(shù)據(jù)
相關(guān)推薦

2021-03-29 11:37:50

人工智能深度學(xué)習(xí)

2021-03-22 10:52:13

人工智能深度學(xué)習(xí)自編碼器

2025-04-10 11:52:55

2021-02-20 20:57:16

深度學(xué)習(xí)編程人工智能

2017-07-19 13:40:42

卷積自編碼器降噪

2022-04-02 21:46:27

深度學(xué)習(xí)編碼器圖像修復(fù)

2024-06-18 08:52:50

LLM算法深度學(xué)習(xí)

2024-10-21 16:47:56

2018-05-21 08:22:14

自編碼器協(xié)同過濾深度學(xué)習(xí)

2017-12-26 10:48:37

深度學(xué)習(xí)原始數(shù)據(jù)

2017-07-03 07:14:49

深度學(xué)習(xí)無監(jiān)督學(xué)習(xí)稀疏編碼

2025-04-10 06:30:00

2020-04-26 11:26:02

人臉合成編碼器數(shù)據(jù)

2023-08-14 08:30:32

2024-08-09 08:12:35

深度學(xué)習(xí)VAEsGANs

2017-05-08 22:40:55

深度學(xué)習(xí)自編碼器對抗網(wǎng)絡(luò)

2022-09-13 15:26:40

機(jī)器學(xué)習(xí)算法數(shù)據(jù)

2025-04-08 04:20:00

2021-11-02 20:44:47

數(shù)字化

2024-11-13 16:24:33

ViT架構(gòu)PyTorch
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號