(深度学习快速入门)自编码器及其变体(关键词:自编码器堆叠降噪变分AESAESDAEVAE)

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(深度学习快速入门)自编码器及其变体(关键词:自编码器堆叠降噪变分AESAESDAEVAE)相关的知识,希望对你有一定的参考价值。

文章目录

一:自编码器(AE)

自编码器(Auto-Encoders, AE):自编码器可以理解为一个试图还原原始输入的系统,主要由编码器(Encoder)和解码器(Decoder)组成,其主要目的是将输入 x x x转换成中间变量 y y y,然后再把 y y y转化为 x ︿ \\mathopx\\limits^︿ x︿,训练 x x x x ︿ \\mathopx\\limits^︿ x︿让它们无限接近

从直观上来看,自动编码器可以用于特征降维,类似主成分分析PCA,但是其相比PCA其性能更强,这是由于神经网络模型可以提取更有效的新特征。除了进行特征降维,自动编码器学习到的新特征可以送入有监督学习模型中,所以自动编码器可以起到特征提取器的作用

比如下图,将手写数字图片进行编码,编码后生成的 ϕ 1 \\phi_1 ϕ1~ ϕ 6 \\phi_6 ϕ6 较完整的保留了原始图像的典型特征,因此可较容易地通过解码恢复出原始图像

如下,利用Pytorch实现一个简单的自编码器

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

