在 PyTorch 中实现深度自动编码器以进行图像重建p

machine learningpythonpytorch

机器学习是人工智能的一个分支,涉及开发统计模型和算法,使计算机能够从输入数据中学习并做出决策或预测,而无需进行硬编程。它涉及使用大型数据集训练 ML 算法,以便机器可以识别数据中的模式和关系。

什么是自动编码器?

带有自动编码器的神经网络架构用于无监督学习任务。它由一个编码器和解码器网络组成,这些编码器和解码器经过训练,可以通过将输入数据压缩为低维表示(编码)然后对其进行解码以将其恢复为原始形式来重建输入数据。

为了鼓励网络学习数据的有价值的特征或表示,目标是最小化输入和输出之间的重建误差。数据压缩、图片去噪和异常检测是自动编码器的主要用途。这减少了与传输数据相关的大量工作量和成本。

在本文中,我们将探讨如何使用 PyTorch 的深度自动编码器进行图片重建。该深度学习模型将在 MNIST 手写数字上进行训练,在学习输入图像的表示后,它将重建数字图像。基本的自动编码器由两个主要功能组成 -

  • 编码器

  • 解码器

编码器获取输入并通过一系列层将高维数据转换为相同值的潜在低维表示。解码器使用此潜在表示,使用 Python 库 torch、PyTorch 工作流中的 torch vision 库以及 numpy 和 matplotlib 等通用库来生成重建数据。

算法

  • 导入所有必需的库。

  • 初始化将应用于所获数据集中每个条目的转换操作。

  • 由于张量是 Pytorch 运行所必需的,我们首先将每个项目转换为张量并对其进行规范化,以保留 0 到 1 之间的像素值范围。

  • 使用 torchvision.datasets 程序,下载数据集并将其本地保存在文件夹 ./MNIST/train 和 ./MNIST/test 中,分别用于训练和测试集。

  • 为了更快地学习,将这些数据集转换为批处理大小等于 64 的数据加载器。

  • 从集合中随机打印 25 张照片,以便我们更好地理解我们正在处理的信息。

步骤 1:初始化

此步骤涉及导入所有必要的库,例如 numpy、matplotlib、pytorch 和 torchvision。

语法

torchvision.transforms.ToTensor():

将输入图像(PIL 或 numpy 格式)转换为 PyTorch 张量格式。此转换还将像素强度从范围 [0, 255] 缩放到 [0, 1]。

torchvision.transforms.Normalize(mean, std)

使用平均值和标准差值对输入图像张量进行归一化。此转换有助于提高深度学习模型在训练期间的收敛速度。平均值和标准差通常根据训练数据集计算得出。

torchvision.transforms.Compose(transforms)

允许将多个图像转换链接在一起形成一个对象。该对象可以传递给 PyTorch Dataset 对象,以便在训练或推理期间即时应用转换。

示例

#导入模块
导入 numpy 作为 np
导入 matplotlib.pyplot 作为 plt
导入 torch
从 torchvision 导入数据集、转换
plt.rcParams['figure.figsize'] = 15, 10

# 初始化转换操作
transform = torchvision.transforms.Compose([
   torchvision.transforms.ToTensor(),
   torchvision.transforms.Normalize((0.5), (0.5))
])

# 下载内置的 MNIST 数据
train_dataset = torchvision.datasets.MNIST(
   root="./MNIST/train", train=True,
   transform=torchvision.transforms.ToTensor(),
   download=True)
test_dataset = torchvision.datasets.MNIST(
   root="./MNIST/test", train=False,
   transform=torchvision.transforms.ToTensor(),
   download=True)

输出

步骤 2:初始化自动编码器

我们首先初始化 Autoencoder 类,它是 torch.nn.Module 的一个子类。现在我们可以集中精力创建模型架构,如下所示,因为这为我们抽象出了很多样板代码。

语法

torch.nn.Linear()

将线性变换应用于输入张量的模块。

my_linear_layer = nn.Linear(in_features, out_features, bias=True)

torch.nn.ReLU()

将整流线性单元 (ReLU) 函数应用于输入张量的激活函数。

torch.nn.Sigmoid()

激活函数将 S 型函数应用于输入张量。

示例

# 创建自动编码器类
class Autoencoder(torch.nn.Module):
   def __init__(self):
      super().__init__()
      self.encoder=torch.nn.Sequential(
         torch.nn.Linear(28*28,128), #N, 784 -> 128
         torch.nn.ReLU(),
         torch.nn.Linear(128,64),
         torch.nn.ReLU(),
         torch.nn.Linear(64,12),
         torch.nn.ReLU(),
         torch.nn.Linear(12,3), # --> N, 3
         torch.nn.ReLU()
      )
        
      self.decoder=torch.nn.Sequential(
         torch.nn.Linear(3,12), #N, 3 -> 12
         torch.nn.ReLU(),
         torch.nn.Linear(12,64),
         torch.nn.ReLU(),
         torch.nn.Linear(64,128),
         torch.nn.ReLU(),
         torch.nn.Linear(128,28*28), # --> N, 28*28
         torch.nn.Sigmoid()
      )
        
   def forward(self,x):
      encoded=self.encoder(x)
      decoded = self.decoder(encoded)
      return decoded

