访问自动编码器的低维编码数据
Access lower dimensional encoded data of autoencoder
这是我在教程中使用的自动编码器:https://debuggercafe.com/implementing-deep-autoencoder-in-pytorch/
我只是在学习自动编码器,我已经修改了源编码一个自定义的小数据集,其中包括:
[0,1,0,1,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0]
似乎工作正常,但我不确定如何访问维度 2 的低维嵌入值(由参数 out_features 设置)。
我已将自动编码器 class 添加到 return 嵌入的方法,这是访问嵌入的推荐方法吗?
代码:
import torch
import torchvision
from torch import nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import MNIST
from torchvision.utils import save_image
import warnings
import os
# import packages
import os
import torch
import torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import torch.optim as optim
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision.utils import save_image
import numpy as np
# utility functions
def get_device():
if torch.cuda.is_available():
device = 'cuda:0'
else:
device = 'cpu'
return device
device = get_device()
features = torch.tensor(np.array([ [0,1,0,1,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0] ])).float()
tic_tac_toe_data_loader = torch.utils.data.DataLoader(features, batch_size=1, shuffle=True)
class Encoder(nn.Module):
def __init__(self):
super(Encoder, self).__init__()
self.fc1 = nn.Linear(in_features=9, out_features=2)
def forward(self, x):
return F.sigmoid(self.fc1(x))
class Decoder(nn.Module):
def __init__(self):
super(Decoder, self).__init__()
self.fc1 = nn.Linear(in_features=2, out_features=9)
def forward(self, x):
return F.sigmoid(self.fc1(x))
class Autoencoder(nn.Module):
def __init__(self):
super(Autoencoder, self).__init__()
self.fc1 = Encoder()
self.fc2 = Decoder()
def forward(self, x):
return self.fc2(self.fc1(x))
net = Autoencoder()
net.to(device)
NUM_EPOCHS = 50
LEARNING_RATE = 1e-3
criterion = nn.MSELoss()
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE)
# image transformations
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
outputs = None
def train(net, trainloader, NUM_EPOCHS):
train_loss = []
for epoch in range(NUM_EPOCHS):
running_loss = 0.0
for data in trainloader:
img = data
img = img.to(device)
img = img.view(img.size(0), -1)
# print('img.shape' , img.shape)
optimizer.zero_grad()
outputs = net(img)
loss = criterion(outputs, img)
loss.backward()
optimizer.step()
running_loss += loss.item()
loss = running_loss / len(trainloader)
train_loss.append(loss)
return train_loss
# train the network
train_loss = train(net, tic_tac_toe_data_loader, NUM_EPOCHS)
我可以使用
访问低维嵌入
print(编码器().forward(torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float() ))
但是这是使用经过训练的权重值进行嵌入吗?如果我使用相同的值多次调用编码器:
print(Encoder().forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
print(Encoder().forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
return编辑了不同的结果:
tensor([0.5083, 0.5020], grad_fn=<SigmoidBackward>)
tensor([0.4929, 0.6940], grad_fn=<SigmoidBackward>)
为什么会这样?调用 Encoder 是否会调用额外的训练步骤?
通过调用 Encoder()
,您基本上每次都在创建一个新的编码器实例,并且每次都会随机初始化权重。
通常,您创建一个实例并对其进行训练,保存权重并对其进行推断。
另外,对于PyTorch,不需要调用.forward()
,直接调用实例即可。 Forward 被它隐式调用,包括其他钩子方法。
enc = Encoder()
input = torch.from_numpy(np.asarray([0,1,0,1,0,1,0,1,0]).float()
print(enc(input))
print(enc(input))
当您将 Encode()
实例传递给 train
函数时,会发生训练传递。调用 Encoder()
只会创建一个新对象。
由于每个对象都有自己的权重,并且权重是随机初始化的(请参阅 xavier 和 kaiming 初始化),所以输出不同。移动到单个对象,您仍然必须使用 train
函数对其进行显式训练。
就像其他响应者在您调用 Encoder()
时指出的那样,您会生成具有随机初始化权重的新实例。因为您对编码器生成的 低维嵌入 感兴趣,所以您需要在训练的 net
:
中访问编码器的权重
trained_encoder = net.fc1
现在您的编码器具有经过训练的权重,下面几行应该会产生相同的结果:
print(trained_encoder.forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
print(trained_encoder.forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
正如其他人所指出的,您可以通过直接传递输入来进一步简化:
test_input = torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()
print(trained_encoder(test_input))
这是我在教程中使用的自动编码器:https://debuggercafe.com/implementing-deep-autoencoder-in-pytorch/
我只是在学习自动编码器,我已经修改了源编码一个自定义的小数据集,其中包括:
[0,1,0,1,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0]
似乎工作正常,但我不确定如何访问维度 2 的低维嵌入值(由参数 out_features 设置)。
我已将自动编码器 class 添加到 return 嵌入的方法,这是访问嵌入的推荐方法吗?
代码:
import torch
import torchvision
from torch import nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import MNIST
from torchvision.utils import save_image
import warnings
import os
# import packages
import os
import torch
import torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import torch.optim as optim
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision.utils import save_image
import numpy as np
# utility functions
def get_device():
if torch.cuda.is_available():
device = 'cuda:0'
else:
device = 'cpu'
return device
device = get_device()
features = torch.tensor(np.array([ [0,1,0,1,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0],[0,1,1,0,0,1,0,1,0] ])).float()
tic_tac_toe_data_loader = torch.utils.data.DataLoader(features, batch_size=1, shuffle=True)
class Encoder(nn.Module):
def __init__(self):
super(Encoder, self).__init__()
self.fc1 = nn.Linear(in_features=9, out_features=2)
def forward(self, x):
return F.sigmoid(self.fc1(x))
class Decoder(nn.Module):
def __init__(self):
super(Decoder, self).__init__()
self.fc1 = nn.Linear(in_features=2, out_features=9)
def forward(self, x):
return F.sigmoid(self.fc1(x))
class Autoencoder(nn.Module):
def __init__(self):
super(Autoencoder, self).__init__()
self.fc1 = Encoder()
self.fc2 = Decoder()
def forward(self, x):
return self.fc2(self.fc1(x))
net = Autoencoder()
net.to(device)
NUM_EPOCHS = 50
LEARNING_RATE = 1e-3
criterion = nn.MSELoss()
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE)
# image transformations
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
outputs = None
def train(net, trainloader, NUM_EPOCHS):
train_loss = []
for epoch in range(NUM_EPOCHS):
running_loss = 0.0
for data in trainloader:
img = data
img = img.to(device)
img = img.view(img.size(0), -1)
# print('img.shape' , img.shape)
optimizer.zero_grad()
outputs = net(img)
loss = criterion(outputs, img)
loss.backward()
optimizer.step()
running_loss += loss.item()
loss = running_loss / len(trainloader)
train_loss.append(loss)
return train_loss
# train the network
train_loss = train(net, tic_tac_toe_data_loader, NUM_EPOCHS)
我可以使用
访问低维嵌入print(编码器().forward(torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float() ))
但是这是使用经过训练的权重值进行嵌入吗?如果我使用相同的值多次调用编码器:
print(Encoder().forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
print(Encoder().forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
return编辑了不同的结果:
tensor([0.5083, 0.5020], grad_fn=<SigmoidBackward>)
tensor([0.4929, 0.6940], grad_fn=<SigmoidBackward>)
为什么会这样?调用 Encoder 是否会调用额外的训练步骤?
通过调用 Encoder()
,您基本上每次都在创建一个新的编码器实例,并且每次都会随机初始化权重。
通常,您创建一个实例并对其进行训练,保存权重并对其进行推断。
另外,对于PyTorch,不需要调用.forward()
,直接调用实例即可。 Forward 被它隐式调用,包括其他钩子方法。
enc = Encoder()
input = torch.from_numpy(np.asarray([0,1,0,1,0,1,0,1,0]).float()
print(enc(input))
print(enc(input))
当您将 Encode()
实例传递给 train
函数时,会发生训练传递。调用 Encoder()
只会创建一个新对象。
由于每个对象都有自己的权重,并且权重是随机初始化的(请参阅 xavier 和 kaiming 初始化),所以输出不同。移动到单个对象,您仍然必须使用 train
函数对其进行显式训练。
就像其他响应者在您调用 Encoder()
时指出的那样,您会生成具有随机初始化权重的新实例。因为您对编码器生成的 低维嵌入 感兴趣,所以您需要在训练的 net
:
trained_encoder = net.fc1
现在您的编码器具有经过训练的权重,下面几行应该会产生相同的结果:
print(trained_encoder.forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
print(trained_encoder.forward( torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()))
正如其他人所指出的,您可以通过直接传递输入来进一步简化:
test_input = torch.tensor(np.array([0,1,0,1,0,1,0,1,0])).float()
print(trained_encoder(test_input))