Deep learning 自动编码器能在不重新训练的情况下编码新矢量吗?
下面是一个简单的自动编码器,用于将3个尺寸为1x3的向量编码为1x1: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
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]
类似吗?它没有不同维度的概念,需要将这三个数字压缩成一个值(稍后用于重建)
正如所演示的,它可能会学习数据中的一些隐式模式,以便能够很好地重建“至少有些东西”,但不会找到您正在寻找的一般模式。它仍然取决于你的数据和它的属性,但我认为一般来说是否定的,我认为它的泛化能力很差