Tensorflow与自编码器
使用Tensorflow实现自编码器
自编码器原理
Fashion MNIST 图片重建实战
- 自编码器算法原理非常简单,实现方便,训练也较稳定,相对于 PCA 算法,神经网络 的强大表达能力可以学习到输入的高层抽象的隐藏特征向量𝒛,同时也能够基于𝒛重建出输入
Fashion MNIST 数据集
- 利用keras.datasets.fashion_mnist.load_data()函数即可在线下载、管理和加载。
# 加载Fashion MNIST图片数据集 |
编码器
- 利用 3 层的神经网络将长度为 784 的图片向量数据依次 降维到 256、128,最后降维到 h_dim 维度,每层使用 ReLU 激活函数,最后一层不使用激 活函数
# 创建Encoders网络,实现在自编码器类的初始化函数中 |
解码器
- 基于隐藏向量 h_dim 依次升维到 128、256、784 长 度,除最后一层,激活函数使用 ReLU 函数。解码器的输出为 784 长度的向量,代表了打 平后的28 × 28大小图片,通过 Reshape 操作即可恢复为图片矩阵
# 创建Decoders网络 |
自编码器
- 网络结构
class AE(keras.Model): |
- 前向传播过程实现在 call 函数中,输入图片首先通过 encoder 子网络得到隐 藏向量 h,再通过 decoder 得到重建图片
def call(self, inputs, training=None): # 前向传播函数 |
网络训练
- 创建自编码器实例和优化器,并设置合适的学习率
# 创建网络对象 |
- 固定训练 100 个 Epoch,每次通过前向计算获得重建图片向量,并利用 tf.nn.sigmoid_cross_entropy_with_logits 损失函数计算重建图片与原始图片直接的误差,实 际上利用 MSE 误差函数也是可行的
for epoch in range(100): |
图片重建
- 为了测试图片重建效果,我们把数据集切分为训练集与测试集,其中测试集不参与训 练。我们从测试集中随机采样测试图片𝒙 ∈ 𝔻test,经过自编码器计算得到重建后的图片, 然后将真实图片与重建图片保存为图片阵列,并可视化,方便比对
# 重建图片,从测试集采样一批图片 |
- save_images 函数负责将多张图片合并并保存为一张大图,这部分代码使用 PIL 图片库完成图片阵列逻辑
def save_images(imgs, name): |
VAE 图片生成实战
- 输入为 Fashion MNIST 图片向量,经过 3 个全连接层后得到隐向量𝐳的均值与方差,分别用两 个输出节点数为 20
的全连接层表示,FC2 的 20 个输出节点表示 20 个特征分布的均值向量u,FC3 的 20 个输出节点表示 20
个特征分布的取log后的方差向量。通过 Reparameterization Trick 采样获得长度为 20 的隐向量𝐳,并通过
FC4 和 FC5 重建出样本图片。 - VAE 作为生成模型,除了可以重建输入样本,还可以单独使用解码器生成样本。通过
从先验分布𝑝(𝐳)中直接采样获得隐向量𝐳,经过解码后可以产生生成的样本。
VAE 模型
- 创建 Encoder 和 Decoder 需要的网络层
class VAE(keras.Model): |
- Encoder 的输入先通过共享层 FC1,然后分别通过 FC2 与 FC3 网络,获得隐向量分布 的均值向量与方差的log向量值
def encoder(self, x): |
- Decoder 接受采样后的隐向量𝐳,并解码为图片输出
def decoder(self, z): |
- 在 VAE 的前向计算过程中,首先通过编码器获得输入的隐向量𝐳的分布,然后利用 Reparameterization Trick 实现的 reparameterize 函数采样获得隐向量𝐳,最后通过解码器即可 恢复重建的图片向量
def call(self, inputs, training=None): # 前向计算 |
- Reparameterize 函数接受均值与方差参数,并从正态分布𝒩(0, 𝐼)中采样获得𝜀,通过 z= 𝜇 + 𝜎 ⊙ 𝜀方式返回采样隐向量。
def reparameterize(self, mu, log_var): |
网络训练
# 创建网络对象 |
图片生成
- 图片生成只利用到解码器网络,首先从先验分布𝒩(0, 𝐼)中采样获得隐向量,再通过解 码器获得图片向量,最后 Reshape 为图片矩阵。
# 测试生成效果,从正态分布随机采样z |