Pytorch 入门系列(一)

前言

本文旨在介绍Pytorch的入门知识。在第一部分,我们简单介绍了当前的主流深度学习框架,并介绍了选择Pytorch的理由及其安装方法。在第二部分,我们给出了Pytorch的一个简单入门,包括张量的使用,如何借助Cuda在Pytorch中使用GPU进行计算,以及Pytorch中的求导运算等。最后在第三部分,我们对文中讲到的关键操作进行了总结。

1. 深度学习框架的简单介绍

1.1 主流深度学习框架

PyTorch是一个基于Python的库,用来提供一个具有灵活性的深度学习开发平台。PyTorch的工作流程非常接近Python的科学计算库numpy。

当前主流的深度学习框架有两种,一种是以Tensorflow为代表的静态图框架,另一种就是以Pytorch为代表的动态图框架。静态图框架要求我们先定义好模型结构再运行模型,而动态图框架意味着程序将按照命令顺序执行,这种机制使得我们调试更加容易。用编程语言做类比,Tensorflow更像C++,而Pytorch更像Python。

Pytorch在近年来发展迅速,下图对比了Pytorch和Tensorflow在论文中的使用情况:

从图中可以看到,2019年1月到6月底,在arXiv.org上发表的论文中,提及TensorFlow和PyTorch的数量相差无几,PyTorch仅稍稍落后。但最关键的在于增长速度:与2018年1月到6月相比,PyTorch增长了194%,相比之下,TensorFlow的增长幅度仅为23%。从当前的数据可以看出,Pytorch因其简单易用而越来越受到大家的青睐。

1.2 为什么选择Pytorch

首先不得不提Tensorflow的反人类设计。Tensorflow的逻辑有两种,一种是建graph时的逻辑,另一种是运行时的逻辑。当要实现的算法比较复杂的时候就会很麻烦,一不小心就会出错。

其次,Pytorch可以和Python无缝衔接,学习成本很低,给人的直观感受就是用着顺手、舒服。

最后,Pytorch代码简洁易懂。因此,作为深度学习的入门工具来说,Pytorch再合适不过了。

1.3 Pytorch 的安装

Pytorch 安装起来十分简单,只要三步即可完成,

(1) 进入 Pytorch 官网

(2) 选择合适的操作系统和版本</br>

在YourOs一栏选择你的操作系统。在CUDA一栏是选择是否安装GPU版本,如果要安装GPU版本,首先要安装上CUDA,然后选择CUDA的版本。

(3) 拷贝 Run this Command 一栏中的命令

将命令拷贝到终端执行,即可自动安装。

2. Pytorch 的简单入门

2.1 张量的概念

简单的说,张量概念是矢量概念和矩阵概念的推广。标量是零阶张量,矢量是一阶张量,矩阵(方阵)是二阶张量,而三阶张量则好比是立体矩阵,更高阶的张量用图形无法表达。机器学习中的数据往往以张量形式表达。

2.2 张量的创建

Pytorch 中张量的创建主要有以下几种形式:

(1) torch.empty 函数

import torch

x = torch.empty(5,3) #创建一个5*3的矩阵
print(x)
y = torch.empty(2,2,2) #创建一个2*2*2的张量
print(y)

输出:

tensor([[1.1210e-44, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00]])

tensor([[[8.4078e-45, 0.0000e+00],
         [1.2708e-31, 1.4013e-45]],

        [[0.0000e+00, 0.0000e+00],
         [0.0000e+00, 0.0000e+00]]])

empty函数返回填充有未初始化数据的张量,在我们不需要初始化具有特定分布的数据时可以使用。

(2) torch.rand 函数

x = torch.rand(5,3) #创建一个5*3的矩阵
print(x)
y = torch.rand(2,2,2) #创建一个2*2*2的张量
print(y)

输出:

tensor([[0.1413, 0.5294, 0.6538],
        [0.4040, 0.0293, 0.7876],
        [0.8263, 0.2070, 0.5927],
        [0.4749, 0.7163, 0.4874],
        [0.2791, 0.3276, 0.1504]])

tensor([[[0.2636, 0.9148],
         [0.9117, 0.9742]],

        [[0.4946, 0.6069],
         [0.5841, 0.6050]]])

torch.rand 建立一个张量,默认将数据初始化为[0,1)的均匀分布。类似的函数有 torch.randn 将数据初始化为均值为0,方差为1的标准正态分布;torch.normal 可以生成指定均值和方差的正态分布。

(3) torch.ones 函数

x = torch.ones(5,3)
print(x)

输出:

tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

torch.ones 建立一个张量,并将值初始化为1。

(4) torch.zeros 函数

x = torch.zeros(5,3)
print(x)

输出:

tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

torch.zeros 建立一个张量,并将矩阵值初始化为0。

(5) 直接从数组建立一个张量

x = torch.tensor([2,3,4,5])
print(x)

输出:

tensor([2, 3, 4, 5])

(6) new_ones,new_zeros,new_empty

x = torch.zeros(2,3,dtype=torch.int32) #新建一个张量
print(x)
y = x.new_ones(1,2)      #从x中创建一个新的张量,数据类型不变
print(y)

输出:

tensor([[0, 0, 0],
        [0, 0, 0]], dtype=torch.int32)
        
tensor([[1, 1]], dtype=torch.int32)

这些函数可以从已有张量建立一个新的张量。

(7) ones_like,zeros_like,empty_like

x = torch.ones(4,4)
print(x)
y = torch.rand_like(x)
print(y)

输出:

tensor([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]])

tensor([[0.5023, 0.7911, 0.3639, 0.3315],
        [0.8617, 0.0388, 0.1612, 0.2071],
        [0.1755, 0.3988, 0.8381, 0.5835],
        [0.9588, 0.3950, 0.8371, 0.5337]])

