pytorch学习笔记(零)之基础知识(张量,自动微分)

文章目录

  • 张量(tensor)基础
    • 1.张量的创建
    • 2.张量的操作
      • (1)张量变换
      • (2)张量拼接与切分
  • tensor与numpy转换
    • 1.numpy.array转换为torch.tensor
    • 2.torch.tensor转换为numpy.array
  • 自动微分Autograd

张量(tensor)基础

tensor和numpy非常像,无论是创建还是其他操作几乎一样,不熟悉numpy的可以先看这一篇:numpy快速入门教程

1.张量的创建

(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)按概率分布创建

2.张量的操作

(1)张量变换

方法 描述
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扩展维度

(2)张量拼接与切分

函数 描述
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进行切分

tensor与numpy转换

1.numpy.array转换为torch.tensor

(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)

2.torch.tensor转换为numpy.array

(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])

自动微分Autograd

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

你可能感兴趣的:(2022,人工智能,机器学习,pytorch)