欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pytorch学习笔记(一)

程序员文章站 2022-06-06 11:18:07
...

前言

此为小弟pytorch的学习笔记,希望自己可以坚持下去。(2020/2/17)

pytorch官方文档

pytorch中文教程

tensor

tensor是pytorch的最基本数据类型,相当于numpy中的ndarray,并且属性和numpy相似,tensor可在GPU上进行运算。

tensor常见的基本属性:
pytorch学习笔记(一)

1.创建tensor

通常此类方法都有以下属性,特别注意,区别numpy,一般这里的入口参数size都是数字序列,而不是元组或者列表:

#创建无初始化tensor
x1 = torch.empty(5, 3)
#创建全0值tensor
x2 = torch.zeros(5, 3, dtype=torch.long)
#创建随机值tensor
x3 = torch.rand(5, 3)
#创建全1
x4 =torch.ones(5,3)

#根据已有tensor创建新的tensor,可继承之前的所有属性,包括dtype,device等
x = x1.new_ones(5, 3, dtype=torch.double)#必须输入size
x = torch.randn_like(x1, dtype=torch.float)

#根据其余数据类型创建tensor
#列表
x=torch.tensor([1,2,3])
#ndarray
np_data=np.arange(4).reshape((2,2))
x=torch.tensor(np_data,dtype=torch.float)

补充:关于随机数,这里提供一个总结后的帖子:随机数生成

2. 基本属性

requires_grad:是否需要梯度,如果为true则会允许自动求导

#设置为有梯度属性
x= torch.rand(5, 3,requires_grad=True)
#改变梯度属性
x.requires_grad_(False)

3. 基本方法

size():获取大小

item():获取只有一个值的tensor的值

view():改变shape,此改变创建了新的副本

x= torch.rand(5, 3,requires_grad=True)
#Size()为元组
x.size()
x=torch.arange(6,dtype=torch.float).reshape((2,3))

#view() 	
y1=x.view(-1,1)
y2=x.view(3,2)
print(
    '\n',y1,
    '\n',y2
)

4. 运算

tensor的所有常规运算都是基于元素的。

x=torch.arange(4,dtype=torch.float).reshape((2,2))
#点乘
out1=x*x
#如果要用到叉乘
out2=torch.mm(x,x)

print(
    '\n',out1,
    '\n',out2
)
>>>>>>>
 tensor([[0., 1.],
        [4., 9.]]) 
 tensor([[ 2.,  3.],
        [ 6., 11.]])

5. GPU运算

#创建tensor
x=torch.ones(3,4,dtype=torch.float)
# 当GPU可用时,我们可以运行以下代码
# 我们将使用`torch.device`来将tensor移入和移出GPU
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA device object
    y = torch.ones_like(x, device=device)  # 直接在GPU上创建tensor
    # x = x.to(device)                       # 或者使用`.to("cuda")`方法
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # `.to`也能在移动时改变dtype

自动求导Autograd

对于一个tensor,若其requires_grad=True 那么它将会追踪对于该张量的所有操作。当完成计算后可以通过调用 .backward(),来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad属性.

x = torch.ones(3,3, requires_grad=True)
y=x*x+2
#
out1=y.sum()
#out1通常是一个标量,若是一个非变量,不可直接进行backward()
out1.backward()
#根据链式求导法则,x_i.grad=1*2x=2
print(
    '\n',x,
    '\n',y,
    '\n',x.grad
)
>>>>>>>>>
 tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], requires_grad=True) 
 tensor([[3., 3., 3.],
        [3., 3., 3.],
        [3., 3., 3.]], grad_fn=<AddBackward0>) 
 tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
 
#若输出结果是一个非标量
x = torch.rand(2,2, requires_grad=True)
y = torch.rand(2,1,requires_grad=True)
out1=2*torch.mm(x,y)
#不可直接使用out1.backward()
out1.backward(torch.ones_like(y))
print(
    '\n',x,
    '\n',y,
    '\n',out1,
    '\n',y.grad
)

对于向量的求导,实际atuograd已经计算了雅可比矩阵,但是pytorch的内部机制,或者说本身pytorch就是为神经网络设计的,反向传播的起点为损失函数,必然为一个标量,所以,自动求导的out是需要为标量。
pytorch学习笔记(一)
out1.backward(torch.ones_like(y))这里实际上输入了一个[1,1].T 的向量,代表某个标量l对out1的导数,等同于以下程序:

x2 = torch.ones(2,2,requires_grad=True)
y2 = torch.ones(2,1,requires_grad=True)
z=2*torch.mm(x2,y2)
out2=z.sum()
print(out2)
#不可直接使用out1.backward()
out2.backward()
print(
    '\n',y2.grad
)

关于更多,更深入的atuograd理解,可品读这个帖子,深入浅出:PyTorch 自动一阶求导在标量、向量、矩阵、张量运算中的定义

清空grad

当我们需要清除某个tensor的梯度时,我们需要:

tensor.grad = None

阻止autograd跟踪

除了修改tensor的requires_grad为False以外,我们还可以进行这样的操作,阻止autograd跟踪:

with torch.no_grad():
    print((y2*y2).requires_grad):	
相关标签: 机器视觉 python