学习笔记:《深度学习框架PyTorch入门与实践》(陈云)Part1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27022241/article/details/84556278

       学习笔记:《深度学习框架PyTorch入门与实践》(陈云)Part1

    2017年1月,FAIR团队在GitHub上开源了PyTorch。

    常见的深度学习框架:

    (1)Theono(2008)已经停止开发,不建议学习;

    (2)TensorFlow(2015,Google):使用数据流图进行数值计算,图中节点代表数学运算,而图中的边代表在这些节点之间传递的多维数组(张量)。不完美但流行,社区强大,适合生产环境;

    (3)Keras:高层神经网络API,由纯Python编写而成并使用TensorFlow、Theano及CNTK作为后端。过度封装导致程序过于缓慢。入门最简单,但是不够灵活,使用受限;

    (4)Caffe/Caffe2:核心语言是C++,支持命令行、PyThon和MATLAB接口,既可以在CPU上运行,也可在GPU上运行。文档不够完善,但性能优异,几乎全平台支持(Caffe2),适合生产环境;

    (5)MXNet:文档略混乱,但分布式性能强大,语言支持最多,适合AWS平台使用;

    (6)CNTK(2015,MicroSoft):社区不够活跃,但是性能突出,擅长语言方面的研究。

    计算图:

    几乎所有的框架都是基于计算图的,而计算图又可以分为静态计算图和动态计算图。PyTorch基于动态图,TensorFlow基于静态图。

    为什么选择Pytorch?

   (1)简洁:追求最少的封装,避免重复造轮子。PyTorch设计遵循tensor->variable(autograd)->nn.module三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可同时进行修改和操作。

    (2)速度:许多评测中,Pytorch速度表现胜过TensorFlow和Keras等框架。

    (3)易用。

    (4)活跃的社区。

    目前,官方已经支持Windows PyTorch。

2 PyTorch安装

    需提前安装:Python + Pip + CUDA + Numpy。

    Anaconda对于Python相当于Ubuntu对于Linux,即Anaconda是Python的一个发行版,将Python和许多常用的package打包,方便Pythoners直接使用。

    Pip是一个安装和管理Python包的工具。

    安装Pip:sudo python get-pip.py

    升级Pip:pip install -U pip

    简单来说,pip和pip3一样,只是为了区别python2和python3之间的调用,避免冲突而进行的设定。如果你的电脑只安装了Python,那么你无法使用pip3。同时安装了Python和Python3,使用pip命令,新安装的库会在python2.x/site-packages目录下,使用pip3命令,会在python3.x/site-packages目录下。

    CUDA(Comupute Unified Device Architecture):英伟达公司推出的一种基于新的并行编程模型和指令集架构的通用计算架构。

    cuDNN:用于深度神经网络的GPU加速库。

    安装PyTorch需安装2个模块:主模块torch用来搭建网络,辅模块torchvision用来生成图片、视频数据集和一些流行的模型类和预训练模型。

    安装(PyTorch官网):

# Python 3.7
pip3 install http://download.pytorch.org/whl/cu80/torch-0.4.1-cp37-cp37m-win_amd64.whl
pip3 install torchvision

    验证是否安装成功:

python   (进入Python环境)

import python

import torchvision

#不报错则成功

3 学习环境配置

    在从事科学计算相关工作时,Ipython和Jupyter Notebook是两个必不可少的工具。

    Ipython是一个交互式计算系统,可认为增强版的Python Shell。

    Jupyter是一个交互式笔记本,现支持运行40多种编程语言。

    Jupyter:

    (1)安装:pip install jupyter。

    (2)打开:命令行输入jupyter notebook即可启动。或打开浏览器,输入http://127.0.0.1:8888访问。

    (3)使用:单击页面右上角“new”选项,选择相应Notebook类型(python3/python2)可新建一个notebook,写入代码,按“ctrl+enter”快捷键即可运行代码。

4 PyTorch入门第一步

4.1 Tensor

    Tensor是PyTorch中重要的数据结构,可认为是一个高维数组,它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)或更高维的数组。Tensor和numpy的ndarrays类似,但Tensor可以使用GPU加速。Tensor的使用和numpy及MATLAB的接口十分相似。下面展示Tensor的基本使用方法。

from __future__ import print_function
import torch as t
#构建5*3矩阵,只是分配了空间,未初始化
x1=t.Tensor(5,3)
print(x1)
#使用[0,1]均匀分布随机初始化二维数组
x2=t.rand(5,3)
print(x2)
print(x2.size())    #查看x2的形状
print(x2.size()[1])    #查看列的个数,等价于x2.size(1)


Out:
tensor([[-386620439650957628105129136431824896.0000,
                                             0.0000,
         -386620439650957628105129136431824896.0000],
        [                                    0.0000,
                                             0.0000,
                                             0.0000],
        [                                    0.0000,
                                             0.0000,
                                             0.0000],
        [                                    0.0000,
                                             0.0000,
                                             0.0000],
        [                                    0.0000,
                                             0.0000,
                                             0.0000]])
tensor([[0.4898, 0.9725, 0.1614],
        [0.2631, 0.0199, 0.9133],
        [0.0881, 0.8390, 0.6090],
        [0.7283, 0.7939, 0.4258],
        [0.5043, 0.2234, 0.3374]])
torch.Size([5, 3])
3
from __future__ import print_function
import torch as t

