数据操作

对于广播机制中两个张量按元素相加,要满足以下两个条件:
1、两个张量维度相同
2、每个张量的size里面要有一个维度为1
然后各自按照那个维度复制再按元素相加。

  1. 运行X >Y和X<Y后会返回一个全为bool的张量
    返回结果分别为:
    tensor([[False, False, False, False],
    [ True, True, True, True],
    [ True, True, True, True]])

    tensor([[ True, False, True, False],
    [False, False, False, False],
    [False, False, False, False]])
    2.使用3维张量运行
    // 使用三维向量
    a = torch.arange(3).reshape(3,1,1)
    b = torch.arange(6).reshape(1,3,2)
    a+b
    如下为广播机制的分析:

import torch
import numpy as np

x = torch.rand(3,3)
xr1 = x.reshape(1,9)
xr9 = x.reshape(9,1)
print(id(x) == id(xr1))
print(id(x) == id(xr9))
print(id(x.storage()) == id(xr1.storage()))
print(id(x.storage()) == id(xr9.storage()))

results :
False
False
True
True
2.1.5 节省内存小节似乎可以提一下张量(tensor)的存储结构,这样可以更底层知道其是否共享存储。

除了1那个维度之外的维度必须相等。。。。。。。。。。。。

哦,我明白了,共享内存的意思不是说地址一样,而是说一个改变会引起另一个改变?

 满足广播的条件:需要两个张量的每个维度满足以下条件:

  a.这两个维度的大小相等
  b. 某个维度 一个张量有,一个张量没有
  c.某个维度 一个张量有,一个张量也有但大小是1

个人见解:我看了一下两个reshape()的API说明,reshape提供两种参数接收方式,也就是说有重载。一种是直接接收数据 reshape(self, *shape: _int),也就是以reshape(3,4)的形式,一种是sequence的形式reshape(self, shape: Sequence[Union[_int, SymInt]]),这种就是((3,4))

这里torch.arange(3)生成的不也是tensor对象吗,两者有什么区别吗,还是不明白x.reshape(3,4)和x.reshape((3,4))有什么区别 :eyes:

三峡刘战来也[quote=“goldpiggy, post:1, topic:1747, full:true”]
https://zh.d2l.ai/chapter_preliminaries/ndarray.html
[/quote]

:stuck_out_tongue:

可以参考 :grinning:
广播机制规则:

  • 如果遵守以下规则,则两个tensor是“可广播的”:
    • 每个tensor至少有一个维度;
    • 遍历tensor所有维度时,从末尾随开始遍历,两个tensor存在下列情况:
      • tensor维度相等。
      • tensor维度不等且其中一个维度为1。
      • tensor维度不等且其中一个维度不存在。
  • 如果两个tensor是“可广播的”,则计算过程遵循下列规则:
    • 如果两个tensor的维度不同,则在维度较小的tensor的前面增加维度,使它们维度相等。
    • 对于每个维度,计算结果的维度值取两个tensor中较大的那个值。
    • 两个tensor扩展维度的过程是将数值进行复制。
3 Likes

我之前找到的形式上的规律是: 两个张量总是在两轴间成对出现x,1和1,x形式,然后对1的轴做广播;其他轴若不能配对则应该保持大小相同。 :smiling_face_with_three_hearts: 还是你这个规则全面。

  1. 运行本节中的代码。将本节中的条件语句X == Y更改为X < YX > Y,然后看看你可以得到什么样的张量。

    X = torch.arange(12, dtype=torch.float32).reshape((3,4))
    Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
    X > Y

​ 输出:

tensor([[False, False, False, False],
        [ True,  True,  True,  True],
        [ True,  True,  True,  True]])
        
  1. 用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同?
a = torch.arange(20).reshape((5,1,4))
b = torch.arange(48).reshape((6,2,4))
(a+b).shape
RuntimeError: The size of tensor a (5) must match the size of tensor b (6) at non-singleton dimension 0
a = torch.arange(30).reshape((2,3,1,5))
b = torch.arange(60).reshape((3,4,5))
(a+b).shape
torch.Size([2, 3, 4, 5])

