Skip to content

张量Tensor

更新: 2025/2/24 字数: 0 字 时长: 0 分钟

张量(Tensor)是 PyTorch 深度学习框架中最基本包含单一数据类型的单元和数据结构

初识张量

我们可以简单地将张量 Tensor 理解为标量、向量或者矩阵的泛化形式,也可以将张量看做是一个支持高效科学计算方法的数组。

image-20240922171811158

不同张量

首先我们来说明一下什么是标量、向量、矩阵等概念,具体解释如下:

  • 标量:指仅包含一个数字的张量,也被成为是 0 维张量。例如,下图的 -9 就是一个标量。

image-20240922172137145

  • 向量:指由多个标量组成的数组,也被成为是 1 维张量。例如,下图中的 5 个标量放到一个数组中,就得到了一个向量。

image-20240922172626856

  • 矩阵:指由多个向量组成的数组,也被成为是 2 维张量。例如,将 4 个长度是 5 的向量,一行一行的排列,就得到了 454*5 形状的矩阵。

image-20240922172952532

  • 3 维张量:指由多个矩阵组成的数组。例如,图中将 3 个 454*5 形状的矩阵叠放,就得到了 3453*4*5 形状的 3 维张量(这里我们可以将 3 维张量直观地理解为数字组成的立方体)。

image-20240922173559168

  • 4 维张量:指由多个 3 维张量组成的数组。例如,图中将 3 维张量看做是一个立方体,多个立方体组合,就会得到 4 维张量。

image-20240922173843395

  • 5 维张量:指由多个 3 维张量组成的矩阵。例如,图中将 3453*4*5 形状的 3 维张量放到 555*5 的矩阵中,就会得到 345553*4*5*5*5 的 5 维张量。

image-20240922175305309

  • 高维张量:通过扩展 5 维张量的排列方式,还可以进一步得到 6 维、7 维等等更高维度的张量。

image-20240922175628781

创建张量

torch.Tensor(形状) 返回一个指定形状数据全为随机浮点类型的张量。

python
import torch

print(torch.Tensor(2, 3))  # 创建一个2*3形状的随机数张量
"""
输出:
tensor([[1.1547e+19, 4.1988e+07, 3.0357e+32],
        [1.1547e+19, 6.4069e+02, 4.3066e+21]])
"""

torch.Tensor(列表) 根据指定的列表数据创建张量。

python
a = torch.Tensor([[1, 2, 3], [4, 5, 6]])
print(a)        # 输出:tensor([[1., 2., 3.], [4., 5., 6.]])
b = a.tolist()  # 通过tolist函数,将张量a转换为列表
print(b)        # 输出:[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]

torch.empty(形状) 返回一个指定形状包含未初始化数据的张量。

python
import torch

print(torch.empty(2))     # 输出:tensor([0., 0.])。注释:2列(一维),里面全是未初始化数据,可能包含任意数值。
print(torch.empty(2, 3))  # 输出:tensor([[0., 0., 0.],[0., 0., 0.]])。注释:2行3列(二维),里面全未初始化数据,可能包含任意数值。
print(torch.empty(2, 3, 4))
'''
输出:tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]],
        [[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]])
注释:2组3行4列(三维),里面全未初始化数据,可能包含任意数值。
'''

torch.zeros(形状) 返回一个指定形状数据全为 0 浮点类型的张量。

python
import torch

print(torch.zeros(2))     # 输出:tensor([0., 0.])。注释:2列(一维),里面全是0浮点类型数据。
print(torch.zeros(2, 3))  # 输出:tensor([[0., 0., 0.],[0., 0., 0.]])。注释:2行3列(二维),里面全是0浮点类型数据。
print(torch.zeros(2, 3, 4))
'''
输出:tensor([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]],
        [[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]]])
注释:2组3行4列(三维),里面全是0浮点类型数据。
'''

torch.ones(形状) 返回一个指定形状数据全为 1 浮点类型的张量。

python
import torch

print(torch.ones(2))  # 输出:tensor([1., 1.])。注释:2列(一维),里面全是浮点型数据1。
print(torch.ones(2, 3))  # 输出:tensor([[1., 1., 1.],[1., 1., 1.]])。注释:2行3列(二维),里面全是浮点型数据1。
print(torch.ones(2, 3, 4))
'''
输出:tensor([[[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]],
        [[1., 1., 1., 1.],
         [1., 1., 1., 1.],
         [1., 1., 1., 1.]]])
注释:2组3行4列(三维),里面全是浮点型数据1。
'''

