Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PyTorch中的掩蔽和实例规范化_Pytorch_Normalization - Fatal编程技术网

PyTorch中的掩蔽和实例规范化

PyTorch中的掩蔽和实例规范化,pytorch,normalization,Pytorch,Normalization,假设我有一个PyTorch张量,排列为[N,C,L]形,其中N是批量大小,C是通道或特征的数量,L是长度。在这种情况下,如果希望执行实例规范化,可以执行以下操作: N = 20 C = 100 L = 40 m = nn.InstanceNorm1d(C, affine=True) input = torch.randn(N, C, L) output = m(input) 这将对每个N*C=2000个数据切片在L维中执行标准化,减去2000个平均值,按2000个标准偏差进行缩放,并按100

假设我有一个PyTorch张量,排列为[N,C,L]形,其中N是批量大小,C是通道或特征的数量,L是长度。在这种情况下,如果希望执行实例规范化,可以执行以下操作:

N = 20
C = 100
L = 40
m = nn.InstanceNorm1d(C, affine=True)
input = torch.randn(N, C, L)
output = m(input) 
这将对每个N*C=2000个数据切片在L维中执行标准化,减去2000个平均值,按2000个标准偏差进行缩放,并按100个可学习的权重和偏差参数(每个通道一个)重新缩放。这里的潜台词是,所有这些价值观都存在并有意义

但是我有一种情况,对于切片N=1,我想排除(比如)L=35之后的所有数据。对于切片N=2(假设),所有数据都有效。对于切片N=3,排除L=30之后的所有数据,以此类推。这模拟了一维时间序列的数据,具有多个特征,但长度不同

如何对此类数据执行实例规范,获得正确的统计数据,并在PyTorch中维护可微性/自动标记信息?

更新:在保持GPU性能的同时,或者至少不让它死机。

我不能

  • …用零值屏蔽,因为这会破坏计算机的平均值和方差,从而产生错误的结果
  • …使用np.nan或np.inf屏蔽,因为PyTorch张量不会忽略这些值,而是将它们视为错误。它们是粘性的,会导致垃圾结果。Pytork目前缺乏与np.nanmean和np.nanvar的等价物
  • …对数据进行适当的排列或转换;没有这样的方法能满足我的需要
  • …使用包填充序列;实例规范化不会对该数据结构进行操作,据我所知,无法将数据导入该结构。此外,仍然需要重新安排数据,见上文3 我是否错过了一个可以满足我需求的方法?或者,我是否缺少一种数据重新安排的方法,可以让3或4个以上的数据正常工作


    这是递归神经网络一直面临的问题,因此具有pack_-padded_序列功能,但在这里不太适用

    我认为使用现有的
    InstanceNorm1d
    无法直接实现,最简单的方法可能是自己从头开始实现。我做了一个快速的实现,应该可以工作。为了使它更通用一点,这个模块需要一个布尔掩码(与输入大小相同的布尔张量),指定在通过实例范数时应该考虑哪些元素

    import torch
    
    
    class MaskedInstanceNorm1d(torch.nn.Module):
        def __init__(self, num_features, eps=1e-6, momentum=0.1, affine=True, track_running_stats=False):
            super().__init__()
            self.num_features = num_features
            self.eps = eps
            self.momentum = momentum
            self.affine = affine
            self.track_running_stats = track_running_stats
            self.gamma = None
            self.beta = None
            if self.affine:
                self.gamma = torch.nn.Parameter(torch.ones((1, self.num_features, 1), requires_grad=True))
                self.beta = torch.nn.Parameter(torch.zeros((1, self.num_features, 1), requires_grad=True))
    
            self.running_mean = None
            self.running_variance = None
            if self.affine:
                self.running_mean = torch.zeros((1, self.num_features, 1), requires_grad=True)
                self.running_variance = torch.zeros((1, self.num_features, 1), requires_grad=True)
    
        def forward(self, x, mask):
            mean = torch.zeros((1, self.num_features, 1), requires_grad=False)
            variance = torch.ones((1, self.num_features, 1), requires_grad=False)
    
            # compute masked mean and variance of batch
            for c in range(self.num_features):
                if mask[:, c, :].any():
                    mean[0, c, 0] = x[:, c, :][mask[:, c, :]].mean()
                    variance[0, c, 0] = (x[:, c, :][mask[:, c, :]] - mean[0, c, 0]).pow(2).mean()
    
            # update running mean and variance
            if self.training and self.track_running_stats:
                for c in range(self.num_features):
                    if mask[:, c, :].any():
                        self.running_mean[0, c, 0] = (1-self.momentum) * self.running_mean[0, c, 0] \
                                                     + self.momentum * mean[0, c, 0]
                        self.running_variance[0, c, 0] = (1-self.momentum) * self.running_variance[0, c, 0] \
                                                         + self.momentum * variance[0, c, 0]
    
            # compute output
            x = (x - mean)/(self.eps + variance).sqrt()
    
            if self.affine:
                x = x * self.gamma + self.beta
    
            return x
    

    我是否正确理解您,如果您指定排除最后35个条目,您不希望更新
    InstanceNorm
    s最后35个权重(和偏差)?您如何在其他模块中处理这些最后35个值?(比如
    Conv1d
    或者
    Linear
    等等?@failfr不是我不想让它们更新(虽然从技术上说它们不应该更新)。而是标准化依赖于均值和方差的计算,我想让计算忽略屏蔽值。例如,[1,2,3,4,5,__________;应在平均值为3和总体方差为2的基础上进行标准化,而不管用____;表示的屏蔽值是什么。@r经过计算后,它们将从损失函数中屏蔽。如果有必要,重新设置为零也是一种选择。Sot huis意味着对于通过修改的
    InstanceForm
    的每一批,您也会传递一个索引列表/张量(大小
    NxC
    ),这些索引定义了哪些值是相关的,哪些值应该被屏蔽,对吗?我得出了相同的结论,如果不实施或重新实施某些东西,就无法实现。我怀疑将nanmean和nanvar添加到torch中,并有条不紊地将它们扩展到规范化例程中,是最干净的方法,但这超出了我的时间投资范围。此外,这方面的语义(特别是循环指数)并不完全正确,但它们很容易修补以提供正确的行为。我将对此进行思考和基准测试,同时希望其他人看到我错过的东西。@Novak王到底是什么?我对它进行了测试,它的工作原理与我们讨论的一样,在更新中只考虑屏蔽条目,而未屏蔽条目基本上通过一个标识;简单的解释需要在某些位置嵌套循环。制作一个形状为[3,2,4]的随机张量,并使用InstanceNorm1d()的默认实现对其进行测试。如果掩码张量设置为all True,您应该会看到相同的结果,但您不会看到。而且-,这也是我真正担心的-,GPU设备上的性能会因为这些循环而下降。