对于广播机制中两个张量按元素相加,要满足以下两个条件:
1、两个张量维度相同
2、每个张量的size里面要有一个维度为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))有什么区别
三峡刘战来也[quote=“goldpiggy, post:1, topic:1747, full:true”]
https://zh.d2l.ai/chapter_preliminaries/ndarray.html
[/quote]
可以参考 :
广播机制规则:
- 如果遵守以下规则,则两个tensor是“可广播的”:
- 每个tensor至少有一个维度;
- 遍历tensor所有维度时,从末尾随开始遍历,两个tensor存在下列情况:
- tensor维度相等。
- tensor维度不等且其中一个维度为1。
- tensor维度不等且其中一个维度不存在。
- 如果两个tensor是“可广播的”,则计算过程遵循下列规则:
- 如果两个tensor的维度不同,则在维度较小的tensor的前面增加维度,使它们维度相等。
- 对于每个维度,计算结果的维度值取两个tensor中较大的那个值。
- 两个tensor扩展维度的过程是将数值进行复制。
我之前找到的形式上的规律是: 两个张量总是在两轴间成对出现x,1和1,x形式,然后对1的轴做广播;其他轴若不能配对则应该保持大小相同。 还是你这个规则全面。
-
运行本节中的代码。将本节中的条件语句
X == Y
更改为X < Y
或X > 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]])
- 用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同?
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)
由于每个维度都符合广播条件,这两个张量可以成功进行广播。
我对广播的理解:
- 将每个维度补齐到大值为止 ,即 max(a.shape,b.shape)
- 对于每个维度,小值必须是1才可以补.
- 将两个矩阵的维度扩展到相同的长度,从后向前补齐
第一:
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).
你这是在手机上吗?怎么做到的,可以在手机上编程?
不太理解,为什么张量和数组的内存地址不一样,他们在内存中怎么会是同一片内存区域呢?