pytorch基础(一):tensor张量和自动微分

前言

  本系列主要是对pytorch基础知识学习的一个记录,尽量保持博客的更新进度和自己的学习进度。本人也处于学习阶段,博客中涉及到的知识可能存在某些问题,希望大家批评指正。

一、pytorch入门

1.什么是tensor张量

  在吴恩达老师深度学习视频中,第一章和第二章的课后作业我们用numpy实现前向传播和反向传播,numpy提供的ndarray数据类型,支持numpy内置的dot运算简化了极大简化了矩阵运算,让我们可以快速的搭建一个简单的神经网络模型。
  在深度学习框架pytorch中,其实我们很难见到numpy的使用,准确的说是很难见到ndarray这一数据类型,见到更多的其实是tensor类型的数据。
  ndarray和tensor本质上来说都是多维数组,pytorch封装了很多关于tensor类型数据的操作,比如随机初始化,广播等,所以在pytorch框架下,tensor可以完成ndarray在numpy中的几乎所有操作。tensor和ndarray数据类型之间是可以相互转换的。
  除此之外,tensor的一个重大优势是可以利用GPU进行加速运算。

2.tensor张量的基本操作

导入库:

import torch

刚开始学习的时候其实有点疑惑的,我pip的明明是pytorch,为什么import的库的名字是torch。

构造一个5x3的矩阵,不初始化:

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

输出:

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

构造一个随机初始化矩阵:

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

输出:

tensor([[0.1033, 0.4686, 0.5900],
    [0.1427, 0.8772, 0.3225],
    [0.7151, 0.7967, 0.2124],
    [0.3208, 0.7758, 0.6411],
    [0.9130, 0.7475, 0.6015]])

与numpy一样,随机初始化提供rand和randn两种方法。

构造一个矩阵全为 0,而且数据类型是 long:

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

输出:

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

直接传入数据构造张量:

x = torch.tensor([5.5, 3])
print(x)

输出:

tensor([5.5000, 3.0000])

通过已有tensor创建一个新的tensor:

x = torch.rand(5, 3)
x = x.new_ones(5, 3, dtype=torch.double)
# new_* methods take in sizes
print(x)

x = torch.randn_like(x, dtype=torch.float)
# override dtype!
print(x)
# result has the same size

输出:

tensor([[1., 1., 1.],
    [1., 1., 1.],
    [1., 1., 1.],
    [1., 1., 1.],
    [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.6138,  0.8007,  1.6560],
    [-0.1160,  1.0738,  0.5042],
    [ 0.3081,  0.0404,  0.1803],
    [-0.3866,  0.2987, -1.9679],
    [-1.0050,  0.9958, -0.5199]])

获取维度信息:

x = torch.rand(5, 3)
print(x.size())
print(x.size()[0])
print(x.size()[1])

输出:

torch.Size([5, 3])
5
3

可以看出,torch.Size()是一个元组,所以它支持左右的元组操作。

加法操作:

x = torch.rand(5, 3)
y = torch.rand(5, 3)
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(x + y)
print(torch.add(x, y))
print(result)

输出:

tensor([[0.2672, 1.6628, 0.6432],
    [1.1228, 0.8476, 0.4138],
    [1.7469, 0.4409, 1.0035],
    [1.2439, 0.6834, 0.9636],
    [1.2115, 1.6199, 1.1866]])
tensor([[0.2672, 1.6628, 0.6432],
    [1.1228, 0.8476, 0.4138],
    [1.7469, 0.4409, 1.0035],
    [1.2439, 0.6834, 0.9636],
    [1.2115, 1.6199, 1.1866]])
tensor([[0.2672, 1.6628, 0.6432],
    [1.1228, 0.8476, 0.4138],
    [1.7469, 0.4409, 1.0035],
    [1.2439, 0.6834, 0.9636],
    [1.2115, 1.6199, 1.1866]])

可以看出,pytorch对加法运算符进行了重载,能够进行tensor类型之间的加法,pytorch也提供了add方法实现两个tensor类型数据相加。add方法可以提供一个输出tensor作为参数,上面使用的result也赋值了相同的运算结果。

加法in-place:

x = torch.rand(5, 3)
y = torch.rand(5, 3)
print(y)
y.add_(x)
print(y)

输出:

tensor([[0.4575, 0.1560, 0.5231],
    [0.3615, 0.4968, 0.9983],
    [0.6981, 0.8572, 0.3183],
    [0.5831, 0.4591, 0.2261],
    [0.7476, 0.3067, 0.1562]])
tensor([[0.8333, 0.1667, 1.2496],
    [0.8277, 1.4037, 1.9814],
    [1.5074, 1.4336, 0.4321],
    [0.8253, 0.9932, 0.8753],
    [1.2419, 0.9924, 0.3691]])

可以看出使用 ==add()== 会直接改变y的值,是把x加到y上。
**==任何使张量会发生变化的操作都有一个前缀 '
'==**

改变tensor的形状和大小:

x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size()

输出:

torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

当view()传入的参数为-1时,该位置上的维度由其他维度上的参数决定,在本例中,x的大小为16,确定z的第二个维度是8,那么z的第一个维度上是16/8=2。

如果你有一个元素 tensor ,使用 .item() 来获得这个 value 。

x = torch.randn(1)
print(x)
print(x.item())

输出:

tensor([-0.9010])
-0.9009907841682434

二、pytorch自动微分

  自动求导(autograd)是深度学习框架的重要组成部分。在之前的作业中,我们使用numpy搭建神经网络,我们需要保存每层计算的A和Z的值,另外我们在定义激活函数的同时会定义对应激活函数求导后的函数,方便我们在反向传播的计算。
  但是torch.Tensor类中有属性 ==requires_grad== ,将其设置为True时会开始跟踪针对tensor的所有操作,完成计算后,可以调用 .backward() 来自动计算所有梯度。该张量的梯度将累积到 .grad 属性中。接下来通过官方的一个例子来理解以下:

import torch
x = torch.ones(2, 2, requires_grad=True)

y = x + 2
print(y)

z = y * y * 3
print(z)

out = z.mean()
print(out)

out.backward()
print(x.grad)

输出:

tensor([[3., 3.],
    [3., 3.]], grad_fn=)
tensor([[27., 27.],
    [27., 27.]], grad_fn=)
tensor(27., grad_fn=)
tensor([[4.5000, 4.5000],
    [4.5000, 4.5000]])

  具体推导过程如下:

在这里插入图片描述

  在对神经网络进行训练时我们需要将requieres_grad设置为True,记录梯度需要消耗大量内存,但是训练完成对模型评估时并不用记录梯度,可以将代码块使用 with torch.no_grad(): 包装起来。

总结

  学了官方文档的这两部分,个人感受是感觉学了挺多东西,又感觉什么也没学。接下来会讲解使用pytorch搭建一个简单的神经网络,动手实践才是王道。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