来自同一源的两个张量具有不同的平均值,这很奇怪

问题描述 投票:0回答:1

分别沿不同的两个轴连接二维张量列表,得到张量 A,B,其中 A.T==B,但它们沿同一轴的平均值略有不同

(A.T.mean(axis=0) != B.mean(axis=0))
,为什么?理论上它们是相同的。

从形状为 (10,2,1) 的 3d 列表开始

In [4]: tmp
Out[4]: 
[[[0.3471660912036896], [0.652833878993988]],
 [[0.5512792468070984], [0.4487205743789673]],
 [[0.5454527139663696], [0.4545471668243408]],
 [[0.3661797344684601], [0.6338202953338623]],
 [[0.2655346989631653], [0.7344651222229004]],
 [[0.28296780586242676], [0.717032253742218]],
 [[0.28441378474235535], [0.7155864238739014]],
 [[0.3660774230957031], [0.6339224576950073]],
 [[0.3515346944332123], [0.6484655141830444]],
 [[0.3660774230957031], [0.6339224576950073]]]
  • 第 1 步,将
    tmp
    转换为张量列表
In [7]: tensor_list = [torch.tensor(x) for x in tmp]
   ...: tensor_list
Out[7]: 
[tensor([[0.3472],
         [0.6528]]),
 tensor([[0.5513],
         [0.4487]]),
 tensor([[0.5455],
         [0.4545]]),
 tensor([[0.3662],
         [0.6338]]),
 tensor([[0.2655],
         [0.7345]]),
 tensor([[0.2830],
         [0.7170]]),
 tensor([[0.2844],
         [0.7156]]),
 tensor([[0.3661],
         [0.6339]]),
 tensor([[0.3515],
         [0.6485]]),
 tensor([[0.3661],
         [0.6339]])]
  • 步骤2
    • torch.cat() 沿axis 0 遍历tensor_list 中的每个tensor.T 以获得A。
    • torch.cat() 沿轴 1 遍历tensor_list中的每个tensor,然后然后转置以获得B。

其中 A.shape == B.shape

In [11]: A = torch.cat([x.T for x in tensor_list], dim=0)
    ...: A.shape
Out[11]: torch.Size([10, 2])

In [12]: B = torch.cat(tensor_list, dim=1).T
    ...: B.shape
Out[12]: torch.Size([10, 2])

步骤3.检查A和B之间的一致性。我们可以在下面看到它们的逐元素差异之和为零,并且逐元素比较显示每个元素与另一个张量中的元素相同。

In [13]: (A - B).abs().sum()
Out[13]: tensor(0.)

In [14]: A == B
Out[14]: 
tensor([[True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True],
        [True, True]])

步骤 4. 检查它们沿轴 (0) 的平均值。奇怪的是,略有不同。

In [15]: A.mean(dim=0) - B.mean(dim=0)
Out[15]: tensor([5.9605e-08, 0.0000e+00])

虽然它们的平均值之间的差异很小,可以忽略不计,但我想知道为什么会发生这种情况。 torch.cat() 是如何工作的?

[环境信息]

  • 操作系统:Ubuntu 20.04.5 LTS
  • Python:Python 3.8.10
  • 火炬:2.0.1
  • cuda:11.7
  • NVIDIA-SMI 515.86.01
pytorch tensor
1个回答
0
投票

张量具有相同的形状和值,但它们的构造导致它们具有不同的内存布局。您可以使用 stride 函数看到这一点:

tmp = torch.randn(10,2,1)
tensor_list = [x for x in tmp]
A = torch.cat([x.T for x in tensor_list], dim=0)
B = torch.cat(tensor_list, dim=1).T
print(A.stride())
> (2, 1)
print(B.stride())
> (1, 10)

步幅告诉我们需要沿着轴移动多少字节才能从一个值到达另一个值。

由于内存布局不同,因此

mean
操作以不同的顺序处理每个张量的值。不同的平均结果来自于不同的运算顺序以及数值精度问题。

作为比较,如果您从列表中重新创建

A
B
(创建一个全新的张量),您将得到两个具有相同步幅且没有均值差的张量。

C = torch.tensor(A.tolist())
D = torch.tensor(B.tolist())
print(C.stride())
> (2, 1)
print(D.stride())
> (2, 1)

C.mean(dim=0) - D.mean(dim=0)
> tensor([0., 0.])
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.