【问题标题】:Why is the decoder in an autoencoder uses a sigmoid on the last layer?为什么自动编码器中的解码器在最后一层使用 sigmoid?
【发布时间】:2021-03-26 04:52:36
【问题描述】:

我正在查看this 工作变分自动编码器。

主类

class VAE(nn.Module):
    def __init__(self):
        super(VAE, self).__init__()

        self.fc1 = nn.Linear(784, 400)
        self.fc21 = nn.Linear(400, 20)
        self.fc22 = nn.Linear(400, 20)
        self.fc3 = nn.Linear(20, 400)
        self.fc4 = nn.Linear(400, 784)

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        return self.fc21(h1), self.fc22(h1)

    def reparametrize(self, mu, logvar):
        std = logvar.mul(0.5).exp_()
        if torch.cuda.is_available():
            eps = torch.cuda.FloatTensor(std.size()).normal_()
        else:
            eps = torch.FloatTensor(std.size()).normal_()
        eps = Variable(eps)
        return eps.mul(std).add_(mu)

    def decode(self, z):
        h3 = F.relu(self.fc3(z))
        return F.sigmoid(self.fc4(h3))

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparametrize(mu, logvar)
        return self.decode(z), mu, logvar

    def decode(self, z):
        h3 = F.relu(self.fc3(z))
        return F.sigmoid(self.fc4(h3))

我无法向自己解释为什么最后一层应该在返回之前通过一个 sigmoid。

请解释一下。


编辑: 我只是检查了没有乙状结肠。结果还是不错的。 现在我不确定是否需要。

【问题讨论】:

    标签: machine-learning neural-network pytorch autoencoder sigmoid


    【解决方案1】:

    如果我没记错的话,它会将结果转换为概率,表示为 0 到 1 之间的实数。

    【讨论】:

    • 您确实没记错,但这在这里没有意义。输出应该与输入相同,因为这是一个自动编码器。输入不是概率。
    • 这不太正确,这些值并不代表概率,它只是将它们压缩在 0 和 1 之间。softmax 函数返回的概率在这里没有意义。 Simoid 是有道理的,因为输入(mnist 的所有像素)都在 0 和 1 范围内,所以输出必须在 0 和 1 之间,如@Sandro H 的回答中所述
    【解决方案2】:

    正如 Jim J 的回答中提到的,sigmoid 强制输出在 [0, 1] 范围内。在这种情况下,并不是因为我们要将输出解释为概率,而是强制将输出解释为灰度图像的像素强度。

    如果您移除 sigmoid,NN 将必须知道所有输出都应在 [0, 1] 范围内。 sigmoid 可能有助于使学习过程更加稳定。

    【讨论】:

    • 我们可以用softmax函数代替sigmoid吗?会有什么影响?
    • @MSS Softmax 接受许多输入并只有一个输出。 Sigmoid 有一个输入和一个输出。所以不,它们不可互换。具有单个输入的 softmax 的私有情况是 sigmoid,但我不会说它们可以被替换。
    • 好的,但我还是无法向自己解释。
    【解决方案3】:

    这是因为图片来自

    train_loader = torch.utils.data.DataLoader(
        datasets.MNIST('../data', train=True, download=True,
                       transform=transforms.ToTensor()),
        batch_size=args.batch_size, shuffle=True, **kwargs)
    test_loader = torch.utils.data.DataLoader(
        datasets.MNIST('../data', train=False, transform=transforms.ToTensor()),
        batch_size=args.batch_size, shuffle=True, **kwargs)
    

    有像素值范围[0,1],可以在这里加上print('data[0]: ', data[0])

    def test(epoch):
        model.eval()
        test_loss = 0
        with torch.no_grad():
            for i, (data, _) in enumerate(test_loader):
                data = data.to(device)
                print('data[0]: ', data[0])
                ...
    

    查看打印输出,您会发现这些值的范围是 0 到 1。 顺便说一句,torchvision.utils.save_image() 的第一个参数也是像素值范围为 0 到 1 的张量,因为在该函数内部,它会在保存到图像之前乘以 255。

    【讨论】:

      猜你喜欢
      • 2018-03-08
      • 2020-02-10
      • 2021-02-15
      • 1970-01-01
      • 2019-01-11
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 2021-07-29
      相关资源
      最近更新 更多