【深度学习】张量
深度学习
张量
张量概念
什么是张量(Tensor)?
可以先这样理解:
- 0 维:标量(scalar),比如 3.14
- 1 维:向量(vector),比如 [ 1 2 3 4 ] \begin{bmatrix} 1 & 2 & 3 & 4 \end{bmatrix} [1234]
- 2 维:矩阵(matrix),比如 [ 1 2 3 4 ] \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} [1324]
- 3 维及以上:统称为 张量(tensor)——元素为同一数据类型的多维矩阵
在 PyTorch 里,核心数据结构就是 torch.Tensor,跟 numpy 里的 ndarray 很像,但多了:
- 可以在 GPU 上计算
- 可以记录计算图,自动求导
张量创建方法
PyTorch 框架属于最常用的深度学习框架,无论是 ANN,CNN,RNN 等,都需要使用张量来进行数据的存储和计算。
张量 → \to → 存储同一类型元素的容器,且元素值必须是数值才可以。
基本创建方法
torch.tensor()
根据指定的数据创建张量
import torch
import numpy as np
# 1. 定义函数,演示:torch.tensor() -> 根据指定的数据创建张量
def demo01():
# 场景1:标量 张量
t1 = torch.tensor(10)
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# 场景2:向量 张量
t2 = torch.tensor([1, 2, 3])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# 场景3:矩阵 张量
t3 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(f"t3: {t3},type:{type(t3)}")
print("-" * 30)
# 场景4:numpy 数组 -> 张量
t4 = torch.tensor(
np.random.randint(0, 10, size=(2, 3)),
# 指定张量的数据类型为 float32
dtype=torch.float32)
print(f"t4: {t4},type:{type(t4)}")
print("-" * 30)
输出结果如下:
t1: 10,type:<class 'torch.Tensor'>
------------------------------
t2: tensor([1, 2, 3]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[1, 2, 3],
[4, 5, 6]]),type:<class 'torch.Tensor'>
------------------------------
t4: tensor([[5., 9., 1.],
[8., 0., 9.]]),type:<class 'torch.Tensor'>
------------------------------
当尝试直接创建指定维度张量(例如:2 行 3 列)时:
场景5:尝试直接创建指定维度张量(例如:2行3列)
t5 = torch.tensor(2, 3)
print(f"t5: {t5},type:{type(t5)}")
print("-" * 30)
程序会报错:
Traceback (most recent call last):
File "/Users/PycharmProjects/DL_learn/day01/01_张量的基本创建方式.py", line 46, in <module>
demo01()
File "/Users/PycharmProjects/DL_learn/day01/01_张量的基本创建方式.py", line 35, in demo01
t5 = torch.tensor(2, 3)
^^^^^^^^^^^^^^^^^^
TypeError: tensor() takes 1 positional argument but 2 were given
tensor 的函数签名如下:
def tensor(data: Any, # 这是唯一的必需参数,用于提供创建张量的数据
dtype: dtype | None = None, # 指定所创建张量的数据类型
device: str | device | int | None = None, # 指定张量存储的设备(CPU 或 GPU)
requires_grad: bool = False, # 指定张量是否需要计算梯度,这是实现自动求导(Autograd)的关键开关
pin_memory: bool = False) -> Tensor # 如果为 True,张量的数据将被分配到 “锁定内存”(pinned memory)中,这在使用 GPU 时可以加速数据从 CPU 到 GPU 的传输
所以当尝试指定维度时,参数传递有问题,程序报错。
torch.Tensor()
根据形状创建张量,其也可以根据指定的数据创建张量
# 2. 定义函数,演示:torch.Tensor() -> 根据形状创建张量,其也可以根据指定的数据创建张量
def demo02():
# 场景1:标量 张量
t1 = torch.Tensor(10)
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# 场景2:向量 张量
t2 = torch.Tensor([1, 2, 3])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# 场景3:矩阵 张量
t3 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
print(f"t3: {t3},type:{type(t3)}")
print("-" * 30)
# 场景4:numpy 数组 -> 张量
t4 = torch.Tensor(np.random.randint(0, 10, size=(2, 3)))
# Tensor 不能直接指定数据类型,只能根据 numpy 数组的 dtype 来确定
print(f"t4: {t4},type:{type(t4)}")
print("-" * 30)
# 场景5:尝试直接创建指定维度张量(例如:2行3列)
t5 = torch.Tensor(2, 3)
print(f"t5: {t5},type:{type(t5)}")
print("-" * 30)
输出结果如下:
t1: tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([1., 2., 3.]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[1., 2., 3.],
[4., 5., 6.]]),type:<class 'torch.Tensor'>
------------------------------
t4: tensor([[1., 6., 7.],
[9., 4., 5.]]),type:<class 'torch.Tensor'>
------------------------------
t5: tensor([[0., 0., 0.],
[0., 0., 0.]]),type:<class 'torch.Tensor'>
------------------------------
Tensor 较于 tensor 可以基于形状创建张量,而 tensor 只能基于指定的数据创建张量。
torch.IntTensor()
根据指定的数据创建张量,且指定张量的数据类型(还有 torch.FloatTensor()、torch.DoubleTensor())
# 3. 定义函数,演示:torch.IntTensor() -> 根据指定的数据创建张量,且指定张量的数据类型
def demo03():
# 场景1:标量 张量
t1 = torch.IntTensor(10)
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# 场景2:向量 张量
t2 = torch.IntTensor([1, 2, 3])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# 场景3:矩阵 张量
t3 = torch.IntTensor([[1, 2, 3], [4, 5, 6]])
print(f"t3: {t3},type:{type(t3)}")
print("-" * 30)
# 场景4:numpy 数组 -> 张量
t4 = torch.IntTensor(np.random.randint(0, 10, size=(2, 3)))
print(f"t4: {t4},type:{type(t4)}")
print("-" * 30)
# 场景5:如果类型不匹配,会尝试自动转换
t5 = torch.IntTensor([1, 2, 3.0])
print(f"t5: {t5},type:{type(t5)}")
print("-" * 30)
输出结果如下:
t1: tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=torch.int32),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([1, 2, 3], dtype=torch.int32),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[1, 2, 3],
[4, 5, 6]], dtype=torch.int32),type:<class 'torch.Tensor'>
------------------------------
t4: tensor([[0, 3, 2],
[9, 5, 9]], dtype=torch.int32),type:<class 'torch.Tensor'>
------------------------------
t5: tensor([1, 2, 3], dtype=torch.int32),type:<class 'torch.Tensor'>
------------------------------
张量的数据类型:
在 torch 中 CPU 和 GPU 张量分别有 8 种数据类型
| 数据类型 | dtype | CPU tensor | GPU tensor |
|---|---|---|---|
| 32-bit floating point | torch.float32 or torch.float | torch.FloatTensor | torch.cuda.FloatTensor |
| 64-bit floating point | torch.float64 or torch.double | torch.DoubleTensor | torch.cuda.DoubleTensor |
| 16-bit floating point | torch.float16 or torch.half | torch.HalfTensor | torch.cuda.HalfTensor |
| 8-bit integer (unsigned) | torch.uint8 | torch.ByteTensor | torch.cuda.ByteTensor |
| 8-bit integer (signed) | torch.int8 | torch.CharTensor | torch.cuda.CharTensor |
| 16-bit integer (signed) | torch.int16 or torch.short | torch.ShortTensor | torch.cuda.ShortTensor |
| 32-bit integer (signed) | torch.int32 or torch.int | torch.IntTensor | torch.cuda.IntTensor |
张量中默认的数据类型是 float32(torch.FloatTensor)
创建全 0 / 1 / 指定值张量
创建全 0 张量
torch.zeros() 和 torch.zeros_like()
# 场景:torch.zeros() 和 torch.zeros_like() -> 创建全0张量
t1 = torch.zeros(2, 3) # 创建2行3列的全0张量
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# t2: 3行2列
t2 = torch.tensor([[1, 2], [3, 4], [5, 6]])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# t3 -> 基于t2的形状创建全0张量
t3 = torch.zeros_like(t2)
print(f"t3: {t3},type:{type(t3)}")
print("*" * 30)
输出结果如下:
t1: tensor([[0., 0., 0.],
[0., 0., 0.]]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([[1, 2],
[3, 4],
[5, 6]]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[0, 0],
[0, 0],
[0, 0]]),type:<class 'torch.Tensor'>
******************************
创建全 1 张量
torch.ones() 和 torch.ones_like()
# 场景:torch.ones() 和 torch.ones_like() -> 创建全1张量
t1 = torch.ones(2, 3) # 创建2行3列的全1张量
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# t2: 3行2列
t2 = torch.tensor([[1, 2], [3, 4], [5, 6]])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# t3 -> 基于t2的形状创建全1张量
t3 = torch.ones_like(t2)
print(f"t3: {t3},type:{type(t3)}")
print("*" * 30)
输出结果如下:
t1: tensor([[1., 1., 1.],
[1., 1., 1.]]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([[1, 2],
[3, 4],
[5, 6]]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[1, 1],
[1, 1],
[1, 1]]),type:<class 'torch.Tensor'>
******************************
创建全指定值张量
torch.full() 和 torch.full_like()
# 场景:torch.full() 和 torch.full_like() -> 创建指定值张量
t1 = torch.full(size=(2, 3), fill_value=10) # 创建2行3列的全10张量
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# t2: 3行2列
t2 = torch.tensor([[1, 2], [3, 4], [5, 6]])
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# t3 -> 基于t2的形状创建全10张量
t3 = torch.full_like(t2, 10)
print(f"t3: {t3},type:{type(t3)}")
print("*" * 30)
输出结果如下:
t1: tensor([[10, 10, 10],
[10, 10, 10]]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([[1, 2],
[3, 4],
[5, 6]]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[10, 10],
[10, 10],
[10, 10]]),type:<class 'torch.Tensor'>
******************************
注意事项:
-
torch.full()的size参数格式- 代码中
torch.full(size=(2, 3), fill_value=10)使用了元组(2, 3)作为size参数,这是推荐写法。 - 注意:
size必须是整数序列(元组、列表等),不能直接写size=2, 3(会报参数不匹配错误)。 - 错误示例:
torch.full(2, 3, fill_value=10)→ 会把2当size,3当fill_value,导致形状错误。
- 代码中
-
张量的数据类型推断
-
torch.full()会根据fill_value的类型推断张量 dtype:- 代码中
fill_value=10是整数 → 张量 dtype 默认为torch.int64(PyTorch 中整数默认 int64)。 - 若
fill_value是浮点数(如10.0)→ dtype 默认为torch.float32(默认浮点类型)。
- 代码中
-
若需显式指定 dtype,需加
dtype参数:t1 = torch.full(size=(2, 3), fill_value=10, dtype=torch.float32) # 强制为float32
-
-
torch.full_like()的继承特性-
torch.full_like(input, fill_value)会完全继承输入张量input的形状、dtype 和设备:-
代码中
t2是torch.int64类型(从列表[[1,2],...]推断),因此t3的 dtype 也是torch.int64,形状与t2一致(3 行 2 列)。 -
若
t2在 GPU 上,t3会自动创建在相同 GPU 上(无需额外指定device),示例:t2 = torch.tensor([[1,2],[3,4]], device="cuda:0") # GPU上的张量 t3 = torch.full_like(t2, 10) # t3 也在 cuda:0 上
-
-
-
fill_value与 dtype 的兼容性- 若
fill_value的类型与目标 dtype 不匹配,会发生隐式转换(可能丢失精度):- 例:用
fill_value=10.5填充int64类型张量 → 小数部分被截断(结果为10)。 - 例:用
fill_value=10填充float32张量 → 自动转为10.0(安全转换)。
- 例:用
- 建议:
fill_value类型与目标 dtype 保持一致,避免意外截断。
- 若
torch.full():通过指定形状 + 填充值创建张量,需注意size格式和 dtype 推断。
torch.full_like():通过继承已有张量的形状 /dtype/ 设备创建张量,适合快速复用张量属性的场景。
创建线性和随机张量
创建线性张量
torch.arange() 和 torch.linspace()
# 定义函数,演示:创建线性张量
def demo01():
# 场景1:创建指定范围的线性张量
t1 = torch.arange(0, 10, 2) # 创建0-10之间的偶数张量,包含0不包含10
"""
参数:
start: 序列的起始值(包含在序列中)
end: 序列的结束值(不包含在序列中)
step: 序列中每个元素之间的步长(默认值为1)
"""
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# 场景2:创建指定范围的线性张量 -> 等差数列
t2 = torch.linspace(0, 10, 5) # 创建0-10之间的5个点的等差数列张量
"""
参数:
start: 序列的起始值(包含在序列中)
end: 序列的结束值(包含在序列中)
steps: 序列中元素的个数
"""
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
输出结果如下:
t1: tensor([0, 2, 4, 6, 8]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([ 0.0000, 2.5000, 5.0000, 7.5000, 10.0000]),type:<class 'torch.Tensor'>
------------------------------
创建随机张量
torch.random.initial_seed() 和 torch.random.manual_seed() → \to → 初始化随机种子
torch.rand() 和 torch.randn() → \to → 创建随机浮点类型张量
torch.randint(low, high, size) → \to → 创建随机整数类型张量
# 定义函数,演示:创建随机张量
def demo02():
# step1:设置随机种子
# torch.initial_seed() # 默认采用当前系统的时间戳作为随机种子
# print(f"当前的随机种子: {torch.initial_seed()}") # 每次都不一样
torch.manual_seed(100) # 手动设置随机种子为100
# 设置一次随机种子后,后续的随机操作都将基于该种子
print(f"当前的随机种子: {torch.initial_seed()}")
# step2:创建随机张量
# 场景1: 均匀分布的(0,1)随机张量
t1 = torch.rand(2, 3) # 创建2行3列的随机浮点类型张量
print(f"t1: {t1},type:{type(t1)}")
print("-" * 30)
# 场景2: 标准正态分布的随机张量
t2 = torch.randn(2, 3) # 创建2行3列的随机浮点类型张量
print(f"t2: {t2},type:{type(t2)}")
print("-" * 30)
# 场景3: 随机整数张量
t3 = torch.randint(low=0, high=10, size=(2, 3)) # 创建2行3列的随机整数类型张量,范围[0, 10)
print(f"t3: {t3},type:{type(t3)}")
print("-" * 30)
输出结果如下:
当前的随机种子: 100
t1: tensor([[0.1117, 0.8158, 0.2626],
[0.4839, 0.6765, 0.7539]]),type:<class 'torch.Tensor'>
------------------------------
t2: tensor([[ 1.1869, 0.8798, 1.5180],
[-0.2546, -1.5478, 2.2337]]),type:<class 'torch.Tensor'>
------------------------------
t3: tensor([[4, 3, 8],
[7, 4, 6]]),type:<class 'torch.Tensor'>
------------------------------
张量的类型转换
data.type(torch支持的数据类型)
data.half()/float()/double()/short()/int()/long()
import torch
# 场景1:直接创建指定类型的张量
t1 = torch.tensor([1, 2, 3], dtype=torch.float) # 默认是torch.float32
print(f"t1: {t1},元素类型:{t1.dtype},张量类型:{type(t1)}")
print("-" * 30)
# 场景2:将已有张量转换为指定类型
t2 = t1.type(torch.int32) # 将t1转换为torch.int32类型
print(f"t2: {t2},元素类型:{t2.dtype},张量类型:{type(t2)}")
print("-" * 30)
print(t2.half()) # 转换为torch.float16类型
print(t2.float()) # 转换为torch.float32类型,默认是torch.float32
print(t2.double()) # 转换为torch.float64类型
print(t2.short()) # 转换为torch.int16类型
print(t2.int()) # 转换为torch.int32类型
print(t2.long()) # 转换为torch.int64类型,默认是torch.int64
输出结果如下:
t1: tensor([1., 2., 3.]),元素类型:torch.float32,张量类型:<class 'torch.Tensor'>
------------------------------
t2: tensor([1, 2, 3], dtype=torch.int32),元素类型:torch.int32,张量类型:<class 'torch.Tensor'>
------------------------------
tensor([1., 2., 3.], dtype=torch.float16)
tensor([1., 2., 3.])
tensor([1., 2., 3.], dtype=torch.float64)
tensor([1, 2, 3], dtype=torch.int16)
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3])
张量的转换
张量转换为 Numpy 数组
张量.numpy() → \to → 共享内存(浅拷贝)
张量.numpy().copy() → \to → 不共享内存(深拷贝)
# 1. 定义函数,演示:张量 -> numpy ndarray对象
def demo01():
# 1. 创建张量
t1 = torch.tensor([1, 2, 3, 4, 5])
print(f"t1: {t1},type:{type(t1)}")
# 2. 张量 -> numpy ndarray对象
# 2.1 共享内存(浅拷贝)
ndarray1 = t1.numpy()
print(f"ndarray1: {ndarray1},type:{type(ndarray1)}")
# 演示上述方式为共享内存
ndarray1[0] = 100
print(f"ndarray1: {ndarray1}")
print(f"t1: {t1}")
# 2.2 不共享内存(深拷贝)
ndarray2 = t1.numpy().copy()
print(f"ndarray2: {ndarray2},type:{type(ndarray2)}")
# 演示上述方式为不共享内存
ndarray2[0] = 200
print(f"ndarray2: {ndarray2}")
print(f"t1: {t1}")
输出结果如下:
t1: tensor([1, 2, 3, 4, 5]),type:<class 'torch.Tensor'>
ndarray1: [1 2 3 4 5],type:<class 'numpy.ndarray'>
ndarray1: [100 2 3 4 5]
t1: tensor([100, 2, 3, 4, 5])
ndarray2: [100 2 3 4 5],type:<class 'numpy.ndarray'>
ndarray2: [200 2 3 4 5]
t1: tensor([100, 2, 3, 4, 5])
Numpy 数组转换为张量
torch.from_numpy(ndarray) → \to → 共享内存(浅拷贝)
torch.tensor(ndarray) → \to → 不共享内存(深拷贝)
# 2. 定义函数,演示:numpy ndarray对象 -> 张量
def demo02():
# 1. 创建 numpy ndarray 对象
ndarray1 = np.array([1, 2, 3, 4, 5])
print(f"ndarray1: {ndarray1},type:{type(ndarray1)}")
# 2. numpy ndarray对象 -> 张量
# 2.1 共享内存(浅拷贝)
t1 = torch.from_numpy(ndarray1)
print(f"t1: {t1},type:{type(t1)}")
# 演示上述方式为共享内存
t1[0] = 100
print(f"t1: {t1}")
print(f"ndarray1: {ndarray1}")
# 2.2 不共享内存(深拷贝)
t2 = torch.tensor(ndarray1)
print(f"t2: {t2},type:{type(t2)}")
# 演示上述方式为不共享内存
t2[0] = 200
print(f"t2: {t2}")
print(f"ndarray1: {ndarray1}")
输出结果如下:
ndarray1: [1 2 3 4 5],type:<class 'numpy.ndarray'>
t1: tensor([1, 2, 3, 4, 5]),type:<class 'torch.Tensor'>
t1: tensor([100, 2, 3, 4, 5])
ndarray1: [100 2 3 4 5]
t2: tensor([100, 2, 3, 4, 5]),type:<class 'torch.Tensor'>
t2: tensor([200, 2, 3, 4, 5])
ndarray1: [100 2 3 4 5]
从标量张量中提取其内容
标量张量.item() 只能是标量张量
# 3. 定义函数,演示:从标量张量中提取其内容
def demo03():
# 1. 创建标量张量
t1 = torch.tensor(10)
print(f"t1: {t1},type:{type(t1)}")
# 2. 从标量张量中提取其内容
scalar = t1.item()
print(f"scalar: {scalar},type:{type(scalar)}")
输出结果如下:
t1: 10,type:<class 'torch.Tensor'>
scalar: 10,type:<class 'int'>
张量的运算
张量的基本运算
add(), sub(), mul(), div(), neg() → \to → 加、减、乘、除、取反add_(), sub_(), mul_(), div_(), neg_() → \to → 加、减、乘、除、取反,可以修改源数据,类似于 Pandas 中的 inplace=True
import torch
# 1. 创建张量
t1 = torch.tensor([10, 20, 30], dtype=torch.float)
print(f"t1: {t1}")
# 2. 演示张量的基本运算
# 2.1 加
print("*" * 30)
t2 = t1.add(10) # 不会修改源数据
print(f"t2: {t2}")
t2 = t1 + 10
print(f"t2: {t2}")
print("-" * 30)
t2 = t1.add_(10) # 会修改源数据
print(f"t2: {t2}")
print(f"t1: {t1}") # 源数据被修改了
t1 += 10
print(f"t1: {t1}")
print("*" * 30)
# 2.2 减
print("*" * 30)
t2 = t1.sub(10) # 不会修改源数据
print(f"t2: {t2}")
t2 = t1 - 10
print(f"t2: {t2}")
print("-" * 30)
t2 = t1.sub_(10) # 会修改源数据
print(f"t2: {t2}")
print(f"t1: {t1}") # 源数据被修改了
t1 -= 10
print(f"t1: {t1}")
print("*" * 30)
# 2.3 乘
print("*" * 30)
t2 = t1.mul(10) # 不会修改源数据
print(f"t2: {t2}")
t2 = t1 * 10
print(f"t2: {t2}")
print("-" * 30)
t2 = t1.mul_(10) # 会修改源数据
print(f"t2: {t2}")
print(f"t1: {t1}") # 源数据被修改了
t1 *= 10
print(f"t1: {t1}")
print("*" * 30)
# 2.4 除
print("*" * 30)
t2 = t1.div(10) # 不会修改源数据
print(f"t2: {t2}")
t2 = t1 / 10
print(f"t2: {t2}")
print("-" * 30)
t2 = t1.div_(10) # 会修改源数据
print(f"t2: {t2}")
print(f"t1: {t1}") # 源数据被修改了
t1 /= 10
print(f"t1: {t1}")
print("*" * 30)
# 2.5 取反
print("*" * 30)
t2 = t1.neg() # 不会修改源数据
print(f"t2: {t2}")
t2 = -t1
print(f"t2: {t2}")
print("-" * 30)
t2 = t1.neg_() # 会修改源数据
print(f"t2: {t2}")
print(f"t1: {t1}") # 源数据被修改了
t1 = -t1
print(f"t1: {t1}")
print("*" * 30)
输出结果如下:
t1: tensor([10., 20., 30.])
******************************
t2: tensor([20., 30., 40.])
t2: tensor([20., 30., 40.])
------------------------------
t2: tensor([20., 30., 40.])
t1: tensor([20., 30., 40.])
t1: tensor([30., 40., 50.])
******************************
******************************
t2: tensor([20., 30., 40.])
t2: tensor([20., 30., 40.])
------------------------------
t2: tensor([20., 30., 40.])
t1: tensor([20., 30., 40.])
t1: tensor([10., 20., 30.])
******************************
******************************
t2: tensor([100., 200., 300.])
t2: tensor([100., 200., 300.])
------------------------------
t2: tensor([100., 200., 300.])
t1: tensor([100., 200., 300.])
t1: tensor([1000., 2000., 3000.])
******************************
******************************
t2: tensor([100., 200., 300.])
t2: tensor([100., 200., 300.])
------------------------------
t2: tensor([100., 200., 300.])
t1: tensor([100., 200., 300.])
t1: tensor([10., 20., 30.])
******************************
******************************
t2: tensor([-10., -20., -30.])
t2: tensor([-10., -20., -30.])
------------------------------
t2: tensor([-10., -20., -30.])
t1: tensor([-10., -20., -30.])
t1: tensor([10., 20., 30.])
******************************
- 可以用
+、-、*、/、+=、-=、*=、/=来代替函数进行基本运算- 如果是张量和数值运算,则该数值会和张量中的每个值依次进行对应运算
点乘运算和矩阵运算
点乘运算
点乘指的是相同形状的张量对应位置的元素相乘,使用 mul() 和运算符 * 实现
例如: A = [ 1 2 3 4 ] , B = [ 5 6 7 8 ] A =\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} ,B=\begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} A=[1324],B=[5768]
则 A A A 和 B B B 的点乘运算为:
A ⋅ B = [ 1 × 5 2 × 6 3 × 7 4 × 8 ] = [ 5 12 21 32 ] A \cdot B=\begin{bmatrix} 1 \times 5 & 2 \times 6 \\ 3 \times 7 & 4 \times 8 \end{bmatrix}=\begin{bmatrix} 5 & 12 \\ 21 & 32 \end{bmatrix} A⋅B=[1×53×72×64×8]=[5211232]
# 1. 定义函数,演示张量点乘
def demo01():
# 1. 定义张量:2行3列
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(f"t1: {t1}")
# 2. 定义张量:2行3列
t2 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(f"t2: {t2}")
# 3. 演示点乘
t3 = t1 * t2
print(f"t3: {t3}")
t3 = t1.mul(t2)
print(f"t3: {t3}")
输出结果如下:
t1: tensor([[1, 2, 3],
[4, 5, 6]])
t2: tensor([[1, 2, 3],
[4, 5, 6]])
t3: tensor([[ 1, 4, 9],
[16, 25, 36]])
t3: tensor([[ 1, 4, 9],
[16, 25, 36]])
矩阵运算
矩阵乘法运算要求第一个矩阵 shape:(n, m),第二个矩阵 shape:(m, p),两个矩阵点积运算 shape 为:(n, p)
- 运算符
@用于进行两个矩阵的乘积运算 torch.matmul对进行乘积运算的两个矩阵形状没有限定。对于输入的 shape 不同的张量,对应的最后几个维度必须符合矩阵运算规则
# 2. 定义函数,演示矩阵运算
def demo02():
# 1. 定义张量:2行3列
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(f"t1: {t1}")
# 2. 定义张量:3行2列
t2 = torch.tensor([[1, 2], [3, 4], [5, 6]])
print(f"t2: {t2}")
# 3. 演示矩阵运算
t3 = t1 @ t2
print(f"t3: {t3}")
t3 = t1.matmul(t2)
print(f"t3: {t3}")
输出结果如下:
t1: tensor([[1, 2, 3],
[4, 5, 6]])
t2: tensor([[1, 2],
[3, 4],
[5, 6]])
t3: tensor([[22, 28],
[49, 64]])
t3: tensor([[22, 28],
[49, 64]])
张量运算函数
sum(), max(), min(), mean()
→ \to → 对张量进行求和、求最大值、求最小值、求平均值,都有 dim 参数,0表示按列运算,1表示按行运算pow(), sqrt(), exp(), log(), log2(), log10()
→ \to → 对张量进行幂运算、开方运算、指数运算、自然对数运算、以2为底的对数运算、以10为底的对数运算,没有 dim 参数
import torch
# 1. 定义张量,记录初值
t1 = torch.tensor([
[1, 2, 3],
[4, 5, 6]],
dtype=torch.float)
print(f"t1: {t1}")
# 2. 演示有 dim 参数的函数
# 2.1 演示 sum() 函数
print(f"t1.sum(): {t1.sum()}") # 对所有元素求和
print(f"t1.sum(dim=0): {t1.sum(dim=0)}") # 对每列元素求和
print(f"t1.sum(dim=1): {t1.sum(dim=1)}") # 对每行元素求和
print("-" * 30)
# 2.2 演示 max() 函数
print(f"t1.max(): {t1.max()}") # 对所有元素求最大值
print(f"t1.max(dim=0): {t1.max(dim=0)}") # 对每列元素求最大值
print(f"t1.max(dim=1): {t1.max(dim=1)}") # 对每行元素求最大值
print("-" * 30)
# 2.3 演示 min() 函数
print(f"t1.min(): {t1.min()}") # 对所有元素求最小值
print(f"t1.min(dim=0): {t1.min(dim=0)}") # 对每列元素求最小值
print(f"t1.min(dim=1): {t1.min(dim=1)}") # 对每行元素求最小值
print("-" * 30)
# 2.4 演示 mean() 函数
print(f"t1.mean(): {t1.mean()}") # 对所有元素求平均值
print(f"t1.mean(dim=0): {t1.mean(dim=0)}") # 对每列元素求平均值
print(f"t1.mean(dim=1): {t1.mean(dim=1)}") # 对每行元素求平均值
print("*" * 30)
# 3. 演示无 dim 参数的函数
# 3.1 演示 pow() 函数
print(f"t1.pow(2): {t1.pow(2)}") # 对所有元素求平方
print(f"t1.pow(0.5): {t1.pow(0.5)}") # 对所有元素求平方根
print(f"t1.pow(3): {t1.pow(3)}") # 对所有元素求立方
print("-" * 30)
# 3.2 演示 sqrt() 函数
print(f"t1.sqrt(): {t1.sqrt()}") # 对所有元素求平方根
print("-" * 30)
# 3.3 演示 exp() 函数
print(f"t1.exp(): {t1.exp()}") # 对所有元素求指数
print("-" * 30)
# 3.4 演示 log() 函数
print(f"t1.log(): {t1.log()}") # 对所有元素求自然对数
print("-" * 30)
# 3.5 演示 log2() 函数
print(f"t1.log2(): {t1.log2()}") # 对所有元素求以2为底的对数
print("-" * 30)
# 3.6 演示 log10() 函数
print(f"t1.log10(): {t1.log10()}") # 对所有元素求以10为底的对数
print("-" * 30)
输出结果如下:
t1: tensor([[1., 2., 3.],
[4., 5., 6.]])
t1.sum(): 21.0
t1.sum(dim=0): tensor([5., 7., 9.])
t1.sum(dim=1): tensor([ 6., 15.])
------------------------------
t1.max(): 6.0
t1.max(dim=0): torch.return_types.max(
values=tensor([4., 5., 6.]),
indices=tensor([1, 1, 1]))
t1.max(dim=1): torch.return_types.max(
values=tensor([3., 6.]),
indices=tensor([2, 2]))
------------------------------
t1.min(): 1.0
t1.min(dim=0): torch.return_types.min(
values=tensor([1., 2., 3.]),
indices=tensor([0, 0, 0]))
t1.min(dim=1): torch.return_types.min(
values=tensor([1., 4.]),
indices=tensor([0, 0]))
------------------------------
t1.mean(): 3.5
t1.mean(dim=0): tensor([2.5000, 3.5000, 4.5000])
t1.mean(dim=1): tensor([2., 5.])
******************************
t1.pow(2): tensor([[ 1., 4., 9.],
[16., 25., 36.]])
t1.pow(0.5): tensor([[1.0000, 1.4142, 1.7321],
[2.0000, 2.2361, 2.4495]])
t1.pow(3): tensor([[ 1., 8., 27.],
[ 64., 125., 216.]])
------------------------------
t1.sqrt(): tensor([[1.0000, 1.4142, 1.7321],
[2.0000, 2.2361, 2.4495]])
------------------------------
t1.exp(): tensor([[ 2.7183, 7.3891, 20.0855],
[ 54.5982, 148.4132, 403.4288]])
------------------------------
t1.log(): tensor([[0.0000, 0.6931, 1.0986],
[1.3863, 1.6094, 1.7918]])
------------------------------
t1.log2(): tensor([[0.0000, 1.0000, 1.5850],
[2.0000, 2.3219, 2.5850]])
------------------------------
t1.log10(): tensor([[0.0000, 0.3010, 0.4771],
[0.6021, 0.6990, 0.7782]])
------------------------------
张量的操作
索引操作
简单行列索引
import torch
# 1. 设置随机种子
torch.manual_seed(24)
# 2. 创建随机张量
t1 = torch.randint(1, 10, (5, 5))
print(f"t1: {t1}")
print("-" * 30)
# 3. 演示张量的索引操作
# 3.1 简单行列索引,张量对象[行, 列]
# 场景1: 获取第2行的数据
print(t1[1])
print(t1[1, :]) # 效果同上,":"表示所有列
# 场景2: 获取第3列的数据
print(t1[:, 2])
print("-" * 30)
输出结果如下:
t1: tensor([[6, 9, 9, 2, 8],
[7, 8, 5, 8, 4],
[7, 4, 3, 9, 3],
[6, 1, 4, 2, 8],
[1, 2, 5, 7, 4]])
------------------------------
tensor([7, 8, 5, 8, 4])
tensor([7, 8, 5, 8, 4])
tensor([9, 5, 3, 4, 5])
------------------------------
列表索引
# 3.2 列表索引,张量对象[[行列表], [列列表]]
# 场景1: 获取(0,1)和(1,2)位置上的元素
print(t1[[0, 1], [1, 2]])
# 场景2: 获取(1,2)和(3,4)位置上的元素
print(t1[[1, 3], [2, 4]])
# 场景3: 获取第1,2行的2,3列共4个元素
print(t1[[[0], [1]], [1, 2]])
# print(t1[[1, 2, 3], [1, 2]]),行列表和列列表长度必须相同,不然会报错
print("-" * 30)
输出结果如下:
tensor([9, 5])
tensor([5, 8])
tensor([[9, 9],
[8, 5]])
------------------------------
范围索引
# 3.3 范围索引
# 场景1: 获取前3行,前2列
print(t1[:3, :2])
# 场景2: 获取第2行到最后一行,前2列
print(t1[1:, :2])
# 场景3: 获取所有奇数行,偶数列
print(t1[::2, 1::2]) # 第1行到最后一行,每隔2行取1行,第0列到最后一列,每隔2列取1列
print("-" * 30)
输出结果如下:
tensor([[6, 9],
[7, 8],
[7, 4]])
tensor([[7, 8],
[7, 4],
[6, 1],
[1, 2]])
tensor([[9, 2],
[4, 9],
[2, 7]])
------------------------------
布尔索引
# 3.4 布尔索引
# 演示布尔写法
# print(t1[torch.tensor([True, False, True, False, True]), :])
# 场景1: 获取第3列大于5的行数据
# 理解1: 在第3列的基础上,找到该列中大于5的元素
print(t1[t1[:, 2]>5, 2])
# 理解2: 在第3列的基础上,找到该列中大于5的元素的行索引,返回该行的所有元素
print(t1[t1[:, 2]>5])
# 场景2: 获取第2行大于5的列数据
# 理解1: 在第2行基础上,找到该行中大于5的列索引,返回该列的所有元素
print(t1[1, t1[1, :]>5]) # print(t1[1, t1[1]>5])
# 理解2: 在第2行的基础上,找该行所有列中大于5的元素
print(t1[1, t1[1, :]>5]) # print(t1[1, t1[1]>5])
print("-" * 30)
输出结果如下:
tensor([9])
tensor([[6, 9, 9, 2, 8]])
tensor([7, 8, 8])
tensor([7, 8, 8])
------------------------------
多维索引
# 3.5 多维索引
# 创建3维张量:2个3行4列的张量
t2 = torch.randint(1, 10, (2, 3, 4))
# (2, 3, 4) 分别对应0轴、1轴、2轴
print(f"t2: {t2}")
# 需求1: 获取0轴上的第1个元素
print(t2[0, :, :]) # print(t2[0])
# 需求2: 获取1轴上的第1个元素
print(t2[:, 0, :]) # print(t2[:, 1])
# 需求3: 获取2轴上的第1个元素
print(t2[:, :, 0])
print("-" * 30)
输出结果如下:
t2: tensor([[[3, 4, 6, 5],
[8, 8, 8, 3],
[4, 9, 6, 7]],
[[2, 8, 8, 5],
[6, 4, 2, 2],
[2, 7, 9, 4]]])
tensor([[3, 4, 6, 5],
[8, 8, 8, 3],
[4, 9, 6, 7]])
tensor([[3, 4, 6, 5],
[2, 8, 8, 5]])
tensor([[3, 8, 4],
[2, 6, 2]])
------------------------------
0 轴、1 轴、2 轴解释:
[0轴,2个元素
[1轴,3个元素
[2轴,4个元素
3,
4,
6,
5],
[8, 8, 8, 3],
[4, 9, 6, 7]
],
[
[2, 8, 8, 5],
[6, 4, 2, 2],
[2, 7, 9, 4]
]
]
形状操作
reshape()
可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状。
import torch
torch.manual_seed(42)
# 定义函数,演示 reshape()def demo01():
# 1. 创建张量
t1 = torch.randint(1, 10, size = (2, 3))
print(f"t1: {t1}, shape: {t1.shape}, row: {t1.shape[0]}, col: {t1.shape[1]}, {t1.shape[-1]}")
# 2. 形状操作:reshape(),把t1->3行2列、1行6列、6行1列
t2 = t1.reshape(3, 2)
print(f"t2: {t2}, shape: {t2.shape}, row: {t2.shape[0]}, col: {t2.shape[1]}, {t2.shape[-1]}")
t2 = t1.reshape(1, 6)
print(f"t2: {t2}, shape: {t2.shape}, row: {t2.shape[0]}, col: {t2.shape[1]}, {t2.shape[-1]}")
t2 = t1.reshape(6, 1)
print(f"t2: {t2}, shape: {t2.shape}, row: {t2.shape[0]}, col: {t2.shape[1]}, {t2.shape[-1]}")
# 用reshape转换需要转换前与转换后的元素个数一致
输出结果如下:
t1: tensor([[7, 6, 8],
[5, 1, 3]]), shape: torch.Size([2, 3]), row: 2, col: 3, 3
t2: tensor([[7, 6],
[8, 5],
[1, 3]]), shape: torch.Size([3, 2]), row: 3, col: 2, 2
t2: tensor([[7, 6, 8, 5, 1, 3]]), shape: torch.Size([1, 6]), row: 1, col: 6, 6
t2: tensor([[7],
[6],
[8],
[5],
[1],
[3]]), shape: torch.Size([6, 1]), row: 6, col: 1, 1
squeeze()
删除形状为 1 的维度(降维)
# 定义函数,演示 squeeze()
def demo03():
# 定义2行3列的张量
t1 = torch.randint(1, 10, size=(2, 1, 3, 1, 1))
print(f"t1: {t1}, shape: {t1.shape}, row: {t1.shape[0]}, col: {t1.shape[1]}") # (2, 3)
t2 = t1.squeeze()
print(f"t2: {t2}, shape: {t2.shape}, row: {t2.shape[0]}, col: {t2.shape[1]}") # (2, 3)
输出结果如下:
t1: tensor([[[[[7]],
[[6]],
[[8]]]],
[[[[5]],
[[1]],
[[3]]]]]), shape: torch.Size([2, 1, 3, 1, 1]), row: 2, col: 1
t2: tensor([[7, 6, 8],
[5, 1, 3]]), shape: torch.Size([2, 3]), row: 2, col: 3
unsqueeze()
添加形状为 1 的维度(升维)
# 定义函数,演示 unsqueeze()
def demo02():
# 定义2行3列的张量
t1 = torch.randint(1, 10, size = (2, 3))
print(f"t1: {t1}, shape: {t1.shape}, row: {t1.shape[0]}, col: {t1.shape[1]}") # (2, 3)
# 在0维(轴)添加一个维度
t2 = t1.unsqueeze(0)
print(f"t2: {t2}, "
f"shape: {t2.shape}, "
f"row: {t2.shape[0]}, "
f"col: {t2.shape[1]}") # (1, 2, 3),在0维(最前面)添加一个维度,变成了“1个批次 × 2行 × 3列”的3维张量
# 在1维(轴)添加一个维度
t3 = t1.unsqueeze(1)
print(f"t3: {t3}, "
f"shape: {t3.shape}, "
f"row: {t3.shape[0]}, "
f"col: {t3.shape[1]}") # (2, 1, 3),在1维(行和列之间)添加一个维度,变成了“2个批次 × 1行 × 3列”的3维张量
# 在2维(轴)添加一个维度
t4 = t1.unsqueeze(2)
print(f"t4: {t4}, "
f"shape: {t4.shape}, "
f"row: {t4.shape[0]}, "
f"col: {t4.shape[1]}") # (2, 3, 1),在2维(最后面)添加一个维度,变成了“2个批次 × 3行 × 1列”的3维张量
输出结果如下:
t1: tensor([[7, 6, 8],
[5, 1, 3]]), shape: torch.Size([2, 3]), row: 2, col: 3
t2: tensor([[[7, 6, 8],
[5, 1, 3]]]), shape: torch.Size([1, 2, 3]), row: 1, col: 2
t3: tensor([[[7, 6, 8]],
[[5, 1, 3]]]), shape: torch.Size([2, 1, 3]), row: 2, col: 1
t4: tensor([[[7],
[6],
[8]],
[[5],
[1],
[3]]]), shape: torch.Size([2, 3, 1]), row: 2, col: 3
transpose()
可以实现交换张量形状的指定维度
# 定义函数,演示 transpose()
def demo04():
# 创建张量
t1 = torch.randint(1, 10, size=(2, 3, 4))
print(f"t1: {t1}, shape: {t1.shape}")
print("-" * 30)
# 改变维度从(2, 3, 4) -> (3, 2, 4)
t2 = t1.transpose(0, 1)
print(f"t1: {t1}, shape: {t1.shape}")
print(f"t2: {t2}, shape: {t2.shape}")
输出结果如下:
t1: tensor([[[7, 6, 8, 5],
[1, 3, 8, 6],
[5, 3, 5, 5]],
[[9, 1, 1, 5],
[3, 5, 4, 5],
[5, 9, 2, 6]]]), shape: torch.Size([2, 3, 4])
------------------------------
t1: tensor([[[7, 6, 8, 5],
[1, 3, 8, 6],
[5, 3, 5, 5]],
[[9, 1, 1, 5],
[3, 5, 4, 5],
[5, 9, 2, 6]]]), shape: torch.Size([2, 3, 4])
t2: tensor([[[7, 6, 8, 5],
[9, 1, 1, 5]],
[[1, 3, 8, 6],
[3, 5, 4, 5]],
[[5, 3, 5, 5],
[5, 9, 2, 6]]]), shape: torch.Size([3, 2, 4])
permute()
可以一次交换更多的维度
# 定义函数,演示 permute()
def demo05():
# 创建张量
t1 = torch.randint(1, 10, size=(2, 3, 4))
print(f"t1: {t1}, shape: {t1.shape}")
print("-" * 30)
# 改变维度从(2, 3, 4) -> (4, 3, 2)
t2 = t1.permute(2, 1, 0)
print(f"t1: {t1}, shape: {t1.shape}")
print(f"t2: {t2}, shape: {t2.shape}")
输出结果如下:
t1: tensor([[[7, 6, 8, 5],
[1, 3, 8, 6],
[5, 3, 5, 5]],
[[9, 1, 1, 5],
[3, 5, 4, 5],
[5, 9, 2, 6]]]), shape: torch.Size([2, 3, 4])
------------------------------
t1: tensor([[[7, 6, 8, 5],
[1, 3, 8, 6],
[5, 3, 5, 5]],
[[9, 1, 1, 5],
[3, 5, 4, 5],
[5, 9, 2, 6]]]), shape: torch.Size([2, 3, 4])
t2: tensor([[[7, 9],
[1, 3],
[5, 5]],
[[6, 1],
[3, 5],
[3, 9]],
[[8, 1],
[8, 4],
[5, 2]],
[[5, 5],
[6, 5],
[5, 6]]]), shape: torch.Size([4, 3, 2])
view()、contiguous()、is_contiguous()
view() 也可以用于修改张量的形状,只能用于修改连续的张量。在 PyTorch 中,有些张量的底层数据在内存中存储顺序与其在张量中的逻辑顺序不一致,view() 无法对这样的张量进行变形处理,例如:一个张量经过了 transpose() 或者 permute() 的处理之后,就无法使用 view() 进行形状操作。
# 定义函数,演示 view()、contiguous()、is_contiguous()
def demo06():
# 创建张量
t1 = torch.randint(1, 10, size=(2, 3))
print(f"t1: {t1}, shape: {t1.shape}")
# 判断张量是否连续,即张量中的顺序和内存中存储顺序是否一致
print(f"t1 是否连续: {t1.is_contiguous()}")
# 改变维度从(2, 3) -> (3, 2)
t2 = t1.view(3, 2)
print(f"t2: {t2}, shape: {t2.shape}")
# 判断张量是否连续,即张量中的顺序和内存中存储顺序是否一致
print(f"t2 是否连续: {t2.is_contiguous()}")
# 通过transpose()交换维度,从(2, 3) -> (3, 2)
t3 = t1.transpose(0, 1)
print(f"t3: {t3}, shape: {t3.shape}")
# 判断张量是否连续,即张量中的顺序和内存中存储顺序是否一致
print(f"t3 是否连续: {t3.is_contiguous()}")
# 尝试改变 t3 的维度从(3, 2) -> (2, 3)
# t4 = t3.view(2, 3)
# print(f"t4: {t4}, shape: {t4.shape}")
# # 判断张量是否连续,即张量中的顺序和内存中存储顺序是否一致
# print(f"t4 是否连续: {t4.is_contiguous()}")
# 报错:RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
# 通过contiguous()方法,将 t3 转换为连续张量
t3_contiguous = t3.contiguous()
print(f"t3_contiguous: {t3_contiguous}, shape: {t3_contiguous.shape}")
# 判断张量是否连续,即张量中的顺序和内存中存储顺序是否一致
print(f"t3_contiguous 是否连续: {t3_contiguous.is_contiguous()}")
输出结果如下:
t1: tensor([[7, 6, 8],
[5, 1, 3]]), shape: torch.Size([2, 3])
t1 是否连续: True
t2: tensor([[7, 6],
[8, 5],
[1, 3]]), shape: torch.Size([3, 2])
t2 是否连续: True
t3: tensor([[7, 5],
[6, 1],
[8, 3]]), shape: torch.Size([3, 2])
t3 是否连续: False
t3_contiguous: tensor([[7, 5],
[6, 1],
[8, 3]]), shape: torch.Size([3, 2])
t3_contiguous 是否连续: True
拼接操作
torch.cat()
可以将多个张量根据指定的维度拼接起来,不改变维度数,除了拼接的那个维度外,其它维度数必须保持一致
import torch
# 创建两个张量
t1 = torch.randint(1, 10, (2, 3))
print(f"t1: {t1}, shape: {t1.shape}")
t2 = torch.randint(1, 10, (2, 3))
print(f"t2: {t2}, shape: {t2.shape}")
# 演示张量拼接
t3 = torch.cat([t1, t2], dim=0)
print(f"t3: {t3}, shape: {t3.shape}")
输出结果如下:
t1: tensor([[2, 4, 7],
[4, 4, 8]]), shape: torch.Size([2, 3])
t2: tensor([[9, 3, 8],
[5, 4, 8]]), shape: torch.Size([2, 3])
t3: tensor([[2, 4, 7],
[4, 4, 8],
[9, 3, 8],
[5, 4, 8]]), shape: torch.Size([4, 3])
但是由于拼接的维度是 0,如果其他维度不一致就会报错:
t1 = torch.randint(1, 10, (2, 3))
print(f"t1: {t1}, shape: {t1.shape}")
t2 = torch.randint(1, 10, (2, 4))
print(f"t2: {t2}, shape: {t2.shape}")
报错:
RuntimeError: Sizes of tensors must match except in dimension 0. Expected size 3 but got size 4 for tensor number 1 in the list.
torch.stack()
会在一个新的维度上连续一系列张量,这会增加一个新维度,并且所有输入张量的形状必须完全相同
import torch
# 创建两个张量
t1 = torch.randint(1, 10, (2, 3))
print(f"t1: {t1}, shape: {t1.shape}")
t2 = torch.randint(1, 10, (2, 3))
print(f"t2: {t2}, shape: {t2.shape}")
# 演示张量拼接
t3 = torch.stack([t1, t2], dim=0) # (2, 3) + (2, 3) -> (2, 2, 3)
print(f"t3: {t3}, shape: {t3.shape}")
t3 = torch.stack([t1, t2], dim=1) # (2, 3) + (2, 3) -> (2, 2, 3)
print(f"t3: {t3}, shape: {t3.shape}")
t3 = torch.stack([t1, t2], dim=2) # (2, 3) + (2, 3) -> (2, 3, 2)
print(f"t3: {t3}, shape: {t3.shape}")
输出结果如下:
t1: tensor([[5, 5, 3],
[6, 9, 9]]), shape: torch.Size([2, 3])
t2: tensor([[4, 3, 7],
[8, 9, 4]]), shape: torch.Size([2, 3])
t3: tensor([[[5, 5, 3],
[6, 9, 9]],
[[4, 3, 7],
[8, 9, 4]]]), shape: torch.Size([2, 2, 3])
t3: tensor([[[5, 5, 3],
[4, 3, 7]],
[[6, 9, 9],
[8, 9, 4]]]), shape: torch.Size([2, 2, 3])
t3: tensor([[[5, 4],
[5, 3],
[3, 7]],
[[6, 8],
[9, 9],
[9, 4]]]), shape: torch.Size([2, 3, 2])
更多推荐
所有评论(0)