Advertisement

无监督学习之稀疏编码,自编码

阅读量:

文章目录

  • 前言

  • 一、稀疏编码

    • 1.基本概念
    • 2. 模型算法
  • 二、自编码

    • 1. 概念

      • 自编码用途
      • 结构
      • 去噪编码器
    • 2.自编码核心代码

    • 3.去噪编码核心代码

  • 总结


前言


一、稀疏编码

1.基本概念

稀疏编码这一概念源于神经生物学领域,在实际应用中我们常举的例子是每幅画都是由数以亿计的像素构成的,在初级视觉皮层中可以看到这些细节信息。每个神经元仅对特定类型的刺激信号做出反应(例如特殊条纹、特定方向的边缘),经过大脑处理后虽然成本较低但仍然能够实现图像的重建和存储,并且只保留其中最重要的信息特征。以此类比,在外界的信息经过编码处理后也只有少数几个神经元会被激活(即外界信息在神经系统的表示上具有稀疏性)。稀疏编码的主要目标是从大量数据中选择极小数量的关键元素来进行新的数据表示。在编码理论中(线性)编码是指将输入样本X∈RD表示为一组基向量A=[α₁,…α_M]的线性组合形式:x=Σ_{m=1}M z_m α_m其中X代表D维空间中的样本数据(例如一幅图片)。

在这里插入图片描述

A 代表标准化的基础矩阵... ,它相当于由组成元素所构成的基础单元,在这一框架下被定义为基础字典。特别是在图像处理领域中,则表现为基元边与角的集合体。

在这里插入图片描述

A被定义为基向量(一种字典)。其中Z代表用于编码过程中的系数项,在此过程中生成的AZ即为x值。这表明外界环境在经过编码作用后仅激活少量神经元,在系统表示中呈现出高度稀疏的特点。

注:衡量数据稀疏性的关键指标是非零元素所占比例。当一个向量z仅包含少量非零元素时,则称其为一个稀疏向量。

维度角度:D维空间中的样本x被映射到P维空间中进行表示;为了实现稀疏编码的目的,则需要找到一组基向量组,在该基向量组下往往存在冗余信息;从而导致多个有效的稀疏表示。(基于线性代数理论可知,在P大于D的情况下;这会导致对应的稀疏矩阵拥有多个解)
施加一个稀疏性的约束条件后;这将减少解空间的有效大小;最终得到唯一满足稀疏性的编码结果。

2. 模型算法

给定一组N个输入向量。目标函数为

目标函数
  1. \rho用于衡量数据的稀疏性;当数据越稀疏时,\rho(z)值也会相应减小;而超参数η则用于调节这种稀疏程度的强度。
  2. 此外,在实际应用中,衡量数据稀疏性的方法形式多样。
在这里插入图片描述

二、自编码

1. 概念

数据

如果让你从这两组数据中进行记忆训练,哪种形式的数据更易于被记住?乍一看之下可能会认为第一行更容易记住,在深入研究后会发现第二组数据虽然长度较长但也具有一定的规律性——偶数项的后续数值是前一个数值除以2得到的结果;奇数项后续数值则是前一个数值乘以3后再加1所得的结果。这种规律性的存在实际上涉及到了记忆、感知以及模式识别之间的关系。类似于人类大脑如何处理信息的机制,在自编码器的工作流程中同样面临着类似的挑战——其基本功能是通过学习机制将输入数据重新生成输出的过程。自编码器通常由编码器(亦称识别网络)和解码器(亦称生成网络)两个主要组件构成:编码器的作用是将输入的数据映射到一个高效的潜在空间表示中;而解码器则负责将这个潜在空间中的表示重新映射回原始数据空间并完成重建任务。整个过程中都需要经过严格的训练过程才能达到预期的效果

自编码用途

  1. 通过约束模型的参数规模来实现降维。
  2. 深度神经网络中的预训练阶段采用该技术作为强大的特征提取器。
  3. 随机生成与训练数据相似的样本集合被称为生成模型。
  4. 向输入数据中注入噪声后进行微调优化以恢复原始信号。
  5. 当编码层仅能输出K种离散类别时,则该自编码器等价于执行K聚类分析。

结构

学习目标:最小化重构错误

在这里插入图片描述
  • 当特征空间的维度低于原始空间时,则可理解为一种降维或特征提取的过程;
    • 当特征空间的维度高于原始空间时,则必然存在一组或多组解能够使f ,g映射成单位函数,并使重构误差达到零;然而,在引入诸如编码稀疏性等约束条件的情况下,则能够解决一些具有实际意义的问题。
二层

自编码器的架构与多层感知机具有相似性,在于它们都具备相等数量的输入神经元和输出神经元

去噪编码器

一种约束性自编码器通过学习有用特征的方式是通过向输入添加特定类型的噪音,在经过充分训练后能够生成去噪化的输出结果。这种方法能够有效防止自编码器仅仅复制输入信号到输出而不提取其中潜在的有意义模式。

在这里插入图片描述

2.自编码核心代码

代码如:

