Deep learning 线性层的PyTorch和Chainer实现——它们等效吗?

Deep learning 线性层的PyTorch和Chainer实现——它们等效吗?,deep-learning,pytorch,linear-algebra,chainer,Deep Learning,Pytorch,Linear Algebra,Chainer,我想使用线性、完全连接的层作为网络中的输入层之一。输入具有形状(批次大小、通道数、样本数)。它基于Tacotron论文:Enocder prenet部分。 我觉得Chainer和PyTorch对线性层有不同的实现——他们是真的执行相同的操作还是我误解了什么 在Pytork中,线性层的行为遵循以下文件: 据此,输入和输出数据的形状如下: 输入:(N,∗,in_特征),其中*表示任意数量的附加尺寸 产出:(N,∗,out_特征),其中除最后一个尺寸外,所有尺寸都与输入的形状相同 现在,让我们尝试在p

我想使用线性、完全连接的层作为网络中的输入层之一。输入具有形状(批次大小、通道数、样本数)。它基于Tacotron论文:Enocder prenet部分。 我觉得Chainer和PyTorch对线性层有不同的实现——他们是真的执行相同的操作还是我误解了什么

在Pytork中,线性层的行为遵循以下文件: 据此,输入和输出数据的形状如下:

输入:(N,∗,in_特征),其中*表示任意数量的附加尺寸

产出:(N,∗,out_特征),其中除最后一个尺寸外,所有尺寸都与输入的形状相同

现在,让我们尝试在pytorch中创建一个线性层并执行该操作。我想要一个8通道的输出,输入数据将有3个通道

import numpy as np
import torch
from torch import nn
linear_layer_pytorch = nn.Linear(3, 8)
让我们创建一些形状(1、4、3)的虚拟输入数据(批处理大小、num样本、in通道:

data = np.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=np.float32).reshape(1, 4, 3)
data_pytorch = torch.from_numpy(data)
最后,执行以下操作:

results_pytorch = linear_layer_pytorch(data_pytorch)
results_pytorch.shape
输出的形状如下:
Out[27]:torch.Size([1,4,8])
看看PyTorch实现的来源:

def linear(input, weight, bias=None):
    # type: (Tensor, Tensor, Optional[Tensor]) -> Tensor
    r"""
    Applies a linear transformation to the incoming data: :math:`y = xA^T + b`.

    Shape:

        - Input: :math:`(N, *, in\_features)` where `*` means any number of
          additional dimensions
        - Weight: :math:`(out\_features, in\_features)`
        - Bias: :math:`(out\_features)`
        - Output: :math:`(N, *, out\_features)`
    """
    if input.dim() == 2 and bias is not None:
        # fused op is marginally faster
        ret = torch.addmm(bias, input, weight.t())
    else:
        output = input.matmul(weight.t())
        if bias is not None:
            output += bias
        ret = output
    return ret

它转换传递给它的权重矩阵,沿批量大小轴广播,并执行矩阵乘法。考虑到线性层的工作原理,我将其想象为8个节点,通过突触连接,持有权重,每个通道在输入样本中,因此在我的情况下,它有3*8个权重。这正是s也许我在调试器(8,3)中看到了

现在,让我们跳到Chainer。Chainer的线性层文档在这里可用:。根据此文档,线性层包装函数linear,根据文档,它沿非批量维度展平输入,其权重矩阵的形状为
(输出大小,展平输入大小)


将层创建为
linear\u layer\u chainer=chainer.links.linear(3,8)
并调用它会导致大小不匹配。因此对于chainer,我得到了完全不同的结果,因为这次我有一个形状为(8,12)的权重矩阵,结果的形状为(1,8)现在,我的问题是:由于结果明显不同,权重矩阵和输出都有不同的形状,我如何使它们等效,以及期望的输出是什么?在Tacotron的PyTorch实现中,PyTorch方法似乎按原样使用()-Prenet。如果是这样的话,我如何才能让链接器产生相同的结果(我必须在链接器中实现)。我将感谢任何提示,抱歉帖子这么长。

链接器
线性
层(有点令人沮丧)不将变换应用于最后一个轴。Chainer将展平其余轴。相反,您需要提供批次轴的数量,在您的情况下为2:

# data.shape == (1, 4, 3)
results_chainer = linear_layer_chainer(data, n_batch_axes=2)
# 2 batch axes (1,4) means you apply linear to (..., 3)
# results_chainer.shape == (1, 4, 8)

您还可以使用
l(数据,n\u batch\u axes=len(data.shape)-1)
始终应用于最后一个维度,这是PyTorch、Keras等的默认行为。

Chainer
Linear
层(有点令人沮丧)不将变换应用于最后一个轴。Chainer将展平其余轴。相反,您需要提供批次轴的数量,在您的情况下为2:

# data.shape == (1, 4, 3)
results_chainer = linear_layer_chainer(data, n_batch_axes=2)
# 2 batch axes (1,4) means you apply linear to (..., 3)
# results_chainer.shape == (1, 4, 8)

您还可以使用
l(数据,n\u批处理\u轴=len(data.shape)-1)
始终应用于最后一个维度,这是PyTorch、Keras等中的默认行为。

谢谢!它实际上似乎可行,但为了使其有效,您必须使用in_size和out_size参数显式创建层。如果您按照文档中的建议,将初始化保留到数据馈送为止,它仍然有效ll创建的权重矩阵为(12x8)在我的示例中,由于尺寸不匹配,它会断开。谢谢!它实际上似乎可以工作,但为了使它工作,您必须显式地使用in_size和out_size参数创建层。如果您按照文档中的建议,在输入数据之前保留初始化,它仍然会创建(12x8),然后由于尺寸不匹配而中断。