数学中指的是多维数组;
torch.Tensor
data: 被封装的 Tensor
dtype: 张量的数据类型
shape: 张量的形状
device: 张量所在的设备,GPU/CPU
requires_grad: 指示是否需要计算梯度
grad: data 的梯度
grad_fn: 创建 Tensor 的 Function,是自动求导的关键
is_leaf: 指示是否是叶子结点 (叶子结点指的是用户创建的节点,比如 y=(x+w)*(w+1)中,x和w就是叶子结点【可以用计算图来清楚地表示该过程】)
2.1.1 从 data 创建 tensor
data: 可以是 list, numpy
dtype: 数据类型,默认与data一致
device: 所在设备
requires_grad: 是否需要梯度
pin_memory: 是否存于锁页内存
# 创建方法
torch.tensor(
data,
dtype=None,
device=None,
requires_grad=False,
pin_memory=False
)
2.1.2 从 numpy 创建 tensor
用torch.from_numpy()
创建的tensor与原始的ndarray共享内存,修改其中一个,另一个也会变。
# 创建方法
torch.from_numpy(ndarray)
# 举例
import torch
import numpy as np
# 直接创建
## torch.tensor()
arr = np.ones((3,3))
t = torch.tensor(arr,
dtype=torch.float32,
device="mps") # 把张量放到 GPU 上 (mac M1)
print(t.dtype)
print(t)
## torch.from_numpy()
arr = np.array([[1,2,3],[4,5,6]])
t = torch.from_numpy(arr)
print(t.dtype)
print(t)
torch.float32
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], device='mps:0')
torch.int64
tensor([[1, 2, 3],
[4, 5, 6]])
2.2.1 torch.zeros()
创建全0张量
size: 张量的形状
out: 输出的张量 (暂时可以不考虑)
layout:内存中布局形式,有 strided (通常情况下使用), sparse_coo (读取稀疏矩阵会用到)
device: 所在设备
requires_grad: 是否需要梯度
# 创建方法
torch.zeros(
*size,
out=None,
dtype=None,
layout=torch.strided,
device=False,
requires_grad=False
)
2.2.2 torch.zeros_lisk()
根据 input 形状创建全0张量
input: 创建与 input 同形状的张量;
dtype: 数据类型;
layout: 内存中的布局形式;
# 创建方法
torch.zeros_like(
input,
dtype=None,
layout=None,
device=None,
requires_grad=False
)
2.2.3 torch.ones()
和 torch.ones_like()
创建全1张量
2.2.4 torch.full()
和torch.full_like()
创建自定义数值的张量
size: 张量形状
fill_value: 张量的值
2.2.5 torch.arange()
根据数列创建等差1维张量,[start, end)
start: 起始值
end: 结束值
step: 数列公差,默认为1
2.2.6torch.linspace()
创建均分的1维张量,[start, end]
start: 起始值
end: 结束值
step: 数列长度
2.2.7torch.logspace()
创建对数均分的1D张量
start: 起始值
end: 结束值
steps: 数列长度
base: 对数函数的底,默认为10
# 创建方法
torch.logspace(
start,
end,
steps=100,
base=10.0,
out=None,
dtype=None,
layout=torch.strided,
deivce=None,
requires_grad=False
)
2.2.8 torch.eye()
创建单位对角矩阵 (2D张量)
n: 矩阵行数
m: 矩阵列数
# 创建方法
torch.eye(
n,
m=None,
out=None,
dtype=None,
layout=torch.strided,
device=None,
requires_grad=False
)
# 举例
t = torch.zeros((3,3))
print(t.dtype)
print(t)
t = torch.full((3,3),2) # 创建3x3的全2张量
print(t)
t = torch.arange(2, 8, 2)
print(t)
t = torch.linspace(2, 10, 5)
print(t)
torch.float32
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
tensor([[2, 2, 2],
[2, 2, 2],
[2, 2, 2]])
tensor([2, 4, 6])
tensor([ 2., 4., 6., 8., 10.])
2.3.1 torch.normal()
生成正态分布(高斯分布)
四种模式:
mean | 标量 | std | 标量 |
mean | 标量 | std | 张量 |
mean | 张量 | std | 标量 |
mean | 张量 | std | 张量 |
# 张量
torch.normal(
mean,
std,
out=None
)
# 标量
torch.normal(
mean,
std,
size,
out=None
)
2.3.2 torch.randn()
, torch.randn_like()
生成标准正态分布
torch.randn(
*size, ## 张量形状
out=None,
dtype=None,
layout=torch.strided,
device=None,
requires_grad=False
)
2.3.3 torch.rand()
, torch.rand_like()
在[0,1)区间上生成均匀分布
torch.rand(
*size, ## 张量形状
out=None,
dtype=None,
layout=torch.strided,
device=None,
requires_grad=False
)
2.3.4 torch.randint()
, torch.randint_like()
在 [low, high) 区间上生成整数均匀分布
torch.randint(
low,
high,
size,
out=None,
dtype=None,
layout=torch.strided,
device=None,
requires_grad=False
)
2.3.5 torch.randperm()
生成0到n-1的随机排列
n: 张量长度
torch.randperm(
n,
out=None,
dtype=torch.int64,
layout=torch.strided,
device=None,
requires_grad=False
)
2.3.6torch.bernoulli()
以 input 为概率,生成伯努利分布(0-1分布,两点分布)
torch.bernoulli(
input,
*,
generator=None,
out=None
)
1.1 torch.cat()
将张量按维度 dim 进行拼接 (不回扩张张量维度)
torch.cat(
tensors, ## 张量序列
dim, ## 要拼接的维度
out=None
)
1.2 torch.stack()
在新创建的维度 dim 上进行拼接 (会扩张张量的维度)
torch.stack(
tensors, ## 张量序列
dim=0, ## 要拼接的维度
out=None
)
import torch
t = torch.ones((2,3))
# torch.cat()
t1 = torch.cat([t,t], dim=0) ## 按照 dim=0 对t进行拼接,得到(4,3)
# torch.stack()
t2 = torch.stack([t,t], dim=0) ## 按照 dim=0 对t进行拼接,得到(2,2,3),会在dim=0创建一个新维度
print("t1 shape: ", t1.shape)
print("t2 shape: ", t2.shape)
t1 shape: torch.Size([4, 3])
t2 shape: torch.Size([2, 2, 3])
2.1 torch.chunk()
将张量按照维度 dim 进行平均切分,返回张量列表 (如果不能整除,最后一份张量小于其他张量)
torch.chunk(
input, ## 要切分的张量
chunks, ## 要切分的份数
dim=0 ## 要切分的维度
)
2.2 torch.split()
将张量按照维度 dim 进行切分,返回张量列表
torch.split(
tensor, ## 要切分的张量
split_size_of_sections, ## 为 int 时,表示每一份的长度;为 list 时,按 list 元素切分
dim=0 ## 要切分的维度
)
t1 = torch.ones((2,5))
# torch.chunk()
list_of_tensors = torch.chunk(t1, dim=1, chunks=2) ## 5不能被2整除,所以最后一个张量形状小雨前面的张量
for idx, t in enumerate(list_of_tensors):
print("order {}, shape is {}".format(idx+1, t.shape))
# torch.split()
list_of_tensors = torch.split(t1, [2,1,2], dim=1)
for idx, t in enumerate(list_of_tensors):
print("order {}, shape is {}".format(idx+1, t.shape))
order 1, shape is torch.Size([2, 3])
order 2, shape is torch.Size([2, 2])
order 1, shape is torch.Size([2, 2])
order 2, shape is torch.Size([2, 1])
order 3, shape is torch.Size([2, 2])
3.1 torch.index_select()
在维度 dim 上,按照 index 索引数据,返回依index索引数据拼接的张量 (先索引,再拼接)
torch.index_select(
input, ## 要索引的张量
dim, ## 要索引的维度
index, ## 要索引数据的序号,数据类型必须是 torch.long
out=None
)
3.2 torch.masked_select()
按照 mask 中的 True 进行索引,返回一维张量
torch.masked_select(
input,
mask, ## 与 input 同形状的布尔类型张量
out=None
)
# torch_index_select()
t = torch.randint(0,9,size=(3,3))
idx = torch.tensor([0,2],dtype=torch.long)
t_select = torch.index_select(t, dim=1, index=idx)
print(t)
print(t_select)
# torch.masked_select()
mask = t.ge(5) ## 表示张量中 >= 5的元素;ge()表示大于等于;gt()表示大于;le()表示小于等于;lt()表示小于
t_select = torch.masked_select(t, mask=mask)
print(t)
print(mask)
print(t_select)
tensor([[3, 8, 1],
[6, 0, 0],
[7, 6, 8]])
tensor([[3, 1],
[6, 0],
[7, 8]])
tensor([[3, 8, 1],
[6, 0, 0],
[7, 6, 8]])
tensor([[False, True, False],
[ True, False, False],
[ True, True, True]])
tensor([8, 6, 7, 6, 8])
4.1 torch.reshape()
变换张量形状 (张量在内存中是连续时,新张量与input共享数据内存)
torch.reshape(
input,
shape ## 新张量的形状
)
4.2 torch.transpose()
交换张量的两个维度
torch.transpose(
input,
dim0,
dim1
)
4.3 torch.t()
2维张量转置
torch.t(input)
4.4 torch.squeeze()
压缩长度为1的维度
torch.squeeze(
input,
dim=None, ## 若 dim=None,则移除所有长度为1的轴;若指定维度而且维度长度为1,则可以移除该维度
out=None
)
4.5 torch.unsqueeze()
根据 dim 扩展维度
torch.unsqueeze(
input,
dim,
out=None
)
## torch.reshape
t = torch.randperm(8)
t_reshape = torch.reshape(t, (2,4)) ## 如果是 (-1,2,2),那么-1表示的是:不需要关心-1处的维度是多少,根据后两个维度进行计算得到(比如:这里就是 8/2/2 = 2,即-1处的维度是2)
print(t.shape)
print(t_reshape.shape)
## torch.transpose()
t = torch.rand((2,3,4))
t_transpose = torch.transpose(t, dim0=1, dim1=2) ## 把第1维和第2维进行交换
print(t.shape)
print(t_transpose.shape)
## torch.squeeze()
t = torch.rand((1,2,3,1))
t_squeeze = torch.squeeze(t)
t_squeeze_0 = torch.squeeze(t,dim=0)
t_squeeze_1 = torch.squeeze(t,dim=1)
print(t_squeeze.shape)
print(t_squeeze_0.shape)
print(t_squeeze_1.shape)
## torch.unsqueeze()
t = torch.rand((2,3))
t_unsqueeze = torch.unsqueeze(t, dim=2)
print(t_unsqueeze.shape)
torch.Size([8])
torch.Size([2, 4])
torch.Size([2, 3, 4])
torch.Size([2, 4, 3])
torch.Size([2, 3])
torch.Size([2, 3, 1])
torch.Size([1, 2, 3, 1])
torch.Size([2, 3, 1])
torch.add()
torch.addcdiv()
torch.addcmul()
torch.sub()
torch.div()
torch.mul()
重点: torch.add()
和torch.addcmul()
torch.add()
: 逐元素计算 input + alpha x other
torch.add(
input, ## 第一个张量
alpha=1, ## 乘项因子 (alpha x other + input)
other, ## 第二个张量
out=None
)
torch.addcmul()
out = input + value x tensor1 x tensor2
torch.addcmul(
input,
value=1.
tensor1,
tensor2,
out=None
)
torch.log(input, out=None)
torch.log10(input, out=None)
torch.log2(input, out=None)
torch.exp(input, out=None)
torch.pow()
torch.abs(input, out=None)
torch.acos(input, out=None)
torch.cosh(input, out=None)
torch.cos(input, out=None)
torch.asin(input, out=None)
torch.atan(input, out=None)
torch.atan2(input, other=None, out=None)
计算图是用来描述运算的有向无环图,包括两个主要元素:节点和边。节点表示数据(比如 向量、矩阵、张量);边表示运算(比如 加减乘除卷积等)。
叶子结点:指的是由用户创建的节点,其他非叶子结点都是由叶子结点通过直接或间接的运算得到的。(之所以会有叶子结点的概念,是因为梯度反向传播结束后,只有叶子结点的梯度会被保留,非叶子结点的梯度会被从内存中释放掉。可以通过
.is_leaf()
方法查看是否为叶子结点)。
如果想要使用非叶子结点的梯度,实现方法是 在计算梯度之后,用
.retain_grad()
方法保存非叶子结点的梯度。
grad_fn
: 记录创建该张量(非叶子结点)时所用的方法,比如 y=a*b,那么 y.grad_fn =
计算图可以根据搭建方式的不同,分为:动态图 (运算与搭建同时进行,灵活,易调节,比如 pytorch) 和静态图 (先搭建,后运算,高效,不灵活,比如 tensorflow)。
autograd
torch.autograd.backward
自动计算图中各个结点的梯度
torch.autograd.backward(
tensors, ## 用于求导的张量(比如 loss)
grad_tensors=None, ## 多梯度权重
retain_grap=None, ## 保存计算图
create_graph=False ## 创建导数的计算图,同于高阶求导
)
torch.autograd.grad
求取梯度
torch.autograd.grad(
outputs, ## 用于求导的张量 (比如 loss)
inputs, ## 需要梯度的张量
grad_outputs=None, ## 多梯度权重
retain_graph=None, ## 保存计算图
create_graph=False ## 创建导数计算图,用于高阶求导
)
梯度不自动清零 (手动清零
.grad.zero_()
);依赖于叶子结点结点,requires_grad 默认为 True;
叶子结点不可执行 in-place,即叶子结点不能执行原位操作;
数据, 模型, 损失函数, 优化器, 迭代训练