torch.arange(范围) 返回一个数据且在指定范围内整数类型的张量。

python
import torch

print(torch.arange(12))        # 输出:tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
print(torch.arange(1, 12))     # 输出:tensor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
print(torch.arange(1, 12, 2))  # 输出:tensor([1, 3, 5, 7, 9, 11])

torch.randn(形状) 返回一个符合标准正太分布的随机浮点类型数据的张量。

python
import torch

print(torch.randn(2, 3))  # 输出:tensor([[-0.4764, -0.6393, -0.8041], [ 2.5845, -2.1655, -1.3800]])

torch.randint(low=起始, high=结束, size=(形状)) 返回一个数据且在指定范围内指定形状的整数类型的张量。

python
import torch

print(torch.randint(low=1, high=9, size=(2,)))    # 输出:tensor([4, 6])。注释:创建一个数据在[1,9)前闭后开范围内的2列(一维)张量。
print(torch.randint(low=1, high=9, size=(2, 3)))  # 输出:tensor([[1, 3, 8],[4, 6, 5]])。注释:创建一个数据在[1,9)前闭后开范围内的2行2列(二维)张量。
print(torch.randint(low=1, high=9, size=(2, 3, 4)))
'''
输出:tensor([[[7, 6, 3, 8],
         [2, 2, 3, 3],
         [7, 6, 6, 8]],
        [[1, 4, 2, 8],
         [5, 7, 5, 5],
         [2, 7, 4, 4]]])
注释:创建一个数据在[1,9)前闭后开范围内的2组3行4列(三维)张量。
'''

torch.linspace(low=起始, high=结束, size=(形状)) 返回一个区间范围内的均匀数据的张量。

python
import torch

print(torch.linspace(1, 10, 5))  # 输出:tensor([ 1.0000,  3.2500,  5.5000,  7.7500, 10.0000])

列表转化

张量的结构有点像嵌套列表和 numpy 中的 array 数组的一种结合,其实张量、数组可以通过列表转化。参看下面例子:

python
import torch
import numpy as np

# 一维
list_1 = [1, 2, 3, 4, 5, 6]
print(f'列表:{list_1}')
print(f'数组:{np.array(list_1)}')
print(f'张量:{torch.tensor(list_1)}')
'''
输出:
列表:[1, 2, 3, 4, 5, 6]
数组:[1 2 3 4 5 6]
张量:tensor([1, 2, 3, 4, 5, 6])
'''

# 二维
list_2 = [
    [1, 2, 3, 4, 5, 6],
    [1, 2, 3, 4, 5, 6],
    [1, 2, 3, 4, 5, 6],
]
print(f'列表:{list_2}')
print(f'数组:{np.array(list_2)}')
print(f'张量:{torch.tensor(list_2)}')
'''
输出:
列表:[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]
数组:[[1 2 3 4 5 6]
 [1 2 3 4 5 6]
 [1 2 3 4 5 6]]
张量:tensor([[1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6]])
'''

# 三维
list_3 = [
    [
        [1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6],
    ],
    [
        [1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6],
        [1, 2, 3, 4, 5, 6],
    ],
]
print(f'列表:{list_3}')
print(f'数组:{np.array(list_3)}')
print(f'张量:{torch.tensor(list_3)}')
'''
输出:
列表:[[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]], [[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]]
数组:[[[1 2 3 4 5 6]
  [1 2 3 4 5 6]
  [1 2 3 4 5 6]]
 [[1 2 3 4 5 6]
  [1 2 3 4 5 6]
  [1 2 3 4 5 6]]]
张量:tensor([[[1, 2, 3, 4, 5, 6],
         [1, 2, 3, 4, 5, 6],
         [1, 2, 3, 4, 5, 6]],
        [[1, 2, 3, 4, 5, 6],
         [1, 2, 3, 4, 5, 6],
         [1, 2, 3, 4, 5, 6]]])
'''

