老饼讲解:一步一步上手深度学习
现在基本都是用pytorch框架来搭建与训练深度学习模型,这节我们就先简单用用pytorch吧~!
在python中一般用list来存一个二维矩阵,但如果你玩过numpy,你会发现在numpy中必须按numpy定义的array来存二维矩阵数据,更进一步地,如果用过pandas,你会发现也必须按它的daraframe格式来存数据。
为啥呢?因为它们提供的功能不一样,为了方便这些功能的实施,所以它们都创建自己的数据对象类型,并重新定义各种运算的语法。
是的,pytorch也一样,它提供了tensor对象(tensor翻译过来就是"张量",刚接触时特别不适应)。使用pytorch,必须把数据弄成tensor对象,因为它提供的各种计算都是面向它自己提供的tensor对象的。事实上,tensor的基础使用很简单,因为它跟np.array,pd.DataFrame的语法是类似的,下面我们简单玩一玩吧。
来来来,生成一个一维、二维向量吧~
import torch
x1 = torch.tensor([0, 1, 2, 3, 4]) # 生成一维tensor数据
x2 = torch.tensor([[0, 1, 2],[ 3, 4,5]]) # 生成二维tensor数据
print('x1=',x1)
print('x2=',x2)运行结果如下:

可以看到,它跟numpy是类似的,只是numpy用numpy.array,而pytorch用torch.tensor
来来来,下面生成一些常用的特殊矩阵吧
import torch
x1 = torch.eye(3) # 生成3*3的单位矩阵
x2 = torch.zeros(2, 3) # 生成2*3矩阵全是0的矩阵
x3 = torch.full((2, 3),1) # 生成2*3矩阵全是1的矩阵
print('x1=',x1)
print('x2=',x2)
print('x3=',x3)运行结果如下:

好家伙!这不妥妥的跟numpy语法类似吗?!
对,语法是差不多的,在numpy里用到的功能,几乎都能在tensor中找到,使用的时候再去查一下就可以了。
如何将numpy的数据转换为tensor?这是一用tensor就马上会发现的问题,是的,不可能一直手敲来输入数据,很多数据本身就是numpy数据,那怎么把numpy的数据弄到tensor中来呢?
这简直不要太简单!直接用from_numpy方法就可以了,如下
import torch
import numpy as np
n = np.array( [[1, 2],[3, 4]]) # 生成一个numpy数据
x = torch.from_numpy(n) # 将numpy数据转换为tensor
print('x=',x)运行结果:

好了,这就是tensor了,把它当成numpy中的array就行了,使用时遇到的各种问题、语法,需要时再去查就行了。在以后看代码、写代码时慢慢积累,像贪吃蛇一样,遇到什么吃什么就好了。
tensor的运算也与numpy是类似的,加法就用+,乘法就是*,矩阵乘就用@,等等等等
import torch
x = torch.tensor( [[1, 2],[3, 4]]) # 生成x
y1 = x+x # 矩阵加法
y2 = x-x # 矩阵减法
y3 = x*x # 元素对应相乘
y4 = x @ x.T # 矩阵乘法
y5 = x**2 # 指数运算
print('加法-y1:',y1)
print('减法-y2:',y2)
print('乘法-y3:',y3)
print('矩乘-y4:',y4)
print('指数-y5:',y5)运行结果如下:

刚接触pytorch时,最让我惊讶的是,这家伙竟然可以自动梯度!对,就是帮你自动计算出梯度!以前玩机器学习时,总是要手动计算各种梯度,麻烦死了,现在这家伙直接就给你计算出梯度了!那还要什么numpy哟!
但是计算梯度是要耗资源的,所以你必须告诉它,这个变量我是要计算梯度的,它才会把你这个变量特殊对待,当成自动梯度对象来款待。
好了,我们先来个简单的例子试试吧!
import torch
x = torch.tensor([3],dtype=(float),requires_grad=True) # x,并指定需要梯度
y = x@x # 根据x计算y
y.backward() # 将y反向传播
print('y对x的梯度:',x.grad) # 打印y对x的梯度运行结果如下:

在代码中,我们实现的是计算在x=3时的梯度,我们先给x赋值3,并指明该变量需要梯度。然后计算y的值,然后进行backward(这就会计算y所依赖的相关变量的梯度),最后,我们打印x的梯度,得到结果为6。
好了,它计算得准不准确定呢,我们试试手动计算来验证一下。
好家伙,计算得还挺准确的嘛,和我们计算的结果一样!
自动梯度功能真好用,再来玩玩。
这次给它上个难度大一点的!来计算中的梯度吧!
import torch
x1 = torch.tensor([3.],requires_grad=True) # x1,指定需要梯度
x2 = torch.tensor([5.],dtype=(float),requires_grad=True) # x2,指定需要梯度
y = torch.sin(x1@x1)**2+x2-6*x1*x2 # 根据x1,x2计算y
y.backward() # 将y反向传播
print('y对x1的梯度:',x1.grad) # 打印y对x的梯度
print('y对x2的梯度:',x2.grad) # 打印y对x的梯度运行结果如下:

好家伙!瞬间就计算出了!真方便!
好了,这例子太烦了,我就不验证了,不相信的伙计自己去验证吧,我还是选择相信它的结果好了!
上面我们说了,在backward时,所有涉及的相关变量都会计算梯度,所以它是可以隔山打牛的。
以,为例,z进行backward,就会计算出的梯度。
import torch
x1 = torch.tensor([3.],requires_grad=True) # x1,指定需要梯度
x2 = torch.tensor([5.],requires_grad=True) # x2,指定需要梯度
y = torch.sin(x1@x2) # 根据x1,x2计算y
z = y**2 # 根据y计算z
y.backward() # 将z反向传播
print('z对x1的梯度:',x1.grad) # 打印z对x的梯度
print('z对x2的梯度:',x2.grad) # 打印z对x的梯度运行结果如下:

可以看到,它又轻轻松松就计算出了z对的梯度了,简直不要太好玩。
so easy!这节我们简单的认识了pytorch的tensor数据对象,包括tensor数据如何生成、如何进行基本运算等等。更重要的是,我们玩了tensor的自动梯度功能,多好用的功能!
事实上,这里面的坑还多着,谁用谁知道,但只能边玩边熟悉,急不来,毕竟,我们不是来研究pytorch的,而是来玩深度学习的,不可能成为pytorch专家再来搞深度学习,后面在玩深度学习时,再慢慢习惯和熟悉它好了。
评论