这是一个简单的自动编码器,可将尺寸为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]
是否需要重新训练网络,或者可以“引导”现有已训练的网络配置/权重,以便可以对新矢量进行编码不需要重新培训网络?
答案 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]
为例(重复两次)。它的编码为2e-13
,并且接近零,因此我们假设它为零。
现在,将0
与所有权重相乘,您仍然会得到零。添加bias
,即[1.0, 2.0, 2.99999]
,您就可以神奇地重建输入。
您可能会看到前进的方向。
编码值为1.0
,当乘以decoder
权重后,得出[99.0, 198.0, 497.0]
。将bias
添加到其中,瞧,我们得到[100.0, 200.0, 500.0]
。
在您的情况下,由于[1, 1, 1]
的幅度确实很小,因此它显然不起作用,因此将其编码为zero
,并重新构造为[1, 2, 3]
。
torch.nn.Sigmoid
移除encoder
有点题外话,但是当您从编码器中删除Sigmoid时,将无法“轻松”地学习此模式。原因是网络的权重必须更加保守(因为权重将不会被压缩)。您将不得不降低学习率(最好是随着训练的进行而不断降低),因为它会在某个时候变得不稳定(尝试达到“最佳位置”时)。
在这种情况下,很难(至少对于网络而言)定义“相似”。 [1, 2, 3]
与[3, 2, 1]
类似吗?它没有不同维数的概念,需要将这三个数字压缩为一个值(以后用于重建)。
如所示,它可能会学习数据中的一些隐式模式以擅长重构“至少某些内容”,但找不到所需的通用模式。仍然取决于您的数据及其属性,但是我一般不赞成,我认为它的泛化能力很差。
正如您在上面的分析中所看到的那样,即使您没有看到它们(或者也许您已经找到并且正是那样的结果?)或者它们不存在,神经网络还是非常擅长查找那些模式。完全没有。
如果您需要维度相似性(这不仅是思想上的实验),那么您会发现很多“人为”的内容,例如p-norm
,some encodings(它们也可以衡量相似度,但是不同的方式),因此最好选择该IMO。
答案 1 :(得分:0)
您的测试向量/特征[1,1,1]
与输入的维度相同。因此可以通过神经网络传递以获取表示/编码。因此,不需要对参数或网络配置进行任何更改。
它将忠实地工作吗?
这是一个非常有趣的问题,答案是:“取决于”。仅通过三个输入就很难保证学习通用的相似性函数。
您可能希望在与训练分布相似的数据上测试模型,即训练和测试数据应该非常相似。在上述情况下,虽然可以使用经过训练的模型,但很难说它可以正常工作。