有细心的小伙伴会发现,上面创建张量使用 torch.Tensor,这里创建张量使用的是 torch.tensor,它们的区别在于:

  • torch.Tensor 是 Python 的类,默认创建 FloatTensor,运行 torch.Tensor 后,会调用 Tensor 的构造函数 init生成浮点类型的 Tensor,官方文档:https://pytorch.org/docs/stable/tensors.html
  • torch.tensor 是 Python 函数,原型为 torch.tensor(data, *, dtype=None),其中 data 是创建张量时所依赖的数据,可以是 list、tuple、array 等不同的数据类型。调用 torch.tensor 会直接将 data 中的数据进行复制,并根据原数据类型,生成相应的张量类型
python
import torch

a = torch.Tensor([1, 2, 3, 4, 5])
print(a)         # 输出:tensor([1., 2., 3., 4., 5.])
print(a.type())  # 输出:torch.FloatTensor

b = torch.tensor([1, 2, 3, 4, 5])
print(b)         # 输出:tensor([1, 2, 3, 4, 5])
print(b.type())  # 输出:torch.LongTensor

范围限定

torch.tensor(列表) 方法中还有一个 dtyp 参数,通过该参数我们还可以限定转换后张量 tensor 值的范围。我们可以把指定范围想象为一个表盘,0 在最上面,左半侧是负区间,右半侧是正区间,负区间的最小值和正区间的最大值在最下面相连,把数值想象为一个指针,数值为正数就顺时针旋转,数值为负数就逆时针旋转。

python
import torch

# 注释:dtype参数设置tensor格式数据的范围。
# 注释:torch.int8数据范围2**8=256,即-128~127之间。
# 注释:torch.int16数据范围2**16=65536,即-32768~32767之间。
# 注释:torch.int64数据范围2**64(最大),即-2**63~(2**63)-1之间。
print(torch.tensor([126], dtype=torch.int8))   # 输出:tensor([126], dtype=torch.int8)。注释:数值在正区间范围内。
print(torch.tensor([127], dtype=torch.int8))   # 输出:tensor([127], dtype=torch.int8)。注释:数值在正区间范围内。
print(torch.tensor([128], dtype=torch.int8))   # 输出:tensor([-128], dtype=torch.int8)。注释:数值超过正区间范围,跑到负区间范围。
print(torch.tensor([129], dtype=torch.int8))   # 输出:tensor([-127], dtype=torch.int8)。注释:数值超过正区间范围,跑到负区间范围。
print(torch.tensor([256], dtype=torch.int8))   # 输出:tensor([0], dtype=torch.int8)。注释:数值等于正负区间总范围的倍数。
print(torch.tensor([512], dtype=torch.int8))   # 输出:tensor([0], dtype=torch.int8)。注释:数值等于正负区间总范围的倍数。
print(torch.tensor([-127], dtype=torch.int8))  # 输出:tensor([-127], dtype=torch.int8)。注释:数值在负区间范围内。
print(torch.tensor([-128], dtype=torch.int8))  # 输出:tensor([-128], dtype=torch.int8)。注释:数值在负区间范围内。
print(torch.tensor([-129], dtype=torch.int8))  # 输出:tensor([127], dtype=torch.int8)。注释:数值超过负区间范围,跑到正区间范围。
print(torch.tensor([-130], dtype=torch.int8))  # 输出:tensor([126], dtype=torch.int8)。注释:数值超过负区间范围,跑到正区间范围。
print(torch.tensor([-256], dtype=torch.int8))  # 输出:tensor([0], dtype=torch.int8)。注释:数值等于正负区间总范围的倍数。
print(torch.tensor([-512], dtype=torch.int8))  # 输出:tensor([0], dtype=torch.int8)。注释:数值等于正负区间总范围的倍数。

张量属性

张量.dtype 返回张量的数据类型。

python
import torch

print(torch.tensor([128]).dtype)    # 输出:torch.int64
print(torch.tensor([128.0]).dtype)  # 输出:torch.float32

张量.shape 返回张量的结构形状。

python
import torch

print(torch.tensor([128, 128]).shape)  # 输出:torch.Size([2])。注释:2列(一维)。
print(torch.tensor([[128, 128]]).shape)  # 输出:torch.Size([1, 2])。注释:1行2列(二维)。
print(torch.tensor([[128], [128]]).shape)  # 输出:torch.Size([2, 1])。注释:2行1列(二维)。
print(torch.tensor([[[128], [128]], [[128], [128]]]).shape)  # 输出:torch.Size([2, 2, 1])。注释:2组2行1列(三维)。