复制代码
    class autoencoder(nn.Module):#module
    def __init__(self):
        super(autoencoder,self).__init__()
        self.encoder = nn.Sequential(
            #sequential一定要记得大写
        nn.Linear(28*28,1000),
        nn.ReLU(True),
        nn.Linear(1000,500),
        nn.ReLU(True),
        nn.Linear(500,250),
        nn.ReLU(True),
        nn.Linear(250,2))
        
        self.decoder = nn.Sequential(
        nn.Linear(2,250),
        nn.ReLU(True),
        nn.Linear(250,500),
        nn.ReLU(True),
        nn.Linear(500,1000),
        nn.ReLU(True),
        nn.Linear(1000,28*28),
        nn.Tanh())#用tanh来激活
    
    def forward(self,x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

3.去噪编码核心代码

以手写数据集为例,用训练的模型来生成新的图片

导入数据集和库

复制代码
    #加载库和配置参数
    #去噪自编码器
    import torch
    import torch.nn as nn
    import torch.utils as utils
    from torch.autograd import Variable
    import torchvision.datasets as dset
    import torchvision.transforms as transforms
    import numpy as np
    import matplotlib.pyplot as plt
    #配置参数
    torch.manual_seed(2)
    n_epoch=100
    batch_size=100
    learning_rate=0.002
    
    #下载图片库训练集
    mnist_train=dset.MNIST("./",train=True,transform=transforms.ToTensor(),target_transform=None,download=True)
    train_loader=torch.utils.data.DataLoader(dataset=mnist_train,batch_size=batch_size,shuffle=True)
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

Encoder和Decoder模型设置

复制代码
    class Encoder(nn.Module):
    def __init__(self):
        super(Encoder,self).__init__()
        self.layer1=nn.Sequential(
            nn.Conv2d(1,32,3,padding=1),#batch*32*28*28
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.Conv2d(32,32,3,padding=1),#batch*32*28*28
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.Conv2d(32,64,3,padding=1),#batch*64*28*28
            nn.ReLU(),
            nn.BatchNorm2d(64),
            nn.Conv2d(64,64,3,padding=1),#batch*64*28*28
            nn.ReLU(),
            nn.BatchNorm2d(64),
            nn.MaxPool2d(2,2)#batch*64*14*14
        )
        self.layer2=nn.Sequential(
            nn.Conv2d(64,128,3,padding=1),#batch*128*14*14
            nn.ReLU(),
            nn.BatchNorm2d(128),
            nn.Conv2d(128,128,3,padding=1),#batch*128*14*14
            nn.ReLU(),
            nn.BatchNorm2d(128),
            nn.MaxPool2d(2,2),
            nn.Conv2d(128,256,3,padding=1),#batch*256*14*14
            nn.ReLU()
        )
    def forward(self,x):
        out=self.layer1(x)
        out=self.layer2(out)
        out=out.view(batch_size,-1)
        return out
    
    encoder=Encoder()
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

解码

复制代码
    class Decoder(nn.Module):
    def __init__(self):
        super(Decoder,self).__init__()
        self.layer1=nn.Sequential(
            nn.ConvTranspose2d(256,128,3,2,1,1),#batch*128*14*14
            nn.ReLU(),
            nn.BatchNorm2d(128),
            nn.ConvTranspose2d(128,128,3,1,1),#batch*128*14*14
            nn.ReLU(),
            nn.BatchNorm2d(128),
            nn.ConvTranspose2d(128,64,3,1,1),#batch*64*14*14
            nn.ReLU(),
            nn.BatchNorm2d(64),
            nn.ConvTranspose2d(64,64,3,1,1),#batch*64*14*14
            nn.ReLU(),
            nn.BatchNorm2d(64)
        )
        self.layer2=nn.Sequential(
            nn.ConvTranspose2d(64,32,3,1,1),#batch*32*14*14
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.ConvTranspose2d(32,32,3,1,1),#batch*32*14*14
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.ConvTranspose2d(32,1,3,2,1,1),#batch*1*28*28
            nn.ReLU()
        )
    def forward(self,x):
        out=x.view(batch_size,256,7,7)
        out=self.layer1(out)
        out=self.layer2(out)
        return out
    decoder=Decoder()
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
复制代码
    ###Loss 函数和优化器
    parameters=list(encoder.parameters())+list(decoder.parameters())
    loss_func=nn.MSELoss()
    optimizer=torch.optim.Adam(parameters,lr=learning_rate)
    
    ###自编码器训练
    #添加噪声
    noise=torch.rand(batch_size,1,28,28)
    for I in range(n_epoch):
    for image,label in train_loader:
        image_n=torch.mul(image+0.25,0.1*noise)
        image=Variable(image)
        image_n=Variable(image_n)
        optimizer.zero_grad()#loss关于weight的导数变成0.
        output=encoder(image_n)
        output=decoder(output)
        loss=loss_func(output,image)
        loss.backward()
        optimizer.step()#更新所有的参数
        break
    print('epoch[{}/{}],loss:{:.4f}'.format(I+1,n_epoch,loss.item()))
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

训练100次后的损失函数:

在这里插入图片描述
复制代码
    ####带噪图片和去噪图片对比
    img=image[0].cpu()
    input_img=image_n[0].cpu()
    output_img=output[0].cpu()
    
    origin=img.data.numpy()
    inp=input_img.data.numpy()
    out=output_img.data.numpy()
    
    plt.figure('denoising autoencoder')
    
    #一个figure对象包含了多个子图,可以使用subplot()函数来绘制子图
    #这是第一个图
    plt.subplot(131)
    plt.imshow(origin[0])
    plt.subplot(132)
    plt.imshow(inp[0],cmap='gray')
    plt.subplot(133)
    plt.imshow(out[0],cmap='gray')
    
    plt.show()
    print(label[0])
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
在这里插入图片描述

原始图片以第一幅图的形式呈现;经过添加噪声处理的数据展示在第二幅图中;通过解码功能得到的图像显示在第三幅图中,并且其中包含了9个关键特征。

总结

全部评论 (0)

还没有任何评论哟~