3x4x5的张量:
x = torch.tensor([[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]],
[[21, 22, 23, 24, 25],
[26, 27, 28, 29, 30],
[31, 32, 33, 34, 35],
[36, 37, 38, 39, 40]],
[[41, 42, 43, 44, 45],
[46, 47, 48, 49, 50],
[51, 52, 53, 54, 55],
[56, 57, 58, 59, 60]]])
dim=0:代表3个元素的维度,每个元素是一个4x5的矩阵。
dim=1:代表4个元素的维度,每个元素是一个5维的向量。
dim=2:代表5个元素的维度,每个元素是一个标量。
3 维 tensor 的sun操作理解
参考Pytorch从入门到实践:dim维度的使用(终极版)_pytorch tensor dim-CSDN博客
3 个括号代表的维度从左往右分别为 0, 1, 2,在第 0 维遍历得到矩阵,在第 1 维遍历得到向量,在第 2 维遍历得到标量
更详细一点
所以,我们明白了:标量,向量,矩阵, 三维张量之间的关系,三维张量里面包含了二维的矩阵,二维矩阵里面包含了一维的向量,一维向量里面包含了零维的标量。
b = torch.tensor([[[3, 2], [1, 4]], [[5, 6], [7, 8]]])
print(b)tensor([[[3, 2],[1, 4]],[[5, 6],[7, 8]]])
将 b 在第 0 维相加,第 0 维为最外层括号,最外层括号中的元素为矩阵[[3, 2], [1, 4]]和[[5, 6], [7, 8]]。在第 0 维求和,就是将第 0 维中的元素(矩阵)相加
s = torch.sum(b, dim=0)
print(s)
tensor([[ 8, 8],[ 8, 12]])
求 b 在第 1 维的和,就是将 b 第 1 维中的元素[3, 2]和[1, 4], [5, 6]和 [7, 8]相加,所以
[3,2]+[1,4]=[4,6],[5,6]+[7,8]=[12,14]
s = torch.sum(b, dim=1)
print(s)
tensor([[ 4, 6],[12, 14]])
则在 b 的第 2 维求和,就是对标量 3 和 2, 1 和 4, 5 和 6 , 7 和 8 求和
s = torch.sum(b, dim=2)
print(s)
tensor([[ 5, 5],[11, 15]])
如果想要保持结果的维度不变,设置参数keepdim=True
即可。
各阶张量
0阶张量(标量):
0阶张量是一个单独的数字或数值,没有维度。
示例:x = 5
1阶张量(向量):
1阶张量是有序的一维数组,具有一个维度。
示例:x = [1, 2, 3, 4]
在PyTorch中,形状表示为:(4,)
2阶张量(矩阵):
2阶张量是一个二维数组,具有两个维度:行和列。
示例:x = [[1, 2], [3, 4]]
在PyTorch中,形状表示为:(2, 2)
3阶张量(三维数组):
3阶张量是一个具有三个维度的数组,例如图片数据,其中维度可以理解为高度、宽度和通道数。
示例:x = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
在PyTorch中,形状表示为:(2, 2, 2)
dim
一些常见操作
import torch
x = torch.tensor([[0, 1, 2], [3, 4, 5]]) # shape (2, 3)
# 沿行(纵向)压缩 → 每列求和
x.sum(dim=0) # tensor([3, 5, 7]) shape (3,)
# 沿列(横向)压缩 → 每行求和
x.sum(dim=1) # tensor([3, 12]) shape (2,)y = torch.tensor([[[1,2],[3,4]], [[5,6],[7,8]]]) # shape (2, 2, 2)
# 沿最外层维度压缩 → 同位置元素取最大值
y.max(dim=0)
# values: tensor([[5,6], [7,8]]), indices: tensor([[1,1], [1,1]])
# 沿中间维度压缩 → 每行取最大值
y.max(dim=1)
# values: tensor([[3,4], [7,8]]), indices: tensor([[1,1], [1,1]])x = torch.tensor([[1, 2], [3, 4]]) # (2, 2)
y = torch.tensor([[5, 6]]) # (1, 2)
# 沿行(dim=0)拼接 → 新增行
torch.cat([x, y], dim=0)
# tensor([[1, 2],
# [3, 4],
# [5, 6]]) shape (3, 2)
# 错误示例:列数不匹配时 dim=0 会报错!
z = torch.tensor([[7], [8]])
torch.cat([x, z], dim=1) # 正确:沿列拼接 → 新增列t = torch.arange(10).reshape(5, 2) # (5, 2)
# 沿行(dim=0)切分为 2 行和 3 行
parts = t.split([2, 3], dim=0)
# part1: shape (2, 2), part2: shape (3, 2)x = torch.zeros(3, 1, 2) # (3, 1, 2)
x.squeeze(dim=1) # 移除 dim=1 → (3, 2)
x.unsqueeze(dim=0) # 在 dim=0 添加维度 → (1, 3, 1, 2)x = torch.randn(2, 3, 5) # (2, 3, 5)
x.permute(2, 0, 1) # 重排为 (5, 2, 3)
mean操作
import torch
x = torch.arange(24).view(2, 3, 4).float() # 形状 (2, 3, 4)
"""
x 内容:
[[[ 0., 1., 2., 3.],[ 4., 5., 6., 7.],[ 8., 9., 10., 11.]],[[12., 13., 14., 15.],[16., 17., 18., 19.],[20., 21., 22., 23.]]]
"""
不同维度的均值计算:
操作 | 计算逻辑 | 输出形状 | 结果 |
---|---|---|---|
x.mean(dim=0) | 沿通道(第0维)求平均 | (3, 4) | [[6., 7., 8., 9.], [10., 11., 12., 13.], [14., 15., 16., 17.]] |
x.mean(dim=1) | 沿宽度(第1维)求平均 | (2, 4) | [[4., 5., 6., 7.], [16., 17., 18., 19.]] |
x.mean(dim=2) | 沿高度(第2维)求平均 | (2, 3) | [[1.5, 5.5, 9.5], [13.5, 17.5, 21.5]] |
x.mean(dim=[1,2]) | 沿宽度和高度同时求平均 | (2,) | [5.5, 17.5] |
dim=-2
的操作效果(三维张量等价于 dim=1
):
将中间维度(大小为3)压缩为1,结果形状变为 (2, 1, 4)
→ 实际输出 (2, 4)
(因默认压缩空维度),dim=k
表示沿维度 k
压缩(该维度消失),
例如:
原始张量: [3,3,4] -> [3,4]
[[[ 0, 1, 2, 3], # 第1个矩阵
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],[[12, 13, 14, 15], # 第2个矩阵
[16, 17, 18, 19],
[20, 21, 22, 23]]]沿 dim=-2 求和后:
[[ 12, 15, 18, 21], # 0+4+8, 1+5+9, ...
[48, 51, 54, 57]] # 12+16+20, 13+17+21, ...
实际计算示例
假设场景:
transport = incident_lights * incident_areas * n_d_i # 逐元素相乘:
# 结果维度:(num_pts, num_sample, 3)
# incident_lights: (num_pts, num_sample, 3)
# incident_areas: (num_pts, num_sample, 1)
# n_d_i: (num_pts, num_sample, 1)
num_pts=1
(1个表面点)num_sample=2
(2个采样方向)- 数据:
incident_lights = [[[1.0, 0.5, 0.2], [0.8, 0.3, 0.1]]] # (1,2,3) incident_areas = [[0.6], [0.6]] # (1,2,1) n_d_i = [[[0.9], [0.7]]] # (1,2,1)
分步计算:
# 第一步:逐元素相乘
term1 = incident_lights * incident_areas # [[[1.0 * 0.6, 0.5 * 0.6, 0.2 * 0.6] = [0.6, 0.3, 0.12]# [0.8 * 0.6, 0.3 * 0.6, 0.1 * 0.6] = [0.48, 0.18, 0.06]]]
term2 = term1 * n_d_i # [[[0.6 * 0.9, 0.3 * 0.9, 0.12 * 0.9] = [0.54, 0.27, 0.108]# [0.48 * 0.7, 0.18 * 0.7, 0.06 * 0.7] = [0.336, 0.126, 0.042]]]# 第二步:沿采样维度(dim=-2)求平均
diffuse_light = term2.mean(dim=-2) # [(0.54+0.336)/2, (0.27+0.126)/2, (0.108+0.042)/2]# = [0.438, 0.198, 0.075]