张量方法

“张量方法”就是张量对象所自带的一些方法。

python
import torch

# torch.randint()生成的张量所有数值为int64整型。
t1 = torch.randint(low=1, high=9, size=(1,))
print(t1)  # 输出:tensor([7])

类型转换

张量.int() 将张量中所有的数据转换为 int32 整型。

python
print(t1.int())  # 输出:tensor([7], dtype=torch.int32)

张量.float() 将张量中所有的数据转换为 float32 单精度浮点型。

python
print(t1.float())  # 输出:tensor([7.])

张量.double() 将张量中所有的数据转换为 float64 双精度浮点型。

python
print(t1.double())  # 输出:tensor([7.], dtype=torch.float64)

张量.numpy() 将张量转换为 numpy 的 array 数组。

python
print(t1.numpy())  # 输出:[7]

数据提取

张量[维度坐标] 提取张量中指定维度坐标的值,若有多个维度用英文逗号隔开。

python
print(t1[0])  # 输出:7

张量.max() 提取张量中的最大值。

python
print(t1.max())  # 输出:tensor(7)

张量.min() 提取张量中的最小值。

python
print(t1.min())  # 输出:tensor(7)

张量.item() 提取张量里面唯一的一个数据,若有多个数据会报错。

python
print(t1.item())  # 输出:7

其他使用

张量.numel() 返回张量中元素的总个数。

python
print(t1.numel())  # 输出:1

张量.sum() 返回张量中元素的和。

python
print(t1.sum())  # 输出:9

张量[维度坐标]=值 设置张量中指定维度坐标的值,若有多个维度用英文逗号隔开。

python
t1[0] = 9

张量操作

算术运算

tensor 格式数据的算术运算就是对每个数据进行算术运算。

python
import torch

# 一维
list1 = [792, 436, 928, 303]
t1 = torch.tensor(list1)
print(t1 + 1)   # 输出:tensor([793, 437, 929, 304])
print(t1 * 10)  # 输出:tensor([7920, 4360, 9280, 3030])
print(t1 / 2)   # 输出:tensor([396.0000, 218.0000, 464.0000, 151.5000])
print(t1 % 2)   # 输出:tensor([0, 0, 0, 1])
print(t1 + t1)  # 输出:tensor([1584,  872, 1856,  606])
print(t1 - t1)  # 输出:tensor([0, 0, 0, 0])
print(t1 * t1)  # 输出:tensor([627264, 190096, 861184,  91809])
print(t1 / t1)  # 输出:tensor([1., 1., 1., 1.])

# 二维
list1 = [[0], [1], [2]]
list2 = [[0, 1]]
t1 = torch.tensor(list1)
t2 = torch.tensor(list2)
print(t1 + t2)
'''
输出:tensor([[0, 1],
             [1, 2],
             [2, 3]])
注释:当维度相同,形状不同时,会有一个广播机制来执行逻辑运算操作。
'''

# 原地执行操作(张量可以看作一个可变数据类型)
t1 = torch.tensor([[0], [1], [2]])
t2 = torch.tensor([[2], [3], [4]])
z = torch.zeros_like(t1)
print(id(z))  # 输出:140146615319872
z[:] = t1 + t2
print(id(z))  # 输出:140146615319872

逻辑运算

python
list1 = [[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]]
list2 = [[ 2.,  1.,  4.,  3.],
        [ 1.,  2.,  3.,  4.],
        [ 4.,  3.,  2.,  1.]]
t1 = torch.tensor(list1)
t2 = torch.tensor(list2)
print(t1 == t2)
'''
输出:tensor([[False,  True, False,  True],
             [False, False, False, False],
             [False, False, False, False]])
'''

维度操作

维度改变

张量.reshape((维度)) 在不改变元素数量和元素的值情况下,改变张量的形状,类似于 Python 中的浅拷贝。

python
import torch

