
张量Tensor
更新: 2025/2/24 字数: 0 字 时长: 0 分钟
张量(Tensor)是 PyTorch 深度学习框架中最基本包含单一数据类型的单元和数据结构。
初识张量
我们可以简单地将张量 Tensor 理解为标量、向量或者矩阵的泛化形式,也可以将张量看做是一个支持高效科学计算方法的数组。
不同张量
首先我们来说明一下什么是标量、向量、矩阵等概念,具体解释如下:
- 标量:指仅包含一个数字的张量,也被成为是 0 维张量。例如,下图的 -9 就是一个标量。
- 向量:指由多个标量组成的数组,也被成为是 1 维张量。例如,下图中的 5 个标量放到一个数组中,就得到了一个向量。
- 矩阵:指由多个向量组成的数组,也被成为是 2 维张量。例如,将 4 个长度是 5 的向量,一行一行的排列,就得到了 形状的矩阵。
- 3 维张量:指由多个矩阵组成的数组。例如,图中将 3 个 形状的矩阵叠放,就得到了 形状的 3 维张量(这里我们可以将 3 维张量直观地理解为数字组成的立方体)。
- 4 维张量:指由多个 3 维张量组成的数组。例如,图中将 3 维张量看做是一个立方体,多个立方体组合,就会得到 4 维张量。
- 5 维张量:指由多个 3 维张量组成的矩阵。例如,图中将 形状的 3 维张量放到 的矩阵中,就会得到 的 5 维张量。
- 高维张量:通过扩展 5 维张量的排列方式,还可以进一步得到 6 维、7 维等等更高维度的张量。
创建张量
torch.Tensor(形状)
返回一个指定形状数据全为随机浮点类型的张量。
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(列表)
根据指定的列表数据创建张量。
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(形状)
返回一个指定形状包含未初始化数据的张量。
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 浮点类型的张量。
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 浮点类型的张量。
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(范围)
返回一个数据且在指定范围内整数类型的张量。
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(形状)
返回一个符合标准正太分布的随机浮点类型数据的张量。
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=(形状))
返回一个数据且在指定范围内指定形状的整数类型的张量。
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=(形状))
返回一个区间范围内的均匀数据的张量。
import torch
print(torch.linspace(1, 10, 5)) # 输出:tensor([ 1.0000, 3.2500, 5.5000, 7.7500, 10.0000])
列表转化
张量的结构有点像嵌套列表和 numpy
中的 array
数组的一种结合,其实张量、数组可以通过列表转化。参看下面例子:
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
中的数据进行复制,并根据原数据类型,生成相应的张量类型。
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 在最上面,左半侧是负区间,右半侧是正区间,负区间的最小值和正区间的最大值在最下面相连,把数值想象为一个指针,数值为正数就顺时针旋转,数值为负数就逆时针旋转。
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
返回张量的数据类型。
import torch
print(torch.tensor([128]).dtype) # 输出:torch.int64
print(torch.tensor([128.0]).dtype) # 输出:torch.float32
张量.shape
返回张量的结构形状。
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列(三维)。
张量方法
“张量方法”就是张量对象所自带的一些方法。
import torch
# torch.randint()生成的张量所有数值为int64整型。
t1 = torch.randint(low=1, high=9, size=(1,))
print(t1) # 输出:tensor([7])
类型转换
张量.int()
将张量中所有的数据转换为 int32
整型。
print(t1.int()) # 输出:tensor([7], dtype=torch.int32)
张量.float()
将张量中所有的数据转换为 float32
单精度浮点型。
print(t1.float()) # 输出:tensor([7.])
张量.double()
将张量中所有的数据转换为 float64
双精度浮点型。
print(t1.double()) # 输出:tensor([7.], dtype=torch.float64)
张量.numpy()
将张量转换为 numpy 的 array
数组。
print(t1.numpy()) # 输出:[7]
数据提取
张量[维度坐标]
提取张量中指定维度坐标的值,若有多个维度用英文逗号隔开。
print(t1[0]) # 输出:7
张量.max()
提取张量中的最大值。
print(t1.max()) # 输出:tensor(7)
张量.min()
提取张量中的最小值。
print(t1.min()) # 输出:tensor(7)
张量.item()
提取张量里面唯一的一个数据,若有多个数据会报错。
print(t1.item()) # 输出:7
其他使用
张量.numel()
返回张量中元素的总个数。
print(t1.numel()) # 输出:1
张量.sum()
返回张量中元素的和。
print(t1.sum()) # 输出:9
张量[维度坐标]=值
设置张量中指定维度坐标的值,若有多个维度用英文逗号隔开。
t1[0] = 9
张量操作
算术运算
tensor
格式数据的算术运算就是对每个数据进行算术运算。
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
逻辑运算
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 中的浅拷贝。
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(维度)
在不改变元素数量和元素的值情况下,改变张量的形状。
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
方法,我们可以将数据的维度进行轴交换。
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
参数超出取值范围会报错。
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
参数超出取值范围会报错。
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]]))
注释:负数加上数据的维度,进入第一层,返回每一组的最大值以及下标。
'''
维度合并
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]
三组下标范围。
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 来运算?参看下面例子:
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 上参与运算,否则就会报错。参看下面例子:
# 将推送至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 运算方案推荐写法如下:
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核心进行的运算。
'''