TensorFlow2-自编码器
TensorFlow2自編碼器
簡介
深度學習中也有很多無監督學習的算法,其中,自編碼器是最為典型的代表。事實上,人工標注的數據畢竟是少數,互聯網每天都在產生海量的無標簽數據,如何利用這些數據就是無監督學習研究的重點。自編碼器被廣泛應用于特征提取(數據降維),其降維后的數據,樣本之間保留了較多的相關信息。
自編碼器
對自編碼器這種結構,進行無監督學習的方法就是將輸入作為輸出,盡可能通過先降維后升維的運算后,保持輸入的不變性,從而,降維后的數據包含更多原始的信息。所以,自編碼器的端到端過程其實是一個數據重建過程。
關于自編碼器的訓練,對于不同的數據(二分輸入或真值輸入)采用不同的損失函數(MSE或CE)。相比于PCA這類矩陣運算方法,自編碼器由于非線性特性,丟失信息較少;而且PCA降維后的數據,可解釋性變得很低,而AE降維后的數據解釋性強且具有聚類效果。
下圖左側為PCA降維后各類數據的二維顯示,右側為自編碼器的效果。
自編碼器變種
Denoising AutoEncoders(降噪自編碼器),訓練時將原始數據加入隨機噪聲(如高斯噪聲),這樣,自編碼器模型可以較好地從噪聲圖片中還原真實圖片。
Adversarial AutoEncoders(對抗自編碼器),訓練同時設定一個鑒別器(discriminator),用于堅定中間隱層的輸出是否符合標準的指定分布(這是采用GAN(對抗生成網絡)的思路)。
Variational AutoEncoders(變分自編碼器),用于生成與訓練數據類似分布的數據,盡管曾今有過矚目的表現,但是隨著GAN的發展,收到了極大的沖擊。
自編碼器實戰
通過普通的神經元神經網絡,利用低維隱層捕獲特征,實現如下模型。
""" Author: Zhou Chen Date: 2019/11/17 Desc: About """ import os import tensorflow as tf import numpy as np from tensorflow import keras from tensorflow.keras import Sequential, layers from PIL import Image os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def save_images(imgs, name):"""多圖整合保存:param imgs::param name::return:"""new_im = Image.new('L', (280, 280))index = 0for i in range(0, 280, 28):for j in range(0, 280, 28):im = imgs[index]im = Image.fromarray(im, mode='L')new_im.paste(im, (i, j))index += 1new_im.save(name)h_dim = 20 batchsz = 512 lr = 1e-3(x_train, y_train), (x_test, y_test) = keras.datasets.fashion_mnist.load_data() x_train, x_test = x_train.astype(np.float32) / 255., x_test.astype(np.float32) / 255. train_db = tf.data.Dataset.from_tensor_slices(x_train) train_db = train_db.shuffle(batchsz * 5).batch(batchsz) test_db = tf.data.Dataset.from_tensor_slices(x_test) test_db = test_db.batch(batchsz)print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)class AE(keras.Model):def __init__(self):super(AE, self).__init__()# Encodersself.encoder = Sequential([layers.Dense(256, activation=tf.nn.relu),layers.Dense(128, activation=tf.nn.relu),layers.Dense(h_dim)])# Decodersself.decoder = Sequential([layers.Dense(128, activation=tf.nn.relu),layers.Dense(256, activation=tf.nn.relu),layers.Dense(784)])def call(self, inputs, training=None):# [b, 784] => [b, 10]h = self.encoder(inputs)# [b, 10] => [b, 784]x_hat = self.decoder(h)return x_hatmodel = AE() model.build(input_shape=(None, 784)) model.summary()optimizer = tf.optimizers.Adam(lr=lr)for epoch in range(100):for step, x in enumerate(train_db):# [b, 28, 28] => [b, 784]x = tf.reshape(x, [-1, 784])with tf.GradientTape() as tape:x_rec_logits = model(x)rec_loss = tf.losses.binary_crossentropy(x, x_rec_logits, from_logits=True)rec_loss = tf.reduce_mean(rec_loss)grads = tape.gradient(rec_loss, model.trainable_variables)optimizer.apply_gradients(zip(grads, model.trainable_variables))if step % 100 == 0:print('epoch', epoch, 'step', step, float(rec_loss))# evaluationx = next(iter(test_db))logits = model(tf.reshape(x, [-1, 784]))x_hat = tf.sigmoid(logits)# [b, 784] => [b, 28, 28]x_hat = tf.reshape(x_hat, [-1, 28, 28])# [b, 28, 28] => [2b, 28, 28]x_concat = tf.concat([x, x_hat], axis=0)x_concat = x_hatx_concat = x_concat.numpy() * 255.x_concat = x_concat.astype(np.uint8)save_images(x_concat, 'images/rec_epoch_%d.png' % epoch)VAE學習的是數據分布,依據該分布sample出結果。
""" Author: Zhou Chen Date: 2019/11/17 Desc: About """ import os import tensorflow as tf import numpy as np from tensorflow import keras from tensorflow.keras import Sequential, layers from PIL import Image os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def save_images(imgs, name):new_im = Image.new('L', (280, 280))index = 0for i in range(0, 280, 28):for j in range(0, 280, 28):im = imgs[index]im = Image.fromarray(im, mode='L')new_im.paste(im, (i, j))index += 1new_im.save(name)h_dim = 20 batchsz = 512 lr = 1e-3(x_train, y_train), (x_test, y_test) = keras.datasets.fashion_mnist.load_data() x_train, x_test = x_train.astype(np.float32) / 255., x_test.astype(np.float32) / 255. # we do not need label train_db = tf.data.Dataset.from_tensor_slices(x_train) train_db = train_db.shuffle(batchsz * 5).batch(batchsz) test_db = tf.data.Dataset.from_tensor_slices(x_test) test_db = test_db.batch(batchsz)print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)z_dim = 10class VAE(keras.Model):def __init__(self):super(VAE, self).__init__()# Encoderself.fc1 = layers.Dense(128)self.fc2 = layers.Dense(z_dim) # 均值self.fc3 = layers.Dense(z_dim) # 方差# Decoderself.fc4 = layers.Dense(128)self.fc5 = layers.Dense(784)def encoder(self, x):h = tf.nn.relu(self.fc1(x))mu = self.fc2(h)log_var = self.fc3(h) # 取log方差return mu, log_vardef decoder(self, z):out = tf.nn.relu(self.fc4(z))out = self.fc5(out)return outdef reparameterize(self, mu, log_var):epsilon = tf.random.normal(log_var.shape)std = tf.exp(log_var) ** 0.5z = mu + std * epsilonreturn zdef call(self, inputs, training=None):# [b, 784] => mu:[b, z_dim], log_var[b, z_dim]mu, log_var = self.encoder(inputs)# reparameterization技巧z = self.reparameterize(mu, log_var)x_hat = self.decoder(z)return x_hat, mu, log_varmodel = VAE() model.build(input_shape=(3, 784)) optimizer = tf.optimizers.Adam(lr)for epoch in range(1000):for step, x in enumerate(train_db):x = tf.reshape(x, [-1, 784])with tf.GradientTape() as tape:x_rec_logits, mu, log_var = model(x)rec_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=x, logits=x_rec_logits)rec_loss = tf.reduce_sum(rec_loss) / x.shape[0]kl_div = -0.5 * (log_var + 1 - mu ** 2 - tf.exp(log_var))kl_div = tf.reduce_sum(kl_div) / x.shape[0]loss = rec_loss + 1. * kl_divgrads = tape.gradient(loss, model.trainable_variables)optimizer.apply_gradients(zip(grads, model.trainable_variables))if step % 100 == 0:print(epoch, step, 'kl div:', float(kl_div), 'rec loss:', float(rec_loss))# evaluationz = tf.random.normal((batchsz, z_dim))logits = model.decoder(z)x_hat = tf.sigmoid(logits)x_hat = tf.reshape(x_hat, [-1, 28, 28]).numpy() * 255.x_hat = x_hat.astype(np.uint8)save_images(x_hat, 'images/sampled_epoch%d.png' % epoch)x = next(iter(test_db))x = tf.reshape(x, [-1, 784])x_hat_logits, _, _ = model(x)x_hat = tf.sigmoid(x_hat_logits)x_hat = tf.reshape(x_hat, [-1, 28, 28]).numpy() * 255.x_hat = x_hat.astype(np.uint8)save_images(x_hat, 'images/rec_epoch%d.png' % epoch)補充說明
- 本文介紹了Auto-Encoder在TensorFlow2中的實現,更詳細的可以查看官方文檔。
- 具體的代碼同步至我的Github倉庫歡迎star;博客同步至我的個人博客網站,歡迎查看其他文章。
- 如有疏漏,歡迎指正。
總結
以上是生活随笔為你收集整理的TensorFlow2-自编码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习-神经网络
- 下一篇: TensorFlow2-生成对抗网络