x = torch.arange(12, dtype=torch.float32)
# reshape((3, 4))将一维张量转换为了3行4列(二维)的张量。
y = x.reshape((3, 4))
print(id(x), x)
print(id(y), y)
y[:] = 2
print(id(x), x)
print(id(y), y)
'''
输出:2218372795824 tensor([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])
输出:2218372882080 tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]])
输出:2218372795824 tensor([2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.])
输出:2218372882080 tensor([[2., 2., 2., 2.],
        [2., 2., 2., 2.],
        [2., 2., 2., 2.]])
'''

张量.view(维度) 在不改变元素数量和元素的值情况下,改变张量的形状。

python
import torch

# 三维(2组X3行X4列=24个数据)
list1 = [
    [
        [792, 436, 928, 303],
        [809, 170, 778, 652],
        [967, 520, 419, 184]
    ],
    [
        [402, 754, 327, 979],
        [712, 926, 879, 934],
        [540, 953, 209, 369]
    ]
]
t1 = torch.tensor(list1)
print(t1.view(-1))
print(t1.view(-1).shape)
'''
输出:tensor([792, 436, 928, 303, 809, 170, 778, 652, 967, 520, 419, 184, 402, 754, 327, 979, 712, 926, 879, 934, 540, 953, 209, 369])
输出:torch.Size([24])
注释:将张量的维度调整至一维,其中第一个维度(列数)自动计算,最后得到24等于t1中的24个数据。
'''
print(t1.view(-1, 12))
print(t1.view(-1, 12).shape)
'''
输出:tensor([[792, 436, 928, 303, 809, 170, 778, 652, 967, 520, 419, 184],
        [402, 754, 327, 979, 712, 926, 879, 934, 540, 953, 209, 369]])
输出:torch.Size([2, 12])
注释:将张量的维度调整至二维,其中第一个维度(行数)自动计算,第二个维度为12,最后得到2X12等于t1中的24个数据。
'''
print(t1.view(-1, 2, 6))
print(t1.view(-1, 2, 6).shape)
'''
输出:tensor([[[792, 436, 928, 303, 809, 170],
         [778, 652, 967, 520, 419, 184]],
        [[402, 754, 327, 979, 712, 926],
         [879, 934, 540, 953, 209, 369]]])
输出:torch.Size([2, 2, 6])
注释:将张量的维度调整至三维,其中第一个维度(组数)自动计算,第二个维度为2,第三个维度为6,最后得到2X2X6等于t1中的24个数据。
'''

通过 tensor 格式数据的 permute 方法,我们可以将数据的维度进行轴交换。

python
import torch

# 二维
list1 = [
    [402, 754, 327, 979],
    [712, 926, 879, 934],
    [540, 953, 209, 369]
]
# 注释:将列表转换为一个3行4列(二维)的张量。
t1 = torch.tensor(list1)
# 注释:行、列分别对应(0, 1),则(1, 0)就是把行、列进行对调。
t2 = t1.permute(1, 0)
print(t2)
print(t2.shape)
'''
输出:tensor([[402, 712, 540],
             [754, 926, 953],
             [327, 879, 209],
             [979, 934, 369]])
输出:torch.Size([4, 3])
注释:把行、列进行对调后,原本3行4列的张量变为了4行3列的张量,相当于按斜对称轴旋转了一次。
'''

# 三维
t3 = torch.randint(low=1, high=9, size=(2, 3, 4))
t4 = t3.permute(1, 0, 2)
print(t4.shape)
'''
输出:torch.Size([3, 2, 4])
注释:组、行、列分别对应(0, 1, 2),则(1, 0, 2)意味则组、行对调,列不变。因此原本2组3行4列的张量就变为了3组2行4列的张量。
'''

维度比较

上面我们学习了张量常用的内置方法,其中有两个方法 max()/min() 可以通过 dim 参数进行维度上的比较。若数据的维度是二维,则 dim 参数的取值范围是:[-2, 2)

  • dim=1 进入第二层,返回每一行的最大值以及下标。
  • dim=0 进入第一层,返回每一列的最大值以及下标。
  • dim=-1 负数加上数据的维度,相当于 dim=1,返回每一行的最大值以及下标。
  • dim=-2 负数加上数据的维度,相当于 dim=0,返回每一列的最大值以及下标。
  • dim 参数超出取值范围会报错。
python
import torch