x=t.ones(5,3)
y=t.ones(5,3)
#加法的第一种写法
print(x + y)
#加法的第二种写法
print(t.add(x,y))
#加法的第三种写法
result=t.Tensor(5,3)    #预先分配空间
t.add(x,y,out=result)       #输入到result
print(result)

Out:
tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
from __future__ import print_function
import torch as t

x=t.ones(5,3)
y=t.ones(5,3)
print("最初y")
print(y)

print("第一种加法,y的结果")
y.add(x)    #普通加法,不改变y的内容
print(y)

print("第二种加法,y的结果")
y.add_(x)    #inplace加法,改变y的内容
print(y)

    Tensor还支持很多操作,包括数学运算、线性代数、选择、切片等,其接口设计与numpy极为相似。详细会在后续讲解。

    Tensor和numpy的数组间的互操作非常容易且快速。Tensor不支持的操作,可以先转为numpy数组处理,之后再转回Tensor。

from __future__ import print_function
import torch as t

a=t.ones(5)    #新建一个全是1的Tensor
b=a.numpy()    #Tensor->Numpy
print(a)
print(b)

Out:
tensor([1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1.]
import numpy as np
a=np.ones(5)
b=t.from_numpy(a)    #Numpy->Tensor
print(a)
print(b)

Out:
[1. 1. 1. 1. 1.]
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)

    Tensor和numpy对象共享内存,所以它们之间的转换很快,而且几乎不会消耗资源。这也意味着,如果其中一个变了,另外一个也会随之改变。

import numpy as np
a=np.ones(5)
b=t.from_numpy(a)    #Numpy->Tensor
print(a)
print(b)
b.add_(1)    #以_结尾的函数会修改自身
print(a)
print(b)     #Tensor和Numpy共享内存

Out:
[1. 1. 1. 1. 1.]
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

     Tensor可通过.cuda方法转为GPU的Tensor,从而享受GPU带来的加速运算。在此处可能会发现GPU运算的速度并未提升太多,这是因为x和y较小且运算简单,而且将数据从内存转移到显存还需要花费额外的开销。GPU的优势需在大规模数据和复杂运算下才能体现出来。

#在不支持cuda的机器上,下一步不会运行
import torch as t
if t.cuda.is_available():
    x=t.ones(5)
    y=t.ones(5)
    
    print(x.cuda() + y.cuda())  

Out:
tensor([2., 2., 2., 2., 2.], device='cuda:0')

4.2 Autograd:自动微分

from torch.autograd import Variable
import torch as t
#使用Tensor新建一个Variable
x = Variable(t.ones(2,2),requires_grad = True)
print(x)
y = x.sum()    # y=(x[0][0]+x[0][1]+x[1][0]+x[1][1])
print(y)
y.grad_fn
y.backward()   #反向传播,计算梯度
#每个值的梯度都为1
print(x.grad)

#注意:grad在反向传播过程中是累加的,这意味着每次运行反向传播,梯度都会累加之前的梯度,所以反向传播前需把梯度清零
y.backward()
print(x.grad)

#清空
x.grad.data.zero_()
y.backward()
print(x.grad)

Out:
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)
tensor(4., grad_fn=<SumBackward0>)
tensor([[1., 1.],
        [1., 1.]])
tensor([[2., 2.],
        [2., 2.]])
tensor([[1., 1.],
        [1., 1.]])

 4.3 神经网络

   

 
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torch as t

class Net(nn.Module):
    def __init__(self):
        #nn.Module子类的函数必须在构造函数中执行父类的构造函数
        #下式等价于nn.Module.__init__()
        super(Net,self).__init__()
        #卷积层‘1’表示输入图片为单通道,‘6’表示输出通道数,‘5’表示卷积核为5*5
        self.conv1 = nn.Conv2d(1, 6, 5)
        #卷积层
        self.conv2 = nn.Conv2d(6, 16, 5)
        #仿射层/全连接层,y = Wx + b
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
        
    def forward(self,x):
        # 卷积->激活->池化
        x = F.max_pool2d(F.relu(self.conv1(x),(2,2)))
        x = F.max_pool2d(F.relu(self.conv2(x),2))
        
        #reshape,‘-1’表示自适应
        x = x.view(x.size()[0], -1)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    
net = Net()
print(net)

Out:
Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

 

params = list(net.parameters())
print(len(params))

for name, parameters in net.named_parameters():
    print(name, ":", parameters.size())

Out:
10
conv1.weight : torch.Size([6, 1, 5, 5])
conv1.bias : torch.Size([6])
conv2.weight : torch.Size([16, 6, 5, 5])
conv2.bias : torch.Size([16])
fc1.weight : torch.Size([120, 400])
fc1.bias : torch.Size([120])
fc2.weight : torch.Size([84, 120])
fc2.bias : torch.Size([84])
fc3.weight : torch.Size([10, 84])
fc3.bias : torch.Size([10])

input = Variable(t.randn(1,1,32,32))
out = net(input)
out.size()

Out:
torch.Size([1, 10])

 

out = net(input)
target = Variable(t.arange(0,10))
criterion = nn.MSELoss()
loss = criterion(out,target)


#运行.backward,观察调用之前和调用之后的grad
net.zero_grad()    #把net中所有可学习参数的梯度清零
print("反向传播之前conv1.bias的梯度")
print(net.conv1.bias.grad)
loss.backward()
print("反向传播之后conv1.bias的梯度")
print(net.conv1.bias.grad)

Out:
报错待解决

猜你喜欢

转载自blog.csdn.net/qq_27022241/article/details/84556278
今日推荐