python - pytorch对图片进行编码和解码

标签 python machine-learning neural-network pytorch

任务:使用“fetch_lfw_people”数据集的示例来编写和训练自动编码器。 按纪元编写迭代代码。编写代码来可视化学习过程并计算每个时期后验证的指标。 训练自动编码器。实现低验证损失。

我的代码:

from sklearn.datasets import fetch_lfw_people
import numpy as np
import torch
from torch.utils.data import TensorDataset, DataLoader
from sklearn.model_selection import train_test_split

数据准备:

lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)    
X = lfw_people['images']

X_train, X_test = train_test_split(X, test_size=0.1)

X_train = torch.tensor(X_train, dtype=torch.float32, requires_grad=True)
X_test = torch.tensor(X_test, dtype=torch.float32, requires_grad=False)
dataset_train = TensorDataset(X_train, torch.zeros(len(X_train)))
dataset_test = TensorDataset(X_test, torch.zeros(len(X_test)))

batch_size = 32

train_loader = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset_test, batch_size=batch_size, shuffle=False)

创建一个具有编码和解码功能的网络:

class Autoencoder(torch.nn.Module): 
    def __init__(self): 
        super(Autoencoder, self).__init__()
        self.encoder = torch.nn.Sequential(
            torch.nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=2), 
            torch.nn.ReLU(),

            torch.nn.Conv2d(in_channels=32, out_channels=64, stride=2, kernel_size=3),
            torch.nn.ReLU(),

            torch.nn.Conv2d(in_channels=64, out_channels=64, stride=2, kernel_size=3),
            torch.nn.ReLU(),

            torch.nn.Conv2d(in_channels=64, out_channels=64, stride=2, kernel_size=3)
        )

        self.decoder = torch.nn.Sequential( 
            torch.nn.ConvTranspose2d(in_channels=64, out_channels=64, kernel_size=3, stride=2),

            torch.nn.ConvTranspose2d(in_channels=64, out_channels=64, kernel_size=(3,4), stride=2),

            torch.nn.ConvTranspose2d(in_channels=64, out_channels=32, kernel_size=4, stride=2),          

            torch.nn.ConvTranspose2d(in_channels=32, out_channels=1, kernel_size=(4,3), stride=2)
        )

    def encode(self, X):
        encoded_X = self.encoder(X) 
        batch_size = X.shape[0] 
        return encoded_X.reshape(batch_size, -1)

    def decode(self, X): 
        pre_decoder = X.reshape(-1, 64, 2, 1)  
        return self.decoder(pre_decoder)

我在学习之前通过一个例子检查模型的工作情况:

model = Autoencoder()

sample = X_test[:1]
sample = sample[:, None] 
result = model.decode(model.encode(sample))  # before train

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2)
ax1.imshow(sample[0][0].detach().numpy(), cmap=plt.cm.Greys_r)
ax2.imshow(result[0][0].detach().numpy(), cmap=plt.cm.Greys_r)
plt.show()

结果并不令人满意。我开始训练:

model = Autoencoder()
loss = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

history_train = []
history_test = []

for i in range(5):
    for x, y in train_loader:
        x = x[:, None]

        model.train()

        decoded_x = model.decode(model.encode(x))
        mse_loss = loss(torch.tensor(decoded_x, dtype=torch.float), x)

        optimizer.zero_grad()
        mse_loss.backward()
        optimizer.step()

        history_train.append(mse_loss.detach().numpy())

    model.eval()
    with torch.no_grad():
        for x, y in train_loader:
            x = x[:, None]

            result_x = model.decode(model.encode(x))
            loss_test = loss(torch.tensor(result_x, dtype=torch.float), x)

            history_test.append(loss_test.detach().numpy())

plt.subplot(1, 2, 1)
plt.plot(history_train)
plt.title("Optimization process for train data")

plt.subplot(1, 2, 2)
plt.plot(history_test)
plt.title("Loss for test data")

plt.show

训练数据和测试的巨大损失。

训练后没有任何变化:

with torch.no_grad():
    model.eval()
    res1 = model.decode(model.encode(sample))

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2)
ax1.imshow(sample[0][0].detach().numpy(), cmap=plt.cm.Greys_r)
ax2.imshow(res1[0][0].detach().numpy(), cmap=plt.cm.Greys_r)
plt.show()

为何亏损如此之大?将输入减少到区间 [-1, 1] 没有帮助。我是这样做的:(值/255)* 2 - 1 为什么训练后不改变模型的参数? 为什么不改变解码后的样本?

结果:火车前、火车后、损失 /image/OhdrJ.jpg

最佳答案

1) 替换行

mse_loss = loss(torch.tensor(decoded_x, dtype=torch.float), x)

带线

mse_loss = loss(decoded_x, x)

2)替换行

model.eval()
    with torch.no_grad():
        for x, y in train_loader:

有线条

替换行

model.eval()
    with torch.no_grad():
        for x, y in test_loader:

关于python - pytorch对图片进行编码和解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55033669/

相关文章:

python - 结束 mysql-connector-python 中的连接池

python - 忽略条件的后续实例(for 循环和 if 语句)

java - 如何配置Stanford QNMinimizer以获得与scipy.optimize.minimize L-BFGS-B类似的结果

machine-learning - 深度学习基准测试在 16 位和 8 位定点精度下的表现如何?

neural-network - sigmoid 函数在神经网络中的位置重要吗?

machine-learning - 关于神经网络权重向量的一般查询

python - 安装 matplotlib 后,在 Spyder 中导入 pytorch 会导致内核崩溃

python - 如何获取python中符号链接(symbolic link)的大小

tensorflow - 如何在 tensorflow 中创建掩模张量?

neural-network - 为什么我们需要显式调用 zero_grad()?