自动编码器可以在不重新训练的情况下对新矢量进行编码吗?

时间:2020-04-16 21:41:08

标签: deep-learning pytorch autoencoder

这是一个简单的自动编码器,可将尺寸为1x3:[1,2,3],[1,2,3],[100,200,500]的3个向量编码为1x1:

epochs = 1000
from pylab import plt
plt.style.use('seaborn')
import torch.utils.data as data_utils
import torch
import torchvision
import torch.nn as nn
from torch.autograd import Variable

cuda = torch.cuda.is_available()
FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor
import numpy as np
import pandas as pd
import datetime as dt


features = torch.tensor(np.array([ [1,2,3],[1,2,3],[100,200,500] ]))

print(features)

batch = 1
data_loader = torch.utils.data.DataLoader(features, batch_size=2, shuffle=False)

encoder = nn.Sequential(nn.Linear(3,batch), nn.Sigmoid())
decoder = nn.Sequential(nn.Linear(batch,3), nn.Sigmoid())
autoencoder = nn.Sequential(encoder, decoder)

optimizer = torch.optim.Adam(params=autoencoder.parameters(), lr=0.001)

encoded_images = []
for i in range(epochs):
    for j, images in enumerate(data_loader):
    #     images = images.view(images.size(0), -1) 
        images = Variable(images).type(FloatTensor)
        optimizer.zero_grad()
        reconstructions = autoencoder(images)
        loss = torch.dist(images, reconstructions)
        loss.backward()
        optimizer.step()

#     encoded_images.append(encoder(images))

# print(decoder(torch.tensor(np.array([1,2,3])).type(FloatTensor)))

encoded_images = []
for j, images in enumerate(data_loader):
    images = images.view(images.size(0), -1) 
    images = Variable(images).type(FloatTensor)

    encoded_images.append(encoder(images))

变量encoded_images是一个大小为3的数组,其中每个数组项代表feature数组的降维:

[tensor([[0.9972],
         [0.9972]], grad_fn=<SigmoidBackward>),
 tensor([[1.]], grad_fn=<SigmoidBackward>)]

为了确定新功能的相似性,例如[1,1,1]是否需要重新训练网络,或者可以“引导”现有已训练的网络配置/权重,以便可以对新矢量进行编码不需要重新培训网络?

2 个答案:

答案 0 :(得分:2)

对不起,但是您的代码很混乱……如果只是为了展示自动编码器的想法(在这里,您将image命名为X,Y,Z坐标),选择起来就很糟糕。

顺便说一句:如果这是一幅图像,您将无法将其编码为单个像素,则需要稍微复杂一些。

源代码

这是一个简单的自动编码器,用于编码3个尺寸为1x3的向量: [1,2,3],[1,2,3],[100,200,500]到1x1

仅在这种情况下这是正确的,因为您有一批3元素(而您为网络命名了batch out_features!)。它们的尺寸不是1x3,也只是3。这是带有评论的Minimal Reproducible Example

import torch

# Rows are batches, there could be 3, there could be a thousand
data = torch.tensor([[1, 2, 3], [1, 2, 3], [100, 200, 500]]).float()

# 3 input features, columns of data
encoder = torch.nn.Sequential(torch.nn.Linear(3, 1), torch.nn.Sigmoid())
decoder = torch.nn.Sequential(torch.nn.Linear(1, 3), torch.nn.Sigmoid())

autoencoder = torch.nn.Sequential(encoder, decoder)

optimizer = torch.optim.Adam(params=autoencoder.parameters(), lr=0.001)

epochs = 10000

for i in range(epochs):
    optimizer.zero_grad()
    reconstructions = autoencoder(data)
    loss = torch.dist(data, reconstructions)
    loss.backward()
    optimizer.step()
    # Print loss every 100 epoochs
    if i % 100 == 0:
        print(loss)

它将起作用吗?

