Deep learning 自动编码器能在不重新训练的情况下编码新矢量吗?

Deep learning 自动编码器能在不重新训练的情况下编码新矢量吗?,deep-learning,pytorch,autoencoder,Deep Learning,Pytorch,Autoencoder,下面是一个简单的自动编码器,用于将3个尺寸为1x3的向量编码为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_ava

下面是一个简单的自动编码器,用于将3个尺寸为1x3的向量编码为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的数组,其中每个数组条目表示
功能
数组的降维:

[tensor([[0.9972],
         [0.9972]], grad_fn=<SigmoidBackward>),
 tensor([[1.]], grad_fn=<SigmoidBackward>)]
[张量([0.9972],
[0.9972]],梯度fn=),
张量([[1.]],梯度fn=)]

为了确定新特征的相似性,例如,是否需要重新训练网络,或者是否可以“自举”现有训练过的网络配置/权重,以便无需重新训练网络即可对新向量进行编码?

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


它会忠实地工作吗

这是一个非常有趣的问题,答案是:“视情况而定”。仅仅从三个输入学习一般的相似函数是很难保证的


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

很抱歉,您的代码乱七八糟。。。如果只是为了展示autoencoder的想法(这里你只需要X,Y,Z坐标,而你把它命名为
image
),那么它的选择非常糟糕

省事:如果是图像,您将无法将其编码为单个像素,这需要更复杂一点

源代码 下面是一个简单的自动编码器,用于编码3个尺寸为1x3的矢量: [1,2,3],[1,2,3],[100200500]至1x1

这仅在这种情况下是正确的,因为您有一批
3
元素(而您将
batch
out\u网络特性命名为
)。它们的尺寸不是1x3,而是3。以下是评论:

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)
行吗? 这个更有趣。原则上,如果你的神经网络是经过训练的,你就不必再训练它来包含以前没有看到的例子(因为神经网络的目标是学习一些模式来解决任务)

在你的情况下不会

为什么它不起作用? 首先,在
解码器中有sigmoid激活,它将输出限制在
[0,1]
范围内。您正在尝试预测超出此范围的数据,因此这是不可能的

在不运行的情况下,我可以告诉您这个示例的损失是什么(所有权重都是
+inf
)。所有预测将始终是
[1,1,1]
(或尽可能接近它),因为该值对网络的惩罚最小,因此您只需计算数据中每个
向量到
[1,1,1]
的距离。在这里,损失一直徘徊在
546.2719
附近。经过100000个时代后,权重和偏差大约为
10
(这对于乙状结肠来说是相当大的)。您的值可能会有所不同,但趋势很明显(尽管它会停止,因为当您用
sigmoid
挤压它时,
10
非常接近
1

解码器中删除
torch.nn.Sigmoid
如果我们从
解码器中删除
torch.nn.Sigmoid()
,会怎么样?它将学会几乎完美地重建仅你的3个示例,在“仅”
500000
个时代之后,损失为
0.002

以下是
解码器
的学习权重:

tensor([[ 99.0000],
        [198.0000],
        [496.9999]], requires_grad=True)
以下是
偏差

tensor([1.0000, 2.0000, 2.9999])
以下是每个示例的
编码器的输出:

tensor([[2.2822e-13],
        [2.2822e-13],
        [1.0000e+00]])
结果分析 你的网络学到了你告诉它要学的东西,这就是幅度(+聪明的
偏差
黑客)

[1,2,3]向量 以
[1,2,3]
为例(重复两次)。它的编码是
2e-13
并趋于零,因此我们假设它为零

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

[100200500]向量 你也许能看到它的去向

编码值是
1.0
,当乘以
解码器
权重时,我们得到
[99.0198.0497.0]
。加上
bias
,瞧,我们得到了
[100.02000.0500.0]

[1,1,1]向量 在您的情况下,它显然不起作用,因为
[1,1,1]
的大小非常小,因此它将被编码为
,并重建为
[1,2,3]

编码器中删除
torch.nn.Sigmoid
有点离题,但当您从编码器中删除sigmoid时,它将无法“轻松”了解此模式。原因是网络必须对权重更加保守(因为这些权重不会被挤压)。你必须降低学习率(最好随着训练的进行不断降低),因为它在某一点变得不稳定(当试图达到“完美点”时)

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

正如所演示的,它可能会学习数据中的一些隐式模式,以便能够很好地重建“至少有些东西”,但不会找到您正在寻找的一般模式。它仍然取决于你的数据和它的属性,但我认为一般来说是否定的,我认为它的泛化能力很差