tensor和numpy非常像,无论是创建还是其他操作几乎一样,不熟悉numpy的可以先看这一篇:numpy快速入门教程
(1)直接创建
# 从data中创建tensor
torch.tensor(data, dtype=None, device=None,requires_grad=False,pin_memory=False)
参数 | 描述 |
---|---|
data | 数据,可以是list,numpy |
dtype | 数据类型,默认与data的一致 |
device | 所在设备,cuda/cpu |
requires_grad | 是否需要梯度 |
pin_memory | 是否存于锁页内存 |
可以看出tensor和numpy的几点不同是,tensor多了一个requires_grad
参数,还有一个device
参数,其实就是说tensor可以在cpu或者gpu上运行,但是numpy只能在cpu上,并且没有梯度信息。
torch.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
# output:tensor([[0.1000, 1.2000],
# [2.2000, 3.1000],
# [4.9000, 5.2000]])
(2)从数值中创建
这里就是几个方便创建的方法,可以见下表:
方法 | 描述 |
---|---|
torch.zeros(size) | 依size创建全0张量 |
torch.ones(szie) | 依size创建全0张量 |
torch.full(size, fill_value) | 依size创建 fill_value 张量 |
torch.arange(start=0, end , step=1) | 创建等差的1维张量 |
torch.eye(n,m=None) | 创建单位对角(n x m)矩阵(2维张量 ) |
注意:上述方法参数很多,但最需要设置的已经列出,以zeros()
为例可以看一下完整参数,其他方法类似有这样的参数。
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
"""
size: 张量的形状,如(3, 3)、(3, 224, 224)
out: 输出的张量
layout: 内存中布局形式,有strided, sparse_coo等
device: 所在设备,gpu/cpu
requires_grad: 是否需要梯度
"""
(3)按概率分布创建
方法 | 描述 |
---|---|
torch.reshape(input, shape) | 变换张量形状 |
torch.view(size) | 返回的和输入的张量一样,只是改变了维度和大小 |
torch.transpose(input, dim0, dim1) | 交换张量的两个维度 |
torch.squeeze(input, dim=None, out=None) | 压缩长度为1的维度(轴) |
torch.unsqueeze(input, dim, out=None) | 依据dim扩展维度 |
函数 | 描述 |
---|---|
torch.cat(tensors, dim=0, out=None) | 将张量按维度dim进行拼接 |
torch.stack(tensors, dim=0, out=None) | 在新创建的维度dim上进行拼接 |
torch.split(tensor, split_size_or_sections, dim=0) | 将张量按维度dim进行切分 |
(1)torch.tensor() (其实就是最开始tensor的创建,这里再写一遍)
(2)torch.from_numpy():
从torch.from_numpy
创建的tensor于原ndarray共享内存,当修改其中一个数据,另一个也将会被改动。
import numpy as np
import torch
a = np.array([1, 2, 3])
t = torch.from_numpy(a)
print(t)
# output : tensor([1, 2, 3], dtype=torch.int32)
(0)首先介绍一下cpu和gpu上的tensor如何传递
先创建一个tensor:
import torch
a = torch.tensor([2,4,6,8])
print(a)
# output: tensor([2, 4, 6, 8])
然后通过.cuda()
将 tensor 移到gpu上:
b = a.cuda()
# 如果有多张gpu,还可以指定移到哪张卡上
# b = a.cuda(device=1)
print(b)
# output: tensor([2, 4, 6, 8], device='cuda:0')
# 还可以用更常见的方法
# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# b = a.to(device)
通过.cpu()
将tensor从gpu移到cpu上:
c = b.cpu()
print(c)
# output:tensor([2, 4, 6, 8])
(1)如果tensor 在cpu上,直接.numpy()
转换就可以了
import torch
t = torch.tensor([2,4,6,8]) # 创建一个tensor
print(t)
n = t.numpy() # 将tensor转化为numpy
print(n)
输出:
tensor([2, 4, 6, 8])
array([2, 4, 6, 8], dtype=int64)
(2)如果tensor在gpu上,则需要先移到cpu再numpy
import torch
a = torch.tensor([2,4,6,8]).cuda() #创建一个tensor并移到gpu上
b = a.cpu().numpy() # 先将tensor a 移到cpu再转换为numpy
输出:
tensor([2, 4, 6, 8], device='cuda:0')
[2 4 6 8]
(3)如果tensor在gpu上且有梯度,还需要先.detach()
移除梯度信息再numpy()
import torch
a = torch.tensor([2,4,6,8]).cuda() # 创建一个 tensor 并移到 gpu 上
my_module = MyModule() # 实例化一个网络
output = my_module(a) # 将tensor a 送进网络,此时output是有梯度的
"""
先移到cpu上,再移除梯度,再转换为numpy
"""
b = output.cpu().detach().numpy()
print(b)
output: array([1, 2, 3])
PyTorch 中所有神经网络的核心是 autograd,它为张量上的所有操作提供了自动求导。当设置 .requires_grad
为 True,那么将会追踪所有对于该张量的操作。当完成计算后通过调用 .backward()
会自动计算所有的梯度,这个张量的所有梯度将会自动积累到 .grad
属性。这也就完成了自动求导的过程。
grad_fn:用来记录变量是怎么来的,方便计算梯度,y = x+1,grad_fn记录了y由x计算的过程。
grad:当执行完了backward()之后,通过x.grad查看x的梯度值
import torch
"""
y=a*b=(w+x)*(w+1)=w^2+w*x+w+x
"""
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
# 输出变量y是怎么来的
print(y.grad_fn)
"""反向传播,打印对应节点的梯度"""
y.backward()
print(x.grad) # 输出y对x的梯度: w+1=1+1=2
print(w.grad) # 输出y对w的梯度: 2w+x+1=2*1+2+1=5
tensor([2.])
tensor([5.])
更多梯度计算可以参考 click here
如果 .requires_grad=True 但是又不希望进行 Autograd 的计算,那么可以将变量包裹在 with torch.no_grad() 中:
x = torch.randn(3, requires_grad=True)
print(x.requires_grad) # True
print((x ** 2).requires_grad) # True
with torch.no_grad():
print((x ** 2).requires_grad) # False
https://blog.csdn.net/weixin_44853840/article/details/116537678
https://www.lanqiao.cn/courses/1348/learning/
https://blog.csdn.net/weixin_41490373/article/details/114407305