1.2_Pytorch基础使用介绍


文档摘要

Pytorch基础使用介绍 Pytorch是什么? Pytorch是一个基于python的科学计算包,主要面向两部分受众: 一个为了充分发挥GPU能力而设计的Numpy的GPU版本替代方案 一个提供更大灵活性和速度的深度学习研究平台 本节将会介绍Pytorch的一些基本使用和操作,帮助你熟悉和上手Pytorch,让我们开始吧~ 1.Tensors Tensors(张量)的概念可以类比Numpy中的ndarrays,本质上就是一个多维数组,是任何运算和操作间数据流动的最基础形式。

Pytorch基础使用介绍

Pytorch是什么?

Pytorch是一个基于python的科学计算包,主要面向两部分受众:

  • 一个为了充分发挥GPU能力而设计的Numpy的GPU版本替代方案

  • 一个提供更大灵活性和速度的深度学习研究平台

本节将会介绍Pytorch的一些基本使用和操作,帮助你熟悉和上手Pytorch,让我们开始吧~

1.Tensors

Tensors(张量)的概念可以类比Numpy中的ndarrays,本质上就是一个多维数组,是任何运算和操作间数据流动的最基础形式。

首先让我们加载torch库

import torch

首先让我们来看下如何生成一些简单的Tensor

构建一个未初始化的5*3的空矩阵(张量)的代码如下:

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

输出:

<class 'torch.Tensor'> tensor([[7.7050e+31, 6.7415e+22, 1.2690e+31], [6.1186e-04, 4.6165e+24, 4.3701e+12], [7.5338e+28, 7.1774e+22, 3.7386e-14], [6.6532e-33, 1.8337e+31, 1.3556e-19], [1.8370e+25, 2.0616e-19, 4.7429e+30]])

注意,对于未初始化的张量,它的取值是不固定的,取决于它创建时分配的那块内存的取值。

torch.zerostorch.ones也是非常常用的Tensor初始化函数:

tensor_ones = torch.ones(2,3) print(tensor_ones) tensor_zeros = torch.zeros(2,3) print(tensor_zeros)

输出:

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

可以通过dtype属性来指定tensor的数据类型

这里我们再次构建一个使用0填充的tensor,将dtype属性设置为长整型,并打印结果的数据类型,注意观察区别

print(tensor_zeros.dtype) tensor_zeros_int = torch.zeros(2, 3, dtype=torch.long) print(tensor_zeros_int.dtype)

输出:

torch.float32 torch.int64

和Numpy类似,除了常见的0/1取值的初始化,我们还可以进行随机初始化,或者直接用现有数据进行张量的初始化。

torch.randtorch.randn 是两个常用的随机初始化函数

torch.rand用于生成服从区间[0,1)均匀分布的随机张量,示例:

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

输出:

tensor([[0.6544, 0.1733, 0.2569], [0.0680, 0.5781, 0.2667], [0.5051, 0.5366, 0.2776], [0.4903, 0.9934, 0.1181], [0.4497, 0.6201, 0.1952]])

torch.randn用于生成服从均值为0、方差为1正太分布的随机张量,示例:

x = torch.randn(4, 4) print(x)

输出:

tensor([[-1.2787, -1.8935, -0.1098, -0.5664], [ 1.2988, 0.5578, -1.7803, 0.9369], [ 0.7574, -0.4856, -1.5168, -0.5782], [ 0.9653, -1.0099, 0.4913, -0.1843]])

我们还可以直接用现有数据进行张量的初始化,例如python的列表List,例如:

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

输出:

tensor([5.5000, 3.0000])

也可以基于已有的tensor来创建新的tensor,通常是为了复用已有tensor的一些属性,包括shape和dtype。观察下面的示例:

x = torch.tensor([5.5, 3], dtype=torch.double) print(x.dtype) x = x.new_ones(5, 3) # new_* methods take in sizes print(x) x = torch.randn_like(x, dtype=torch.float) # override dtype! print(x) # result has the same size

输出:

torch.float64 tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=torch.float64) tensor([[-0.4643, -0.1942, -0.4497], [ 0.8090, 1.6753, -0.0678], [-1.1654, -0.3817, 0.3495], [ 2.3517, 1.7688, 0.0251], [-0.6314, -1.2776, 0.8398]])

可以看到,new_ones函数复用了x的dtype属性,randn_like函数复用了x的shape同时通过手动指定数据类型覆盖了原有的dtype属性

如果获取tensor的size?很简单

x_size = x.size() print(x_size) row, col = x_size print(row, col)

输出:

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

torch.Size本质上是一个tuple,通过上面的例子也可以看出,它支持元组的操作。