这些函数可以创建一个和目标张量形状相同的张量。

2.3 张量的运算

张量常用的计算操作主要有张量的加法,张量乘法,张量形状改变。

(1) 张量加法

主要有三种方式:

  • x+y
  • torch.add(x,y,out=result)
  • y.add_(x)是将x增加到y上并改变y的值,运算符加“_”是将运算结果赋值给左边的变量。
y = torch.rand(3,5)
x = torch.ones(5)
result = torch.empty(3,5) 
print(x+y) #第一种方式
print(torch.add(x,y,out=result)) #第二种方式
y.add_(x) #第三种方式
print(y)

输出:

tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
        [1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
        [1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])

tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
        [1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
        [1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])

tensor([[1.8442, 1.9501, 1.8182, 1.0880, 1.7674],
        [1.5743, 1.5252, 1.8656, 1.2426, 1.4136],
        [1.9056, 1.3625, 1.8482, 1.6156, 1.7287]])

(2) 张量乘法

  • mm 只能是矩阵乘法,也就是输入的两个tensor维度只能是(n,m)和(m,p)
  • bmm 是两个三维张量相乘,两个tensor维度是(b,m,p)和(b,p,n),b一般是batch_size
  • matmul 可以进行张量乘法,输入可以是高维的

mm 操作示例:

x = torch.ones(3,2)
y = torch.ones(2,3)
x.mm(y)

输出:

tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])

bmm 操作示例:

x = torch.ones(2,3,2)
y = torch.ones(2,2,3)
x.bmm(y)

输出:

tensor([[[2., 2., 2.],
         [2., 2., 2.],
         [2., 2., 2.]],

        [[2., 2., 2.],
         [2., 2., 2.],
         [2., 2., 2.]]])

(3) Resize 操作

view函数实现了torch中张量的Resize操作。

x = torch.rand(2,2)
y = x.view(-1) # 从x生成一维向量,长度自动计算
print(y)
z = y.view(2,-1) #从y生成行数为2的矩阵,列的长度自动计算
print(z)

输出:

tensor([[0.2995, 0.2133],
        [0.6413, 0.7581]])

tensor([0.2995, 0.2133, 0.6413, 0.7581])

tensor([[0.2995, 0.2133],
        [0.6413, 0.7581]])

Resize操作在很多时候都有用,例如我们进行图像识别时,卷积层是n个方阵,要将卷积核输出为类别,通常是先将它们展成一维,再带入softmax函数计算进行分类。

(4) 转置操作 t.()

x = torch.empty(3,4)
print(x)
print(x.t())

输出:

tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]])

tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

2.4 Pytorch 中张量和 NumPy Array 的相互转化

在Torch Tensor和NumPy array之间相互转化非常容易。Torch Tensor和NumPy array共享内存,所以改变其中一项也会改变另一项。

把Torch Tensor转变成NumPy Array:

a = torch.ones(5)
print(a)
b = a.numpy()
print(b)

输出:

tensor([1., 1., 1., 1., 1.])

[1. 1. 1. 1. 1.]

把上面的a增加1:

a.add_(1)
print(a)
print(b)

输出:

tensor([2., 2., 2., 2., 2.])

[2. 2. 2. 2. 2.]

把NumPy Array转变成Torch Tensor:

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
print(a)
print(b)
np.add(a,1,out=a)
print(a)
print(b)

输出:

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

2.5 Pytorch 中使用GPU计算

在Pytorch 中,使用GPU计算是很方便的,可以在创建张量的时候指定张量计算位置,也可以将张量转移到GPU上计算。

if torch.cuda.is_available():
    device = torch.device("cuda")
    y = torch.ones(2,3,device=device) #在GPU上创建张量
    x = torch.empty(4,5) 
    x.to(device) #将张量x转移到GPU上
    z = x+y

2.6 Pytorch 中的求导运算

我们在进行模型训练的时候,常常需要用梯度下降法,所以求导是很重要的,在Pytorch中,求导非常方便。例如对Y = WX + B,我们计算Y关于W和B的导数。不难发现,Y关于W的导数是X的转置,Y关于B的导数是1。

操作示例:

w = torch.zeros((3,1),requires_grad=True) # 声明W的形状,以及可导性(默认不可导)
x = torch.ones(1,3) # 声明X形状
b = torch.tensor([1.],requires_grad=True)
y = x.mm(w) + b     # Y = wx + b
y.backward()       # 求导操作
print(w.grad)
print(b.grad)

输出:

tensor([[1.],
        [1.],
        [1.]])
        
tensor([1.])

3. 总结

本文我们简单介绍了Pytorch基本知识,包括安装方法,基本的张量操作。张量操作我们主要说明了Pytorch中张量的几种创建方法,张量的运算。然后我们学习了如何在GPU上进行计算,最后我们介绍了Pytorch上的求导操作。

最后,要记住以下重要操作哦:

  1. 张量创建
    • torch.ones(), torch.empty(), torch.zeros()
    • x.new_ones(), x.new_rand()..
    • torch.empty_like(),torch.zeros_like()
  2. 张量操作
    • 加法 torch.add(x,y,result=z),add_(),"+"
    • 乘法 mm(),bmm(),matmul()
    • 和numpy的相互转化 a.numpy(), torch.from_numpy()
  3. GPU计算
    • 记住函数 torch.cuda.is_available(),
    • torch.device("cuda")
    • to(device)
  4. 求导运算
    • 记得在创建张量时加一个requires_grad=True
    • loss.backward()函数
    • 导数在W.grad中取得

下期我们将以房价预测为例,来搭建一个简单的线性模型!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容