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

pytorch使用教程及应用-GANS编程(1)-基础使用

程序员文章站 2022-05-29 07:53:55
...

Pytorch使用教程及应用-GANS(构建生成对抗神经网络)


本博文基于书籍–<<Pytorch 生成对抗网络编程>>,欢迎大家购买书籍支持原创

1.基础使用

建立张量:

x=torch.tensor(3.5,requires_grad=True)#建立一个值为3.5且需要计算其梯度的张量

求解函数y对于x的梯度:

import torch
x=torch.tensor(3.5,requires_grad=True)
y=(x-1)*(X-2)
y.backward() #必要步骤,进行反向传播(包含很多底层步骤)
print(x.grad)

这几个看似简单的步骤,实际上pytorch做了很多工作,例如定义y=(x-1)*(x-2),pytorch会计算出x=3.5时y的值并将其加入张量中,而且,pytorch还记录了y在数学上是由x来定义的,学过基本神经网络的都知道,训练神经网络的计算需要使用微积分计算出误差梯度,既输出误差改变的速率随着网络链接权重的改变而改变。所以,其记录y在数学上由x定义对于后面梯度的计算是十分有作用的,y.backward()这一行代码会计算出x对于y的梯度值并加入到张量x中.

实际上,张量的数学含义就是计算图(compute graph)

所以,总结一下,一个pytorch张量可以包含以下内容:

  1. 除原始数值之外的附加信息,比如梯度值
  2. 关于它所依赖的其他张量的信息,以及这种依赖的数学表达式

实际上,这种关联张量和自动微分的能力是pytorch最重要的特性,是其他功能的基础.

张量的来源:计算图

这种自动梯度计算其实来源于我们人为创造的一个逻辑-计算图(compute graph)

举个例子:

一个最简单的网络 每层只有一个神经元

x->y->z

设定:

y = x 2 y=x^2 y=x2
z = 2 y + 3 z=2y+3 z=2y+3

我们都知道,神经网络中,我们需要计算梯度dy/dx.

计算的基本法则是链式法则,这个大家自己学习bp的时候都会讲到,我就不多赘述了.

总之,我们在标记参数requires_grad=True的时候再执行反向传播pytorch就会帮我们计算好梯度保存在张量x中.

所以,对于这个例子的代码就是下面这样

import torch
x=torch.tensor(3.5,requires_grad=True)
y=x*x
z=2*y+3
z.backward() #x标记好梯度后,用z进行反向传播传入张量x的梯度就是dz/dx,用y进行反向传播就是dy/dx
print(x.grad)

注意,如果直接同时写两个backward函数会报错,当然实际使用过程中我们也没有这样的需求.

报错:RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.

其含义是第一次反向传播的时候我们并没有标记参数

retain_graph为true,导致缓冲区在第一次反向传播后就释放了,从而导致第二次反向传播无法进行,所以,我们在第一次反向传播标记此参数后就可以同时写两个反向传播,这样**保存至张量x的梯度值就是计算出的两个梯度值的和,当然一般我们不需要这个和(只需要依据链式法则进行一层层的反向 传播,不需要叠加),所以也没必要这样做.**

(但是在实际使用过程中dz/dy是需要的,所以一般除了输出层,中间的神经层参数( n [ l ] , n [ l − 1 ] n^[l],n^[l-1] n[l],n[l1])(神经元)都必须被定义为张量来方便后面计算出梯度进行参数更新.)

稍复杂一点的神经网络

定义结点间关系:

x = 2 a + 3 b , y = 5 a 2 + 3 b 3 , z = 2 x + 3 y x=2a+3b ,y=5a^2+3b^3,z=2x+3y x=2a+3b,y=5a2+3b3,z=2x+3y

神经网络关系

a x

​ z

b y

梯度计算代码(这里我们就不能仅仅定义一个张量了):

#创建包含x、y和z的计算图
import torch
a=torch.tensor(2.0,requires_grad=True)
b=torch.tensor(1.0,requires_grad=True)
x=2*a+3*b        #x由张量定义,所以本身也是一个张量
y=5*a*a+3*b*b*b
z=2*x+3*y
z.backward()
print(a.grad,b.grad)       #即使经过反向传播后,也无法打印出x的grad,因为没有标记参数,目前还没有找到一个更好的办法去得到x的grad结果,因为是经过计算图的缓存了的

感兴趣的同学也可以自己画一下计算图来复盘一下pytorch的计算.