官方文档

import torch

创建矩阵-创建Tensor

x = torch.empty(1, 3) 
y = torch.rand(2, 1) 
z = torch.tensor([[1, 3], [1,3]])
value = torch.eye(8).cuda()
value[1,1]  = 0
项目Value
Tensor(*sizes)基础构造函数
tensor(data,)构造函数
ones(*sizes)全1Tensor
zeros(*sizes)全0Tensor
eye(*sizes)对角线为1,其他为0
arange(s,e,step)从s到e,步长为step
linspace(s,e,steps)从s到e,均匀切分成steps份
rand/randn(*sizes)均匀/标准分布
normal(mean,std)/uniform(from,to)正态分布/均匀分布
randperm(m)随机排列
torch.sum(a,1)对输入的tensor数据的某一维度求和

Tensor加减与广播机制

x+y,torch.add(x,y),y.add_(x) 
x-y,torch.sub(x,y),x.sub_(y)
zz = torch.tensor([[1, 3],
                   [1, 3]])
aa = torch.tensor([2, 6])
cc = zz*aa
print(cc)# tensor([[ 2, 18],
         #         [ 2, 18]])
zz = torch.tensor([[1, 3], [1,3]])
aa = torch.tensor([[2], [6]])#torch.rand(2, 2)
cc = zz*aa
print(cc)# tensor([[ 2,  6],
         #         [ 6, 18]])
广播机制

当我们对两个形状不同的Tensor按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使 这两个Tensor形状相同后再按元素运算。例如
由于 x 和 y 分别是1行2列和3行1列的矩阵,如果要计算 x + y,那么 x 中第一行的2个元素被广播(复制) 到了第二行和第三行,而 y 中第一列的3个元素被广播(复制)到了第二列。如此,就可以对2个3行2列的矩 阵按元素相加。

import torch
x = torch.empty(1, 3) 
y = torch.rand(2, 1) 
print(torch.sub(x,y)) #tensor([[-0.6043, -0.6043, -0.6043],[-0.3644, -0.3644, -0.3644]])
print(x-y)            #tensor([[-1.8891e+26,  4.7122e-01, -1.3118e-01],[-1.8891e+26,  3.7813e-01, -2.2427e-01]])
print(x.sub_(y))      
#RuntimeError                              Traceback (most recent call last)
<ipython-input-6-dd2081808359> in <module>
      2 x = torch.empty(1, 3)
      3 y = torch.rand(2, 1)
----> 4 print(x.sub_(y))

RuntimeError: output with shape [1, 3] doesn't match the broadcast shape [2, 3]

import torch
P=torch.normal(mean=torch.full((3,2),0.0),std=torch.full((3,2),0.01))
Q=torch.normal(mean=torch.full((3,2),0.0),std=torch.full((3,2),0.01))
QT=Q.t()
print(torch.mm(P, QT))
#tensor([[ 5.4583e-05,  7.6017e-06, -1.8841e-04],
        [-1.0727e-04,  5.7370e-05,  2.3789e-04],
        [ 5.2739e-05, -3.2579e-05, -1.0894e-04]])
项目Value
trace : input.trace()对角线元素之和(矩阵的迹)
diag对角线元素
triu/tril矩阵的上三角/下三角,可指 定偏移量
mm/bmm矩阵乘法/batch 的矩阵乘法
addmm/addbmm/addmv/addr/baddbmm…矩阵运算
t : x.t()转置
dot/cross内积/外积
inverse求逆矩阵
svd奇异值分解
abs()按照元素求绝对值

矩阵乘法

反向传播求梯度,优化函数参更新

l.backward()就是用来执行求解梯度的过程,而optimizer.step()则是用来执行梯度下降进行权重参数更新的过程。
自动求梯度
每个Tensor都有一个.grad_fn属性,
若Tensor是通过某些运算得到的,则grad_fn正常返回,
若Tensor不是通过某些运算得到的,返回None

x = torch.ones(2, 2, requires_grad=True)
print(x) 
print(x.grad_fn) #None  
张量求导增加维数,为了简单,避免张量对张量求导
import torch
x = torch.ones(2, 2, requires_grad=True) 
𝑦 = 2*𝑥
𝑦.backward()
print(x.grad)
#RuntimeError: grad can be implicitly created only for scalar outputs
---------------grad只能为标量输出隐式创建
---------------backward只能被应用在一个标量上,也就是一个一维tensor
𝐲.𝐛𝐚𝐜𝐤𝐰𝐚𝐫𝐝(𝒘)的含义是:先计算𝐭𝐨𝐫𝐜𝐡.𝐬𝐮𝐦(𝒚 ∗ 𝒘),得到标量

∗ 用 来 对 t e n s o r 进 行 矩 阵 进 行 逐 元 素 相 乘 *用来对tensor进行矩阵进行逐元素相乘 tensor

import torch
x = torch.ones(2, 2, requires_grad=True) 
𝑦 = 2*𝑥
w=torch.ones(2, 2) 
𝑦.backward(w)
print(x.grad)#tensor([[2., 2.],[2., 2.]])