# 定义网络模型
class Autoencoder(nn.Module):
    def __init__(self):
        super(Autoencoder, self).__init__()
        
        self.encoder = nn.Sequential(
            nn.Linear(28 * 28, 128),
            nn.ReLU(True),
            nn.Linear(128, 64),
            nn.ReLU(True),
            nn.Linear(64, 12),
            nn.ReLU(True),
            nn.Linear(12, 3),   # encoding layer
        )
        self.decoder = nn.Sequential(
            nn.Linear(3, 12),
            nn.ReLU(True),
            nn.Linear(12, 64),
            nn.ReLU(True),
            nn.Linear(64, 128),
            nn.ReLU(True),
            nn.Linear(128, 28 * 28),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

# 加载数据集并预处理
from torchvision.datasets import MNIST

dataset = MNIST(root='data/', download=True)

data_loader = torch.utils.data.DataLoader(dataset=dataset,
                                          batch_size=100, 
                                          shuffle=True)

# 定义损失函数和优化器
model = Autoencoder().cuda()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
for epoch in range(100):
    for data in data_loader:
        img, _ = data
        img = img.view(img.size(0), -1).cuda()
        # ===================forward=====================
        output = model(img)
        loss = criterion(output, img)
        # ===================backward====================
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    # ===================log========================
    print('epoch [/], loss::.4f'
          .format(epoch + 1, 100, loss.data.item()))

# 保存模型
torch.save(model.state_dict(), 'autoencoder.pth')

二:自编码器变体

(1)堆叠自编码器(SAE)

堆叠自编码器(Stacked Autoencoder, SAE):将多个自编码器进行堆叠,每个自编码器的输出都作为下一个自编码器的输入,并且每个自编码器都可以训练从原始数据到低维表示的映射

如下,用Pytorch实现一个堆叠自编码器

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms

# 设置随机种子
torch.manual_seed(0)

# 加载 MNIST 数据集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=64, shuffle=True)

test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('data', train=False, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=64, shuffle=True)

# 定义自动编码器模型
class Autoencoder(nn.Module):
    def __init__(self):
        super(Autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(28 * 28, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 32),
            nn.ReLU()
        )
        self.decoder = nn.Sequential(
            nn.Linear(32, 64),
            nn.ReLU(),
            nn.Linear(64, 128),
            nn.ReLU(),
            nn.Linear(128, 28 * 28),
            nn.Sigmoid()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

# 堆叠自动编码器
class StackedAutoencoder(nn.Module):
    def __init__(self):
        super(StackedAutoencoder, self).__init__()
        self.autoencoder1 = Autoencoder()
        self.autoencoder2 = Autoencoder()
        self.autoencoder3 = Autoencoder()

    def forward(self, x):
        x = self.autoencoder1(x)
        x = self.autoencoder2(x)
        x = self.autoencoder3(x)
        return x

# 创建堆叠自动编码器模型
model = StackedAutoencoder()
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 30
for epoch in range(num_epochs):
    for data in train_loader:
        img, _ = data
        img = img.view(img.size(0), -1)
        output = model(img)
        loss = criterion(output, img)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    if (epoch+1) % 5 == 0:
        print('Epoch [/], Loss: :.4f'.format(epoch+1, num_epochs, loss.item()))

# 在测试数据上评估模型
with torch.no_grad():
    correct = 0
    total = 0
    for data in test_loader:
        img, label = data
        img = img.view(img.size(0), -1)
        output = model(img)
        total += label.size(0)
        correct += (output.round() == img).sum().item()
    print('Accuracy on test set: / (:.0f%)'.format(correct, total, 100. * correct / total))



(2)降噪自编码器(DAE)

降噪自编码(Denoising Auto-Encoders, DAE):首先对干净的输入信号加入噪声产生一个受损的信号。然后将受损信号送入传统的自动编码器中,使其重建回原来的无损信号

降噪编码器与传统自编码器的主要区别在于

  • 降噪自编码器通过人为的增加噪声使模型获得鲁棒性的特征表达
  • 避免使隐层单元学习一个传统自编码器中没有意义的恒等函数

降噪自编码器优缺点

  • 优点:重建信号对输入中的噪声具有一定的鲁棒性
  • 缺点:每次进行网络训练之前,都需要对干净输入信号人为地添加噪声,以获得它的损坏信号,这无形中就增加了该模型的处理时间

(3)堆叠降噪自编码器(SDAE)

堆叠降燥自编码器 (Stacked Denoising Auto-Encoders, SDAE):它是降噪自编码器的一个应用方法,采用了降噪编码器的编码器(encoder)作为基础单元,这个编码器是被预训练(pre-training)好的

如下图所示,编码器 f 1 f_1 f1, f 2 f_2 f2,…, f n f_n fn分别对应的是预训练号的降噪自编码器 D 1 D_1 D1 D 2 D_2 D2 D n D_n Dn的编码函数(编码器)

堆叠降噪自编码器训练过程如下

  • 输入 x x x
  • 加入噪声,和 f 1 f_1 f1对应的解码器 f 1 、 f_1^、 f1采用降噪自编码器的方式进行训练
  • 固定 f 1 f_1 f1,以相同方式训练 f 2 f_2 f2, f 3 f_3 f3,…, f n f_n fn,并在最后一层加入分类器
  • 利用 x x x的真实标签和预测标签以监督方式进行训练,对网络参数进行微调

SDAE可以看作是监督学习和无监督学习的结合。在无监督学习中,通过编码-解码过程学习输入数据的表示,而不需要标记数据。并且,其降噪方面通过强制它从损坏的版本重建原始输入,进一步增强了它学习有意义的数据表示的能力。在监督学习中,它学习到的表示可以用作下游监督任务的特征,例如分类或回归。其最后一层通常替换为分类器或回归器,自动编码器的权重根据特定任务的标记数据进行微调。因此,SDAE 可以被视为无监督学习和有监督学习的混合体,其中无监督组件为数据提供有意义的表示,而有监督组件将这些表示用于特定任务

(4)变分自编码器(VAE)

变分自动编码器(Variational Auto-Encoders, VAE):是一种主要用于数据生成的自编码器的变体。首先利用数据训练变分自编码器,然后只使用变分自编码器的解码部分,自动生成与训练数据类似的输出。相当于在传统自编码器的隐层表达上增加一个对隐变量的约束(目的使编码器产生的隐层表达满足正态分布,能够更好的生成图像模型),是一种将概率模型和神经网络结构结合的方法

整个结构可以分成三个部分,分别是编码部分,解码部分和生成部分。编码部分和解码部分同时进行训练

VAE采用方差推断技术最大化ELBO公式

其中

  • D K L D_KL DKL表示两个分布之间的KL散度
  • p h p_h ph是潜在表征的先验分布
  • q ( h ∣ x ; ϕ ) q(h|x;\\phi) q(hx;ϕ)是表示的变分后验,用来逼近真实后验

如下,使用Pytorch实现一个简单的VAE模型

VAE的架构由两部分组成:编码器和解码器。编码器获取输入数据 x 并通过两个全连接层 fc1 和 fc2 将其转换为潜在表示 z。 reparameterize 方法从均值 mu 和方差 log_var 的对数生成样本 z。然后解码器采用潜在表示 z 并通过两个完全连接的层 fc3 和 fc4 重建原始数据 x。
import torch
import torch.nn as nn
import torch.nn.functional as F

class VAE(nn.Module):
    def __init__(self, input_size, hidden_size, latent_size):
        super(VAE, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, latent_size * 2)
        self.fc3 = nn.Linear(latent_size, hidden_size)
        self.fc4 = nn.Linear(hidden_size, input_size)

    def encode(self, x):
        h = F.relu(self.fc1(x))
        return self.fc2(h)

    def reparameterize(self, mu, log_var):
        std = torch.exp(0.5 * log_var)
        eps = torch.randn_like(std)
        return mu + eps * std

    def decode(self, z):
        h = F.relu(self.fc3(z))
        return torch1 TensorFlow介绍
  • 2 TensorFlow的安装
  • 3 张量及其操作
  • 4 tf.keras介绍
  • 5 总结

  • 1 TensorFlow介绍

    深度学习框架TensorFlow一经发布,就受到了广泛的关注,并在计算机视觉、音频处理、推荐系统和自然语言处理等场景下都被大面积推广使用,接下来我们深入浅出的介绍Tensorflow的相关应用。

    TensorFlow的依赖视图如下所示:

    • TF托管在github平台,有google groups和contributors共同维护。
    • TF提供了丰富的深度学习相关的API,支持Python和C/C++接口。
    • TF提供了可视化分析工具Tensorboard,方便分析和调整模型。
    • TF支持Linux平台,Windows平台,Mac平台,甚至手机移动设备等各种平台。

    TensorFlow 2.0 将专注于简单性和易用性,工作流程如下所示:

    1、使用tf.data加载数据。 使用tf.data实例化读取训练数据和测试数据

    2、模型的建立与调试: 使用动态图模式 Eager Execution 和著名的神经网络高层 API 框架 Keras,结合可视化工具 TensorBoard,简易、快速地建立和调试模型;

    3、模型的训练: 支持 CPU / 单 GPU / 单机多卡 GPU / 多机集群 / TPU 训练模型,充分利用海量数据和计算资源进行高效训练;

    4、预训练模型调用: 通过 TensorFlow Hub,可以方便地调用预训练完毕的已有成熟模型。

    5、模型的部署: 通过 TensorFlow Serving、TensorFlow Lite、TensorFlow.js 等组件,可以将TensorFlow 模型部署到服务器、移动端、嵌入式端等多种使用场景;

    2 TensorFlow的安装

    安装 TensorFlow在64 位系统上测试这些系统支持 TensorFlow:

    • Ubuntu 16.04 或更高版本
    • Windows 7 或更高版本
    • macOS 10.12.6 (Sierra) 或更高版本(不支持 GPU)

    进入虚拟环境当中再安装。推荐使用anoconda进行安装

    • 1、非GPU版本安装

    ubuntu安装:pip install tensorflow==2.3.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

    • 2、GPU版本安装

    pip install tensorflow-gpu==2.3.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

    注:如果需要下载GPU版本的(TensorFlow只提供windows和linux版本的,没有Macos版本的)。

    3 张量及其操作

    张量Tensor是一个多维数组。 与NumPy ndarray对象类似,tf.Tensor对象也具有数据类型和形状。如下图所示:

    此外,tf.Tensors可以保留在GPU中。 TensorFlow提供了丰富的操作库(tf.add,tf.matmul,tf.linalg.inv等),它们使用和生成tf.Tensor。在进行张量操作之前先导入相应的工具包:

    import tensorflow as tf
    import numpy as np
    

    首先让我们创建基础的张量:

    # 创建int32类型的0维张量,即标量
    rank_0_tensor = tf.constant(4)
    print(rank_0_tensor)
    # 创建float32类型的1维张量
    rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
    print(rank_1_tensor)
    # 创建float16类型的二维张量
    rank_2_tensor = tf.constant([[1, 2],
                                 [3, 4],
                                 [5, 6]], dtype=tf.float16)
    print(rank_2_tensor)
    

    输出结果为:

    tf.Tensor(4, shape=(), dtype=int32)
    tf.Tensor([2. 3. 4.], shape=(3,), dtype=float32)
    tf.Tensor(
    [[1. 2.]
     [3. 4.]
     [5. 6.]], shape=(3, 2), dtype=float16)
    

    我们也可以创建更高维的张量:

    # 创建float32类型的张量
    rank_3_tensor = tf.constant([
      [[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]],
      [[10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]],
      [[20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]],])
    
    print(rank_3_tensor)
    

    该输出结果我们有更多的方式将其展示出来:

    我们可将张量转换为numpy中的ndarray的形式,转换方法有两种,以张量rank_2_tensor为例:

    • np.array
    np.array(rank_2_tensor)
    
    • Tensor.numpy()
    rank_2_tensor.numpy()
    

    我们可以对张量做一些基本的数学运算,包括加法、元素乘法和矩阵乘法等:

    # 定义张量a和b
    a = tf.constant([[1, 2],
                     [3, 4]])
    b = tf.constant([[1, 1],
                     [1, 1]]) 
    
    print(tf.add(a, b), "\\n") # 计算张量的和
    print(tf.multiply(a, b), "\\n") # 计算张量的元素乘法
    print(tf.matmul(a, b), "\\n") # 计算乘法
    

    输出结果为:

    tf.Tensor(
    [[2 3]
     [4 5]], shape=(2, 2), dtype=int32) 
    
    tf.Tensor(
    [[1 2]
     [3 4]], shape=(2, 2), dtype=int32) 
    
    tf.Tensor(
    [[3 3]
     [7 7]], shape=(2, 2), dtype=int32) 
    

    另外张量也可用于各种聚合运算:

    tf.reduce_sum()  # 求和
    tf.reduce_mean() # 平均值
    tf.reduce_max()  # 最大值
    tf.reduce_min()  # 最小值
    tf.argmax() # 最大值的索引
    tf.argmin() # 最小值的索引
    

    例如:

    c = tf.constant([[4.0, 5.0], [10.0, 1.0]])
    # 最大值
    print(tf.reduce_max(c))
    # 最大值索引
    print(tf.argmax(c))
    # 计算均值
    print(tf.reduce_mean(c))
    

    输出为:

    tf.Tensor(10.0, shape=(), dtype=float32)
    tf.Tensor([1 0], shape=(2,), dtype=int64)
    tf.Tensor(5.0, shape=(), dtype=float32)
    

    变量是一种特殊的张量,形状是不可变,但可以更改其中的参数。定义时的方法是:

    my_variable = tf.Variable([[1.0, 2.0], [3.0, 4.0]])
    

    我们也可以获取它的形状,类型及转换为ndarray:

    print("Shape: ",my_variable.shape)
    print("DType: ",my_variable.dtype)
    print("As NumPy: ", my_variable.numpy)
    

    输出为:

    Shape:  (2, 2)
    DType:  <dtype: 'float32'>
    As NumPy:  <bound method BaseResourceVariable.numpy of <tf.Variable 'Variable:0' shape=(2, 2) dtype=float32, numpy=
    array([[1., 2.],
           [3., 4.]], dtype=float32)>>
    

    4 tf.keras介绍

    tf.keras是TensorFlow 2.0的高阶API接口,为TensorFlow的代码提供了新的风格和设计模式,大大提升了TF代码的简洁性和复用性,官方也推荐使用tf.keras来进行模型设计和开发。

    tf.keras中常用模块如下表所示:

    深度学习实现的主要流程:1.数据获取,2,数据处理,3.模型创建与训练,4 模型测试与评估,5.模型预测

    1. 导入tf.keras:使用 tf.keras,首先需要在代码开始时导入tf.keras
    import tensorflow as tf
    from tensorflow import keras
    
    1. 数据输入:对于小的数据集,可以直接使用numpy格式的数据进行训练、评估模型,对于大型数据集或者要进行跨设备训练时使用tf.data.datasets来进行数据输入。
    2. 模型构建:简单模型使用Sequential进行构建;复杂模型使用函数式编程来构建;自定义layers
    3. 训练与评估:
    • 配置训练过程:
    # 配置优化方法,损失函数和评价指标
    model.compile(optimizer=tf.train.AdamOptimizer(0.001),
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    
    • 模型训练
    # 指明训练数据集,训练epoch,批次大小和验证集数据
    model.fit/fit_generator(dataset, epochs=10, 
                            batch_size=3,
              validation_data=val_dataset,
              )
    
    • 模型评估
    # 指明评估数据集和批次大小
    model.evaluate(x, y, batch_size=32)
    
    • 模型预测
    # 对新的样本进行预测
    model.predict(x, batch_size=32)
    
    1. 回调函数(callbacks)

    回调函数用在模型训练过程中,来控制模型训练行为,可以自定义回调函数,也可使用tf.keras.callbacks 内置的 callback :

    ModelCheckpoint:定期保存 checkpoints。 LearningRateScheduler:动态改变学习速率。 EarlyStopping:当验证集上的性能不再提高时,终止训练。 TensorBoard:使用 TensorBoard 监测模型的状态。

    1. 模型的保存和恢复
    • 只保存参数
    # 只保存模型的权重
    model.save_weights('./my_model')
    # 加载模型的权重
    model.load_weights('my_model')
    
    • 保存整个模型
    # 保存模型架构与权重在h5文件中
    model.save('my_model.h5')
    # 加载模型:包括架构和对应的权重
    model = keras.models.load_model('my_model.h5')
    

    5 总结

    • 了解Tensorflow2.0框架的用途及流程

      1.使用tf.data加载数据

      2、模型的建立与调试

      3、模型的训练

      4、预训练模型调用

      5、模型的部署

    • 知道tf2.0的张量及其操作

      张量是多维数组。

      1、创建方法:tf.constant()

      2、转换为numpy: np.array()或tensor.asnumpy()

      3、常用函数:加法,乘法,及各种聚合运算

      4、变量:tf.Variable()

    • 知道tf.keras中的相关模块及常用方法

      常用模块:models,losses,application等

      常用方法:

      1、导入tf.keras
      
      2、数据输入
      
      3、模型构建
      
      4、训练与评估
      
      5、回调函数
      
      6、模型的保存与恢复
    
    

    以上是关于(深度学习快速入门)自编码器及其变体(关键词:自编码器堆叠降噪变分AESAESDAEVAE)的主要内容,如果未能解决你的问题,请参考以下文章

    DeepFake 入门了解

    深度学习框架Tensorflow快速入门

    DSSM:深度语义匹配模型(及其变体CLSMLSTM-DSSM)

    变分自编码器解析

    《自然语言处理实战入门》深度学习基础 ---- attention 注意力机制 ,Transformer 深度解析与学习材料汇总

    《自然语言处理实战入门》深度学习基础 ---- attention 注意力机制 ,Transformer 深度解析与学习材料汇总