scalar vector matrix tensor(维度是无限的)
tensor参数:
dtype,device,requires_grad,pin_memory(拿空间换时间)
import torch
#创建tensor,dtype指定类型(强制转换)
a=torch.tensor(1,dtype=torch.long)
#使用指定类型函数随机初始化指定大小的Tensor
d=torch.FloatTensor(2,3)
e=torch.IntTensor(2)
f=torch.IntTensor([1,2,3,4])#对于列表转成Tensor
#numpy转Tensor
torch.tensor(g)
torch.from_numpy(g)
#Tensor转numpy
h.numpy()
#构造Tensor函数(参数是大小)
k=torch.rand(2,3)
l=torch.ones(2,3)
m=torch.zeros(2,3)
n=torch.arange(0,10,2)#左闭右开
#查看维度信息,注意括号
k.shape
k.size()
#Tensor的运算,对应元素相加
o=torch.add(k,l)
#索引与numpy类似
o[:,1]
#改变Tensor形状函数view
o.view(3,2)
o.view(-1,2)#-1自动填补
#Tensor广播机制,维度不一样,运算时自动配齐
p=torch.arange(1,3).view(1,2)
q=torch.arange(1,4).view(3,1)
p+q
#>>3行2列
#Tensor维数扩展 unsqueeze
#Tensor维数压缩 squeeze ,只能删掉维数是1的Tensor,若不是就保持原样
r=o.unsqueeze(1)
r.squeeze(0)#不变
r.squeeze(1)
雅克比矩阵:向量求导向量是矩阵 + 链式法则
动态计算图(DCG)
import torch
x1 = torch.tensor(1.0,requires_grad=True)
x2 = torch.tensor(2.0,requires_grad=True)
y= x1 + 2*x2
y.backward()
#查看导数的值
x1.grad.data
#导数会累积,再做梯度回传,梯度会相加,每次计算前要清零导数值
#若x1 = torch.tensor(1.0,requires_grad=False),x2 = torch.tensor(2.0,requires_grad=False)
#那y.backward()会报错,不能自动去求导,反向传播不能完成
pytorch补充函数clone(),copy(),detach()
clone()与copy()的用法是一样的,只是写法不同
创建一个tensor与源tensor有相同的shape,dtype和device,不共享内存地址,但新tensor的梯度会叠加在源tensor上。下面例子可以说明上述特点:
import torch
a = torch.tensor([1.,2.,3.],requires_grad=True)
b = a.clone()
print(a.data_ptr()) # 3004830353216
print(b.data_ptr()) # 3004830353344 内存地址不同
print(a) # tensor([1., 2., 3.], requires_grad=True)
print(b) # tensor([1., 2., 3.], grad_fn=) 复制成功
print('-'*30)
c = a * 2
d = b * 3
c.sum().backward()
print(a.grad) # tensor([2., 2., 2.])
d.sum().backward()
print(a.grad) # tensor([5., 5., 5.]) # 源tensor的梯度叠加了新tensor的梯度
print(b.grad) # None # 此时复制出来的节点已经不属于叶子节点,因此不能直接得到其梯度
需要注意的是,b = a.clone()之后,b并非叶子节点(最后输出b的梯度时warning会提醒我们)。b节点更像是a经过一个恒等函数之后得到的输出。
a = torch.tensor([1., 2., 3.],requires_grad=True)
b = torch.empty_like(a).copy_(a)
detach()函数返回与调用对象tensor相关的一个tensor,此新tensor与源tensor共享数据内存(那么tensor的数据必然是相同的),但其requires_grad为False,并且不包含源tensor的计算图信息。当定义两个网络A、B时,把A的输出给B,只改变B的参数,不改变A的参数。
a = A(input)
a = a.deatch() # 或者a.detach_()进行in_place操作
out = B(a)
loss = criterion(out, labels)
loss.backward()