等价于:

import torch
x = torch.ones(2, 2, requires_grad=True) 
𝑦 = 2*𝑥
w=torch.ones(2, 2) 
z=𝐭𝐨𝐫𝐜𝐡.𝐬𝐮𝐦(y*w)
z.backward()
print(x.grad)#tensor([[2., 2.],[2., 2.]])

再测试一次:

import torch
x = torch.ones(2, 2, requires_grad=True) 
𝑦 = 2*𝑥
w=torch.eye(2, 2) 
𝑦.backward(w)
print(x.grad)#tensor([[2., 0.], [0., 2.]])

.detach()+with torch.no_grad()

PyTorch提供的autograd包能够根据输入和前 向传播过程自动构建计算图,并执行反向传播。Tensor是autograd包的核心类,如果将其属性.requires_grad设置为True,它将开始追踪(track)在其上 的所有操作(这样就可以利用链式法则进行梯度传播了)。完成计算后,可以调用.backward()来完成所有 梯度计算。此Tensor的梯度将累积到.grad属性中。
如果不想要被继续追踪,可以调用.detach()将其从追踪记录中分离出来,这样就可以防止将来的计算被追 踪,这样梯度就传不过去了。此外,还可以用with torch.no_grad()将不想被追踪的操作代码块包裹起来, 这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数 (requires_grad=True)的梯度。
Function是另外一个很重要的类。Tensor和Function互相结合就可以构建一个记录有整个计算过程的有向 无环图(DAG)。

正常的计算
import torch
x = torch.ones(1, 1, requires_grad=True) 
y1 = 𝑥*x  
y2 = 𝑥*x*x
𝑦3 = y1+y2
𝑦3.backward()
print(x.grad)
#tensor([[5.]])
 
.detach()实现
import torch
x = torch.ones(1, 1, requires_grad=True) 
y1 = 𝑥*x  
y2 = 𝑥*x*x
u=y2.detach() # 将 u =y2作为常数处理
𝑦3 = y1+u
𝑦3.backward()
print(x.grad)
#tensor([[2.]]) 
with torch.no_grad()实现
import torch
x = torch.ones(1, 1, requires_grad=True) 
y1 = 𝑥*x  
with torch.no_grad():
	y2 = 𝑥*x*x
𝑦3 = y1+y2
𝑦3.backward()
print(x.grad)
#tensor([[2.]])
 

y 2 y_2 y2 的定义是被torch.no_grad():包裹的,所以与 y 2 y_2 y2 有关的梯度是不会回传的,只有与 y 1 y_1 y1 有关的梯度才会回传,即 x 2 x^2 x2 x x x 的梯度。y2.requires_grad=False,所以不能调用 y2.backward()。

其他细节

1.得到一个元素张量里面的元素值:pytorch中.item()方法

2.Tensor和NumPy中的数组相互转换。

注意: 这两个函数所产生的Tensor和NumPy中的数组共享相同的内存
NumPy中:array转换成Tensor的方法torch.tensor(), 注意返回的Tensor和原来的数据“不共享”内存

# torch -> numpy
a = torch.ones(3) 
b = a.numpy() 
# numpy -> torch
a = np.ones(3) 
b = torch.from_numpy(a) # 共享
c = torch.tensor(a)     # 不共享

UserWarning: Using a target size (torch.Size([64])) that is different to the input size (torch.Size([64,1]))

x = x.squeeze(-1)
squeeze的作用就是对tensor变量进行维度压缩,去除维数为1的的维度。
☆存储的数据并没有发生变化,但是去除了“多余”的维度例如,一个3×2×1×2×1的tensor,squeeze()之后便成了3×2×2。

计算方差

torch.var(input, dim, keepdim=False, unbiased=True, out=None) → Tensor

参数:
input (Tensor) - 输入Tensor
dim (int) - 指定维度
keepdim (bool) - 输出张量是否保持与输入张量有相同数量的维度
unbiased (bool) - 是否使用基于修正贝塞尔函数的无偏估计
out (Tensor,optional) - 结果张量

torch.stack()函数:

torch.stack(sequence, dim=0)
沿一个新维度对输入张量序列进行连接,序列中所有张量应为相同形状;stack 函数返回的结果会新增一个维度,而stack()函数指定的dim参数,就是新增维度的(下标)位置。

permute(dims) 将tensor的维度换位。

torch.clamp(input, min, max, out=None) → Tensor 夹紧函数,区域截断取值

mm只能进行矩阵乘法,也就是输入的两个tensor维度只能是( n × m ) (n\times m)(n×m)和( m × p ) (m\times p)(m×p)

bmm是两个三维张量相乘, 两个输入tensor维度是( b × n × m )和( b × m × p ) , 第一维b代表batch size,输出为( b × n × p )
matmul可以进行张量乘法, 输入可以是高维.

[pytorch函数]tensor .expand()扩充 .gt()比较 .t()转置

PyTorch的Broadcasting 和 Element-Wise 操作

矩阵索引

index_select(input, dim, index)# https://blog.csdn.net/wohu1104/article/details/107283279
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