这个比较有趣。原则上,如果您的神经网络是经过训练的,则不必重新训练它就可以包含以前没有看到的示例(因为神经网络的目标是学习一些解决问题的模式)。

就您而言,不会。

为什么不起作用?

首先,您在decoder中进行了S型激活,从而将输出限制在[0, 1]范围内。您正在尝试预测超出此范围的数据,因此不可能。

在不运行的情况下,我可以告诉您此示例将导致什么损失(所有权重为+inf)。所有预测将始终为[1, 1, 1](或尽可能接近),因为此值对网络的影响最小,因此您只需要计算数据中每个vector[1, 1, 1]的距离。此处,损失停留在546.2719附近。在100000个历元之后,权重和偏差大约为10(对于S型而言这是非常大的)。您的值可能会有所不同,但趋势是明确的(尽管它会停止,因为当您用10挤压1时,它与sigmoid非常接近)。

torch.nn.Sigmoid移除decoder

如果我们从torch.nn.Sigmoid()中删除decoder怎么办?它将学会几乎完美地重建仅您的3个示例,而在“仅” 0.002个时期之后,损失500000

以下是decoder的学习权重:

tensor([[ 99.0000],
        [198.0000],
        [496.9999]], requires_grad=True)

这是bias

tensor([1.0000, 2.0000, 2.9999])

这是每个示例的encoder的输出:

tensor([[2.2822e-13],
        [2.2822e-13],
        [1.0000e+00]])

结果分析

您的网络学会了您告诉它的要学习的东西,即... 幅值(+聪明的bias黑客技术)。

[1、2、3]矢量

[1, 2, 3]为例(重复两次)。它的编码为2e-13,并且接近零,因此我们假设它为零。

现在,将0与所有权重相乘,您仍然会得到零。添加bias,即[1.0, 2.0, 2.99999],您就可以神奇地重建输入。

[100,200,500]向量

您可能会看到前进的方向。

编码值为1.0,当乘以decoder权重后,得出[99.0, 198.0, 497.0]。将bias添加到其中,瞧,我们得到[100.0, 200.0, 500.0]

[1,1,1]向量

在您的情况下,由于[1, 1, 1]的幅度确实很小,因此它显然不起作用,因此将其编码为zero,并重新构造为[1, 2, 3]

torch.nn.Sigmoid移除encoder

有点题外话,但是当您从编码器中删除Sigmoid时,将无法“轻松”地学习此模式。原因是网络的权重必须更加保守(因为权重将不会被压缩)。您将不得不降低学习率(最好是随着训练的进行而不断降低),因为它会在某个时候变得不稳定(尝试达到“最佳位置”时)。

学习相似性

在这种情况下,很难(至少对于网络而言)定义“相似”。 [1, 2, 3][3, 2, 1]类似吗?它没有不同维数的概念,需要将这三个数字压缩为一个值(以后用于重建)。

如所示,它可能会学习数据中的一些隐式模式以擅长重构“至少某些内容”,但找不到所需的通用模式。仍然取决于您的数据及其属性,但是我一般不赞成,我认为它的泛化能力很差。

正如您在上面的分析中所看到的那样,即使您没有看到它们(或者也许您已经找到并且正是那样的结果?)或者它们不存在,神经网络还是非常擅长查找那些模式。完全没有。

如果您需要维度相似性(这不仅是思想上的实验),那么您会发现很多“人为”的内容,例如p-normsome encodings(它们也可以衡量相似度,但是不同的方式),因此最好选择该IMO。

答案 1 :(得分:0)

您的测试向量/特征[1,1,1]与输入的维度相同。因此可以通过神经网络传递以获取表示/编码。因此,不需要对参数或网络配置进行任何更改。


它将忠实地工作吗?

这是一个非常有趣的问题,答案是:“取决于”。仅通过三个输入就很难保证学习通用的相似性函数。

您可能希望在与训练分布相似的数据上测试模型,即训练和测试数据应该非常相似。在上述情况下,虽然可以使用经过训练的模型,但很难说它可以正常工作。