# 二维
list1 = [
    [792, 436, 928, 303],
    [809, 170, 778, 652],
    [967, 520, 419, 184],
]
t1 = torch.tensor(list1)
print(t1.max())
'''
输出:tensor(967)
注释:输出t1中所有数值中的最大值。
'''
print(t1.max(dim=1).values)
print(t1.max(dim=1).indices)
'''
输出:tensor([928, 809, 967]),
输出:tensor([2, 0, 0]))
注释:进入第二层,返回每一行的最大值以及下标。
'''
print(t1.max(dim=0).values)
print(t1.max(dim=0).indices)
'''
输出:tensor([967, 520, 928, 652]),
输出:tensor([2, 2, 0, 1]))
注释:进入第一层,返回每一列的最大值以及下标。
'''
print(t1.max(dim=-1).values)
print(t1.max(dim=-1).indices)
'''
输出:tensor([928, 809, 967]),
输出:tensor([2, 0, 0]))
注释:加上数据的维度,相当于进入第二层,返回每一行的最大值以及下标。
'''
print(t1.max(dim=-2).values)
print(t1.max(dim=-2).indices)
'''
输出:tensor([967, 520, 928, 652]),
输出:tensor([2, 2, 0, 1]))
注释:加上数据的维度,相当于进入第一层,返回每一列的最大值以及下标。
'''

接下来我们举一个三维数据的例子,那么他的 dim 参数的取值范围是:[-3, 3)

  • dim=2 进入第三层,返回每一行的最大值以及下标。
  • dim=1 进入第二层,返回每一列的最大值以及下标。
  • dim=0 进入第一层,返回每一组的最大值以及下标。
  • dim=-1 负数加上数据的维度,相当于 dim=2,返回每一行的最大值以及下标。
  • dim=-2 负数加上数据的维度,相当于 dim=1,返回每一列的最大值以及下标。
  • dim=-3 负数加上数据的维度,相当于 dim=0,返回每一组的最大值以及下标。
  • dim 参数超出取值范围会报错。
python
import torch

# 三维
list1 = [
    [
        [792, 436, 928, 303],
        [809, 170, 778, 652],
        [967, 520, 419, 184]
    ],
    [
        [402, 754, 327, 979],
        [712, 926, 879, 934],
        [540, 953, 209, 369]
    ]
]
t1 = torch.tensor(list1)
print(t1.max())
'''
输出:tensor(967)
注释:输出t1中所有数值中的最大值。
'''
print(t1.max(dim=2).values)
print(t1.max(dim=2).indices)
'''
输出:tensor([[928, 809, 967], [979, 934, 953]]),
输出:tensor([[2, 0, 0], [3, 3, 1]]))
注释:进入第三层,返回每一行的最大值以及下标。
'''
print(t1.max(dim=1).values)
print(t1.max(dim=1).indices)
'''
输出:tensor([[967, 520, 928, 652], [712, 953, 879, 979]]),
输出:tensor([[2, 2, 0, 1], [1, 2, 1, 0]]))
注释:进入第二层,返回每一列的最大值以及下标。
'''
print(t1.max(dim=0).values)
print(t1.max(dim=0).indices)
'''
输出:tensor([[792, 754, 928, 979], [809, 926, 879, 934], [967, 953, 419, 369]]),
输出:tensor([[0, 1, 0, 1], [0, 1, 1, 1], [0, 1, 0, 1]]))
注释:进入第一层,返回每一组的最大值以及下标。
'''
print(t1.max(dim=-1).values)
print(t1.max(dim=-1).indices)
'''
输出:tensor([[928, 809, 967], [979, 934, 953]]),
输出:tensor([[2, 0, 0], [3, 3, 1]]))
注释:负数加上数据的维度,进入第三层,返回每一行的最大值以及下标。
'''
print(t1.max(dim=-2).values)
print(t1.max(dim=-2).indices)
'''
输出:tensor([[967, 520, 928, 652], [712, 953, 879, 979]]),
输出:tensor([[2, 2, 0, 1], [1, 2, 1, 0]]))
注释:负数加上数据的维度,进入第二层,返回每一列的最大值以及下标。
'''
print(t1.max(dim=-3).values)
print(t1.max(dim=-3).indices)
'''
输出:tensor([[792, 754, 928, 979], [809, 926, 879, 934], [967, 953, 419, 369]]),
输出:tensor([[0, 1, 0, 1], [0, 1, 1, 1], [0, 1, 0, 1]]))
注释:负数加上数据的维度,进入第一层,返回每一组的最大值以及下标。
'''