广播机制条件:

1)每个张靓至少为1维

2)从后往前比张量形状,维度大小要么相等,要么其中一个等于1,要么其中一个不存在

例: 2 3 1 5 3 4 5 5比5,1比4,3比3 可以广播

我对广播机制的理解是
1.每个张量至少具有一个维度;
2.广播时,从尾部,也可以说是右边开始比对维度,需要满足尺寸大小相等或其中一个为1或其中一个不存在
例如
a = torch.arange(36).reshape((1,9,4))
b = torch.arange(9).reshape((9,1))
a + b就能运行
参考

第一题
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])

X数据如下所示

0. 1. 2. 3.
4. 5. 6. 7.
8. 9. 10. 11.

Y数据如下所示

2. 1. 4. 3.
1. 2. 3. 4.
4. 3. 2. 1.

X == Y的结果为

False True False True
False False False False
False False False False
X<Y的结果为
True False True False
False False False False
False False False False
X>Y的结果为
False False False False
True True True True
True True True True

得到了一些由比较的布尔值组成的张量

第二题

a = torch.arange(3).reshape((3, 1))

b = torch.arange(2).reshape((1, 2))
a,b

输出框

(tensor([[0],
         [1],
         [2]]),
 tensor([[0, 1]]))
a = torch.arange(3).reshape((1,3, 1))
a

输出框

tensor([[[0],
         [1],
         [2]]])
a+b

输出框

tensor([[[0, 1],
         [1, 2],
         [2, 3]]])

可以看出a,b都被复制为shape=(1, 3, 2)形状,然后相加,结果仍然为(1, 3, 2)形状,说明广播机制对张量仍然生效

动手代码写了一下,一个括号完全可以的,所以应该是按照正常方法传参就可以。

注意:

  • .add().add_()都能把两个张量加起来,但.add_in-place 操作,也就是结果会存储到原来的x中。
  • Q:共享内存的意思不是说地址一样,而是说一个改变会引起另一个改变?
    A :如果你对其中一个对象进行了修改,那么另一个对象也会反映出这些更改,因为它们实际上是在操作同一块内存区域,即同一地址。

假设有以下两个张量:
张量A形状为 (8,1,6,1)
张量B形状为 (7,1,5)
要检查这两个张量是否可以进行广播,从尾部向前对齐每个张量的维度,维度大小要么相同,要么其中一个维度的大小必须是1:
A的形状为 (8,1,6,1)
B的形状补全后为 (1,7,1,5)
比较每个维度:
第一维:A是8,B是1(B可以广播匹配A)
第二维:A是1,B是7(A可以广播匹配B)
第三维:A是6,B是1(B可以广播匹配A)
第四维:A是1,B是5(A可以广播匹配B)
由于每个维度都符合广播条件,这两个张量可以成功进行广播。

我对广播的理解:

  1. 将每个维度补齐到大值为止 ,即 max(a.shape,b.shape)
  2. 对于每个维度,小值必须是1才可以补.
  3. 将两个矩阵的维度扩展到相同的长度,从后向前补齐

第一:
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a+b :
会补齐到 (max (3,1), max(1,2) = > (3,2) 满足条件2,那么a 沿着dim=1补1份, b沿着dim=0补2份.

第二:
a = torch.arange(12).reshape((3,4))
b = torch.arange(6).reshape((2,3))
a +b : 失败 , 不满足2

第三:

a = torch.arange(24).reshape((2,3,4))
b = torch.arange(6).reshape((2,3)) => (1,2,3) , 不满足2 ,失败
b = torch.arange(6) => (1,1,6) , 不满足2,失败
b = torch.arange(4) => (1,1,4) , 满足2,先沿dim=1(横着) 补到(1,3,4) ,再沿dim=0(竖着) 补到(2,3,4).

你这是在手机上吗?怎么做到的,可以在手机上编程? :thinking:

不太理解,为什么张量和数组的内存地址不一样,他们在内存中怎么会是同一片内存区域呢?