最后介绍一个非常实用的函数torch.arange,用于生成一定范围内等间隔的一维数组。参数有三个,分别是范围的起始值、范围的结束值和步长,使用示例:

torch.arange(1, 10, 1)

输出:

tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])

2.Operations

Operations(操作)涉及的语法和函数很多,大多数都是相通的,下面我们列举一些常用操作及其用法示例。

首先来看下张量间的元素级的四则运算,加减乘除的用法

有多种不同的使用方法,以加法为例:语法1

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

输出:

tensor([[ 1.7110, -0.0545, 0.3557], [ 0.1074, 2.3876, 1.2455], [-0.1204, 1.1829, 0.6250], [ 0.0873, 1.3114, 1.0403], [-0.6172, 1.2261, -1.0718]])

加法:语法2

z2 = torch.add(x, y) print(z2)

输出:

tensor([[ 1.7110, -0.0545, 0.3557], [ 0.1074, 2.3876, 1.2455], [-0.1204, 1.1829, 0.6250], [ 0.0873, 1.3114, 1.0403], [-0.6172, 1.2261, -1.0718]])

加法:语法3,通过参数的形式进行输出tensor的保存

z3 = torch.empty(5, 3) torch.add(x, y, out=z3) print(z3)

输出:

tensor([[ 1.7110, -0.0545, 0.3557], [ 0.1074, 2.3876, 1.2455], [-0.1204, 1.1829, 0.6250], [ 0.0873, 1.3114, 1.0403], [-0.6172, 1.2261, -1.0718]])

加法:语法4,通过in-place操作直接将计算结果覆盖到y上

y.add_(x) print(y)

输出:

tensor([[ 1.7110, -0.0545, 0.3557], [ 0.1074, 2.3876, 1.2455], [-0.1204, 1.1829, 0.6250], [ 0.0873, 1.3114, 1.0403], [-0.6172, 1.2261, -1.0718]])

在Pytorch中,我们约定凡是会覆盖函数调用主体的in-place操作,都以后缀_结束,例如:x.copy_(y)x.t_(),都会改变x的取值。

张量之间的减法、点乘和点除的用法是类似的:

a =torch.randn(2,3) print(a) b =torch.randn(2,3) print(b) c =torch.sub(a, b) print(c) d =torch.mul(a, b) print(d) e =torch.div(a, b) print(e)

运行后,输出的内容如下:

tensor([[ 0.3580, -0.5780, -0.6883], [ 0.0883, -0.9064, 0.5411]]) tensor([[-1.7065, 0.7099, 0.6574], [-1.3688, 0.1767, 0.3669]]) tensor([[ 2.0645, -1.2880, -1.3457], [ 1.4571, -1.0831, 0.1742]]) tensor([[-0.6109, -0.4104, -0.4525], [-0.1209, -0.1602, 0.1986]]) tensor([[-0.2098, -0.8142, -1.0471], [-0.0645, -5.1292, 1.4748]])

当然,张量和常数间的基本运算也是支持的

a =torch.randn(2,3) print(a) b =torch.mul(a,10) print(b) c =torch.div(a,10) print(c)

运行后,输出的内容如下:

tensor([[-1.6306, 0.2616, 0.0606], [-0.4596, -1.3998, 0.9431]]) tensor([[-16.3055, 2.6162, 0.6061], [ -4.5963, -13.9981, 9.4307]]) tensor([[-0.1631, 0.0262, 0.0061], [-0.0460, -0.1400, 0.0943]])

上面介绍了torch.mul用来计算张量间的点乘,而进行矩阵乘法计算需要用到torch.mm函数

a =torch.randn(2, 3) print(a) b =torch.randn(3, 2) print(b) c =torch.mm(a, b) print(c)

输出的内容如下:

tensor([[-1.0442, 0.2439, 1.3658], [-1.0813, 0.3178, 0.4006]]) tensor([[ 0.4317, 0.3242], [-0.2085, 0.5584], [ 0.7991, 0.0926]]) tensor([[ 0.5898, -0.0759], [-0.2129, -0.1360]])

下面我们来看看其他的一些基础操作。

torch.abs函数可以用来计算张量的绝对值

a =torch.randn(2, 3) print(a) b =torch.abs(a) print(b)

输出:

tensor([[-0.8631, 0.3728, 1.0428], [ 0.5944, 0.5572, 0.6256]]) tensor([[0.8631, 0.3728, 1.0428], [0.5944, 0.5572, 0.6256]])

torch.pow函数用于进行求幂操作

import torch a = torch.randn(2, 3) print(a) b = torch.pow(a, 2) print(b)

输出:

tensor([[ 0.0115, 0.2041, -2.9827], [ 0.6467, 0.3175, -0.4201]]) tensor([[1.3127e-04, 4.1647e-02, 8.8963e+00], [4.1824e-01, 1.0082e-01, 1.7648e-01]])

在Pytorch中,我们可以使用标准的Numpy-like的索引操作,例如:

print(x[:, 1])

输出:

tensor([-0.0211, -1.4157, 0.1453, -1.3401, -0.8556])

resize操作:

如果你想要对tensor进行类似resize/reshape的操作,你可以使用torch.view

x = torch.randn(4, 4) y = x.view(16) z = x.view(-1, 8) # 使用-1时pytorch将会自动根据其他维度进行推导 print(x.size(), y.size(), z.size())

输出:

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

concate操作:

torch.cat函数用于将输入的tensor序列进行concate拼接操作

x = torch.randn(2, 3) print(x) x_cat_dim0 = torch.cat((x,x,x), dim=0) x_cat_dim1 = torch.cat((x,x,x), dim=1) print(x_cat_dim0) print(x_cat_dim1)

输出:

tensor([[ 0.6580, -1.0969, -0.4614], [-0.1034, -0.5790, 0.1497]]) tensor([[ 0.6580, -1.0969, -0.4614], [-0.1034, -0.5790, 0.1497], [ 0.6580, -1.0969, -0.4614], [-0.1034, -0.5790, 0.1497], [ 0.6580, -1.0969, -0.4614], [-0.1034, -0.5790, 0.1497]]) tensor([[ 0.6580, -1.0969, -0.4614, 0.6580, -1.0969, -0.4614, 0.6580, -1.0969, -0.4614], [-0.1034, -0.5790, 0.1497, -0.1034, -0.5790, 0.1497, -0.1034, -0.5790, 0.1497]])

如果有一个tensor,只包含一个元素,你可以使用.item()来获得它对应的Python形式的取值

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

输出:

tensor([0.4448]) torch.Size([1]) 0.4447539746761322 <class 'float'>

通常我们在需要控制张量的取值范围不越界时,需要用到torch.clamp函数,它可以对输入参数按照自定义的范围进行裁剪,最后将参数裁剪的结果作为输出。输入参数一共有三个,分别是需要进行裁剪的Tensor变量、裁剪的下边界和裁剪的上边界

import torch a =torch.randn(2,3) print(a) b =torch.clamp(a, -0.5, 0.5) print(b)

输出的内容如下:

tensor([[-0.1076, 1.4202, 1.5780], [-1.3722, -1.7166, -1.0581]]) tensor([[-0.1076, 0.5000, 0.5000], [-0.5000, -0.5000, -0.5000]])

想要学习更多?这里的官方教程有更多关于tensor操作的介绍,介绍了100多个Tensor运算,包括转置,索引,切片,数学运算,线性代数,随机数等。

3.Numpy桥梁

Pytorch中可以很方便的将Torch的Tensor同Numpy的ndarray进行互相转换,相当于在Numpy和Pytorch间建立了一座沟通的桥梁,这将会让我们的想法实现起来变得非常方便。

注:Torch Tensor 和 Numpy ndarray 底层是分享内存空间的,也就是说改变其中之一会同时改变另一个(前提是你是在CPU上使用Torch Tensor)。

将一个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.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) np.add(a, 1, out=a) print(a) print(b)

输出:

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

注:所有CPU上的Tensors,除了CharTensor均支持与Numpy的互相转换

4.CUDA Tensors

1.1 深度学习环境配置一节,我们介绍了如何配置深度学习环境,以及如何安装GPU版本的pytorch,可以通过以下代码进行验证:

print(torch.cuda.is_available())

如果输出True,代表你安装了GPU版本的pytorch

True

Tensors可以通过.to函数移动到任何我们定义的设备device上,观察如下代码:

# let us run this cell only if CUDA is available # We will use ``torch.device`` objects to move tensors in and out of GPU if torch.cuda.is_available(): device = torch.device("cuda") # a CUDA device object y = torch.ones_like(x, device=device) # directly create a tensor on GPU x = x.to(device) # or just use strings ``.to("cuda")`` z = x + y print(z) print(z.to("cpu", torch.double)) # ``.to`` can also change dtype together!

tensor([0.5906], device='cuda:0')
tensor([0.5906], dtype=torch.float64)

本文作者

初稿:安晟

第2版:游璐颖

校对:安晟

参考资料

  1. 《Pytorch深度学习》

  2. Pytorch官网


作者与出处
原作者: Datawhale
来源:Datawhale
许可证:GPL-3.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: Datawhale 转发
评论区 (0)
U