维度合并

python
import torch

# reshape(3, 4)将一维张量转换为了二维3行4列形状的张量。
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]])
# 在0维上进行合并
print(torch.cat((x, y), dim=0))
# 在1维上进行合并
print(torch.cat((x, y), dim=1))
'''
输出:
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [ 2.,  1.,  4.,  3.],
        [ 1.,  2.,  3.,  4.],
        [ 4.,  3.,  2.,  1.]])
tensor([[ 0.,  1.,  2.,  3.,  2.,  1.,  4.,  3.],
        [ 4.,  5.,  6.,  7.,  1.,  2.,  3.,  4.],
        [ 8.,  9., 10., 11.,  4.,  3.,  2.,  1.]])
'''

切片操作

tensor 格式数据的切片操作和列表的切片操作类似。是几维数据切片就要用几组下标范围,若是三维数据切片就是 [start: end, start: end, start: end] 三组下标范围。

python
import torch

# 三维
list1 = [
    [
        [792, 436, 928, 303],
        [809, 170, 778, 652],
        [967, 520, 419, 184]
    ],
    [
        [402, 754, 327, 979],
        [712, 926, 879, 934],
        [540, 953, 209, 369]
    ]
]
t1 = torch.tensor(list1)
print(t1[:, :, :])
'''
输出:tensor([[[792, 436, 928, 303],
         [809, 170, 778, 652],
         [967, 520, 419, 184]],
        [[402, 754, 327, 979],
         [712, 926, 879, 934],
         [540, 953, 209, 369]]])
注释:没有下标代表全切。
'''
print(t1[1:, :, :])
'''
输出:tensor([[[402, 754, 327, 979],
         [712, 926, 879, 934],
         [540, 953, 209, 369]]])
注释:第1组以后全切。
'''
print(t1[1:, 2:, :])
'''
输出:tensor([[[540, 953, 209, 369]]])
注释:第1组以后的每组第2行全切。
'''
print(t1[1:, 2:, 3:])
'''
输出:tensor([[[369]]])
注释:第1组以后的每组第2行的第3个位置以后全切。
'''
print(t1[1:, 2:, 3:].item())
'''
输出:369
注释:上面结果中tensor格式数据只有一个,因此可以用item方法取出来。
'''

GPU加速

上面 tensor 格式数据都是在 CPU 当中运算,但前面我们安装的 Pytorch 是 GPU 版本,如何利用 GPU 来运算?参看下面例子:

python
import torch

# 一维
list1 = [792, 436, 928, 303]
# 在CPU中将list转为一维的tensor格式数据
t1 = torch.tensor(list1)
# 启用GPU的CUDA核心
device = torch.device('cuda')
# 将t1的数据推送至GPU中
print(t1.to(device))
'''
输出:tensor([792, 436, 928, 303], device='cuda:0')
注释:t1数据被推送至了GPU的CUDA核心中。cuda:0表示在哪个显卡。
'''

运算 tensor 格式数据必须在同一个设备上,即要么都在同一个 CPU 上参与运算或要么都在同一个 GPU 上参与运算,否则就会报错。参看下面例子:

python
# 将推送至GPU中的t1数据和CPU中的t1数据进行运算
print(t1.to(device) + t1)
'''
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!
运行错误:所有的tensor数据都必须在同一个设备上运算,这里使用了至少两个设备运算,一个是CUDA核心0,一个是CPU。
'''

GPU 运算方案推荐写法如下:

python
import torch

# 一维
list1 = [792, 436, 928, 303]
# 在CPU中将list转为一维的tensor格式数据
t1 = torch.tensor(list1)
# cuda:0表示在哪个显卡上进行运算,单显卡可以不写,会自动分配。
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
# 将t1的推送至GPU中
t2 = t1.to(device)
# 在GPU中进行运算
print(t2 + t2)
'''
输出:tensor([1584,  872, 1856,  606], device='cuda:0')
注释:输出的结果后面cuda:0表示是在显卡上利用CUDA核心进行的运算。
'''