第二章:PyTorch基础知识1

链接

PyTorch相关资源

PyTorch之所以被越来越多的人使用,不仅在于其完备的教程,还受益于许多相关的资源,在这里,我们列举了相关的优质资源希望能帮助到各位同学。

Awesome-pytorch-list:目前已获12K Star,包含了NLP,CV,常见库,论文实现以及Pytorch的其他项目。

PyTorch官方文档:官方发布的文档,十分丰富。

Pytorch-handbook:GitHub上已经收获14.8K,pytorch手中书。

PyTorch官方社区:在这里你可以和开发pytorch的人们进行交流。

2.1 张量

2.1.1 简介

几何代数中定义的张量是基于向量和矩阵的推广,比如我们可以将标量视为零阶张量,矢量可以视为一阶张量,矩阵就是二阶张量。

  • 0维张量/标量 标量是一个数字
  • 1维张量/向量 1维张量称为“向量”
  • 2维张量 2维张量称为矩阵
  • 3维张量 公用数据存储在张量 时间序列数据 股价 文本数据 彩色图片(RGB)

2.1.2 创建tensor

在接下来的内容中,我们将介绍几种创建tensor的方法。

  1. 我们可以通过torch.rand()的方法,构造一个随机初始化的矩阵:
import torch
x = torch.rand(4, 3) 
print(x)

###############################
tensor([[0.7569, 0.4281, 0.4722],
        [0.9513, 0.5168, 0.1659],
        [0.4493, 0.2846, 0.4363],
        [0.5043, 0.9637, 0.1469]])
  1. 我们可以通过torch.zeros()构造一个矩阵全为 0,并且通过dtype设置数据类型为 long
import torch
x = torch.zeros(4, 3, dtype=torch.long)
print(x)

###############################
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
  1. 我们可以通过torch.tensor()直接使用数据,构造一个张量:
import torch
x = torch.tensor([5.5, 3]) 
print(x)

###############################
tensor([5.5000, 3.0000])
  1. 基于已经存在的 tensor,创建一个 tensor :
x = x.new_ones(4, 3, dtype=torch.double) # 创建一个新的tensor,返回的tensor默认具有相同的 torch.dtype和torch.device
# 也可以像之前的写法 x = torch.ones(4, 3, dtype=torch.double)
print(x)
x = torch.randn_like(x, dtype=torch.float)
# 重置数据类型
print(x)
# 结果会有一样的size
# 获取它的维度信息
print(x.size())
print(x.shape)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 2.7311, -0.0720,  0.2497],
        [-2.3141,  0.0666, -0.5934],
        [ 1.5253,  1.0336,  1.3859],
        [ 1.3806, -0.6965, -1.2255]])
torch.Size([4, 3])
torch.Size([4, 3])

返回的torch.Size其实是一个tuple,⽀持所有tuple的操作。

还有一些常见的构造Tensor的函数:
第二章:PyTorch基础知识1_第1张图片

2.1.3 张量的操作

在接下来的内容中,我们将介绍几种常见的张量的操作方法:

  1. 加法操作:
import torch
# 方式1
y = torch.rand(4, 3) 
print(x + y)

# 方式2
print(torch.add(x, y))

# 方式3 提供一个输出 tensor 作为参数
# 这里的 out 不需要和真实的运算结果保持维数一致,但是会有警告提示!
result = torch.empty(5, 3) 
torch.add(x, y, out=result) 
print(result)

# 方式4 in-place
y.add_(x) 
print(y)
tensor([[ 2.8977,  0.6581,  0.5856],
        [-1.3604,  0.1656, -0.0823],
        [ 2.1387,  1.7959,  1.5275],
        [ 2.2427, -0.3100, -0.4826]])
tensor([[ 2.8977,  0.6581,  0.5856],
        [-1.3604,  0.1656, -0.0823],
        [ 2.1387,  1.7959,  1.5275],
        [ 2.2427, -0.3100, -0.4826]])
tensor([[ 2.8977,  0.6581,  0.5856],
        [-1.3604,  0.1656, -0.0823],
        [ 2.1387,  1.7959,  1.5275],
        [ 2.2427, -0.3100, -0.4826]])
tensor([[ 2.8977,  0.6581,  0.5856],
        [-1.3604,  0.1656, -0.0823],
        [ 2.1387,  1.7959,  1.5275],
        [ 2.2427, -0.3100, -0.4826]])
  1. 索引操作:(类似于numpy)

需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改。如果不想修改,可以考虑使用copy()等方法

print(x)

###############################
tensor([[ 2.7311, -0.0720,  0.2497],
        [-2.3141,  0.0666, -0.5934],
        [ 1.5253,  1.0336,  1.3859],
        [ 1.3806, -0.6965, -1.2255]])
# 取第二列
print(x[:, 1]) 

###############################
tensor([-0.0720,  0.0666,  1.0336, -0.6965])
y = x[0,:]
y += 1
print(y)
print(x[0, :]) # 源tensor也被改了了
###############################
tensor([3.7311, 0.9280, 1.2497])
tensor([3.7311, 0.9280, 1.2497])

改变大小:如果你想改变一个 tensor 的大小或者形状,你可以使用 torch.view:

x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
print(x.size(), y.size(), z.size())
###############################
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

注意 view() 返回的新tensor与源tensor共享内存(其实是同一个tensor),也即更改其中的一个,另 外一个也会跟着改变。(顾名思义,view仅仅是改变了对这个张量的观察⻆度)

x += 1
print(x)
print(y) # 也加了了1

###############################
tensor([[ 1.3019,  0.3762,  1.2397,  1.3998],
        [ 0.6891,  1.3651,  1.1891, -0.6744],
        [ 0.3490,  1.8377,  1.6456,  0.8403],
        [-0.8259,  2.5454,  1.2474,  0.7884]])
tensor([ 1.3019,  0.3762,  1.2397,  1.3998,  0.6891,  1.3651,  1.1891, -0.6744,
         0.3490,  1.8377,  1.6456,  0.8403, -0.8259,  2.5454,  1.2474,  0.7884])

所以如果我们想**返回一个真正新的副本(即不共享内存)**该怎么办呢?Pytorch还提供了一 个 reshape() 可以改变形状,但是此函数并不能保证返回的是其拷贝,所以不推荐使用。推荐先用 clone 创造一个副本然后再使用 view 。

注意:使用 clone 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor 。

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

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

###############################
<class 'torch.Tensor'>
<class 'float'>

PyTorch中的 Tensor 支持超过一百种操作,包括转置、索引、切片、数学运算、线性代数、随机数等等,可参考官方文档。

2.1.4 广播机制

当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。

x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)

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

由于 x 和 y 分别是1行2列和3行1列的矩阵,如果要计算 x + y ,那么 x 中第一行的2个元素被广播 (复制)到了第二行和第三行,⽽ y 中第⼀列的3个元素被广播(复制)到了第二列。如此,就可以对2 个3行2列的矩阵按元素相加。

你可能感兴趣的:(深度学习,python)