# 实例化模型和超参数
model = Autoencoder()
criterion = torch.nn.MSELoss()
num_epochs = 10
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

步骤 3:创建训练循环

我们正在训练自动编码器模型来学习图像的压缩表示。训练循环总共遍历数据集 10 次。

  • 针对每一批照片计算模型的输出,对每一批图像进行迭代。

  • 然后计算输出照片和原始图片之间的质量差异。

  • 它对每一批的损失取平均值,并存储每个时期的图像及其输出。

  • 我们在循环完成时描绘训练损失,以帮助理解训练过程。

该图显示,损失随着每个时期的过去而降低,表明模型正在获取新信息并且训练过程成功。

训练循环通过最小化输出图像和原始图像之间的损失来训练自动编码器模型学习图像的压缩表示。损失会随着每个时期而减少,表明训练成功。

示例

# 创建空列表来存储训练损失
train_loss = []
# 创建空字典来存储图像及其重建的输出
outputs = {}
# 循环遍历每个时期
for epoch in range(num_epochs):
    # 初始化变量以存储运行损失
    running_loss = 0
    # 循环遍历训练数据中的每个批次
    for batch in train_loader:
                
        # 加载图像及其标签
        img, _ = batch
        # 将图像展平为 1D 张量
        img = img.view(img.size(0), -1)
        # 为自动编码器模型生成输出
        out = model(img)
        # 计算输入和输出图像之间的损失
        loss = criterion(out, img)
        # 重置梯度
        optimizer.zero_grad()
        # 计算梯度
        loss.backward()
        # 更新权重
        optimizer.step()
        # 将运行损失增加批次损失
        running_loss += loss.item()     
    # 计算整个数据集的平均运行损失
    running_loss /= len(train_loader)
    # 将运行损失添加到训练损失列表中
    train_loss.append(running_loss)
    # 存储最后一批的输入和输出图像
    output[epoch+1] = {'input': img, 'output': out}

# 绘制各个时期的训练损失
plt.plot(range(1, num_epochs+1), train_loss)
plt.xlabel("Number of epochs")
plt.ylabel("Training Loss")
plt.show()

输出

步骤 4:可视化

使用此代码绘制经过训练的自动编码器模型的原始图像和重建图像。变量输出包括有关模型输出的数据,例如重建图像和损失值,这些数据是在各个训练时期记录的。要绘制特定时期的重建图像,请使用 list_epochs 变量。

该程序绘制每个给定时期的最新批次的前五张重建图像。

示例

# 绘制重建的图像
# 初始化计数器
count = 1
# 绘制重建的图像
list_epochs = [1, 5, 10]

# 迭代指定的 epochs
for val in list_epochs:
    
    # 提取记录的信息
    temp = output[val]['out'].detach().numpy()
    title_text = f"Epoch = {val}"
    
    # 绘制最后一批的前 5 张图像
    for idx in range(5):
      plt.subplot(7, 5, count)
      plt.title(title_text)
      plt.imshow(temp[idx].reshape(28,28), cmap= 'gray')
      plt.axis('off')
          
      # 增加计数
      count+=1
# 原始图像的绘图

# 迭代前五个

# 最后一批图像
for idx in range(5):

    # 从字典中获取图像
    val = output[10]['img']
    
    # 绘制图像
    plt.subplot(7,5,count)
    plt.imshow(val[idx].reshape(28, 28),
    cmap = 'gray')
    plt.title("Original Image")
    plt.axis('off')
    
    # 增加计数
   	count+=1
  
plt.tight_layout()
plt.show()

输出

步骤 5:测试集性能评估

此代码是如何评估经过训练的自动编码器模型在测试集上的性能的示例。

根据对重建图像的目视检查,代码得出结论,自动编码器模型在测试集上表现良好。如果模型在测试集上表现良好,那么它很可能在新的、未见过的数据上表现良好。

示例

outputs = {}

# 提取最后一批数据集
img, _ = list(test_loader)[-1]

img = img.reshape(-1, 28 * 28)

# 生成输出
out = model(img)

# 将结果存储在字典中
outputs['img'] = img
outputs['out'] = out

# 初始化子图计数
count = 1
val = output['out'].detach().numpy()

# 绘制批次的前 10 张图像
for idx in range(10):
   plt.subplot(2, 10, count)
   plt.title("Reconstructed \n image")
   plt.imshow(val[idx].reshape(28, 28), cmap='gray')
   plt.axis('off')
  
    # 增加子图数量
    count += 1
# 绘制原始图像
# 绘制前 10 张图像
for idx in range(10):
   val = outputs['img']
   plt.subplot(2, 10, count)
   plt.imshow(val[idx].reshape(28, 28), cmap='gray')
   plt.title("Original Image")
   plt.axis('off')
   count += 1
  
plt.tight_layout()
plt.show()

输出

结论

总之,自动编码器是强大的神经网络,可以应用于许多不同的任务,包括数据压缩、异常检测和图像创建。TensorFlow、Keras 和 PyTorch 是一些使自动编码器开发变得简单的 Python 工具。您可以通过理解架构和调整设置来开发极其强大的自动编码器模型。随着机器学习领域的进步,自动编码器可能会继续成为各种应用的有用工具。


相关文章