PyTorch的安装和基本操作,tensor如何与numpy互相转换?如何将CPU数据转换到GPU?

近几年,人工智能的深度学习大热,相关从业者的薪资水平明显高于不少行业,这主要是因为深度学习领域对从业者的要求较高,相关人才有些供不应求——从业者要具备扎实的数学功底,还要熟悉所使用的硬件平台特性,掌握一门扎实的编程语言,尽可能高效的把理论付诸实践。

同样的任务,可能水平欠佳的程序员设计的算法需要几天才能完成,而较高水准的算法几小时就完成了。

好在,愈发成熟的各种深度学习框架大大方便了从业者,从业者甚至无需再关心硬件平台,也无需再把大量精力花费在算法设计上,就能轻易的以不错的性能实现自己的深度学习网络。

关于深度学习框架,我较深入的使用过 Caffe、tensorflow,但是最终还是选择了 PyTorch。

PyTorch 是什么

我认为,与其说 PyTorch 是一个深度学习框架,倒不如说它是一个深度学习,这一点可以在以后的使用中得出。按照官网上的说法,PyTorch 是一个 Python 科学计算包,有两类受众:

  • 替换 NumPy 库,更方便的使用 GPUs 高效计算
  • 充当深度学习研究平台,最大限度的提供灵活性和效率

关于 PyTorch 的安装,可以参考官网,已经非常傻瓜式了,本文就不赘述了。

开始

Tensors(张量)

PyTorch 中的 tensor 类似于 NumPy 中的 ndarray,只不过 tensor 能够更加方便的使用 GPU 加速运算,在使用 tensor 之前,需要导入 PyTorch 包:

import torch

创建一个没有初始化的 5x3 的矩阵:

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

输出如下:

tensor([[-7.1077e+12,  4.5558e-41,  4.2319e-11],
        [ 3.0942e-41,  1.0177e+31,  2.2017e+12],
        [ 2.8488e-14,  9.6809e+24,  1.0880e-19],
        [ 1.0874e-19,  2.5443e+30,  9.4727e+21],
        [ 2.4835e+27,  2.5428e+30,  1.0877e-19]])

创建一个随机初始化的矩阵:

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

输出如下:

tensor([[0.6363, 0.5365, 0.6489],
        [0.8479, 0.3439, 0.3546],
        [0.8024, 0.7198, 0.8319],
        [0.6590, 0.1750, 0.7466],
        [0.8664, 0.7331, 0.1298]])

创建一个数据类型为 torch.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 = x.new_ones(5, 3, dtype=torch.double)
# new_* 方法使用不同的 size
print(x)

x = torch.randn_like(x, dtype=torch.float)   
# 覆盖数据类型,但是 size 保持不变
print(x)                                      

输出如下:

tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.2295,  0.2996,  0.0104],
        [ 0.5513,  0.0489,  0.3046],
        [-0.0529,  0.8116, -0.2754],
        [ 2.3672,  0.1456, -1.3679],
        [ 0.4731,  0.0102,  0.9750]])

获取它的 size:

print(x.size())

输出如下:

torch.Size([5, 3])

torch.Size 实际上是一个 tuple,所以它支持所有的 tuple 操作。

Operations(操作)

PyTorch 中的操作有多个语法,在接下来的例子中,我们将通过加法操作了解这一点:

加法:语法 1

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

输出:

tensor([[ 0.7623,  0.4833,  0.7200],
        [ 0.8453,  0.4220,  1.2202],
        [ 0.8108,  1.6514,  0.3858],
        [ 2.7137,  0.1767, -1.2774],
        [ 0.7659,  0.4483,  1.2968]])

加法:语法2

print(torch.add(x, y))

输出:

tensor([[ 0.7623,  0.4833,  0.7200],
        [ 0.8453,  0.4220,  1.2202],
        [ 0.8108,  1.6514,  0.3858],
        [ 2.7137,  0.1767, -1.2774],
        [ 0.7659,  0.4483,  1.2968]])

加法:通过参数的形式把结果输出给指定张量

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

输出:

tensor([[ 0.7623,  0.4833,  0.7200],
        [ 0.8453,  0.4220,  1.2202],
        [ 0.8108,  1.6514,  0.3858],
        [ 2.7137,  0.1767, -1.2774],
        [ 0.7659,  0.4483,  1.2968]])

加法:in-place 操作

# adds x to y
y.add_(x)
print(y)

输出:

tensor([[ 0.7623,  0.4833,  0.7200],
        [ 0.8453,  0.4220,  1.2202],
        [ 0.8108,  1.6514,  0.3858],
        [ 2.7137,  0.1767, -1.2774],
        [ 0.7659,  0.4483,  1.2968]])

通过_符号,PyTorch 中的操作将变为 in-place 操作,举个例子:x.copy(y),x.t(),这两个操作的最终结果会作用在 x 上。

可以像标准的 NumPy 库那样对 tensor 使用切片操作:

print(x[:, 1])

输出:

tensor([0.2996, 0.0489, 0.8116, 0.1456, 0.0102])

resize:如果希望对 tensor 实现 resize/reshape 操作,可以使用 torch.view

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

如果 tensor 中只有一个元素,可以使用 .item() 把这个元素以 Python 标准 number 的形式取出:

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

输出:

tensor([-1.4181])
-1.4181468486785889

更多的操作可以参考官方文档

与 NumPy 互相转换

PyTorch 中的 Tensor 和 NumPy 中的 array 可以共享一块内存去区域(当 tensor 位于 CPU 中时),改变其中一个,另一个也会随之改变。

将 Tensor 转换为 Numpy 中的 Array

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

输出:

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

将张量 a 转换为 numpy 是非常简单的:

b = a.numpy()
print(b)

输出:

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

正如刚才所说,此时 a、b 共享一块数据内存,我们改变 a,b也会随之改变:

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

输出:

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

将 NumPy 中的 Array 转换为 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)

出了 CharTensor 类型的 Tensor,CPU 中的其他所有 Tensor 都支持与 NumPy 互相转换。

CUDA Tensor

PyTorch 中的 Tensor 可以简单的通过 .to() 方法移到任意的 device 中:

# 下面的代码只有当 CUDA 可用时才运行
if torch.cuda.is_available():
    device = torch.device("cuda")
    # 直接在 GPU 上创建张量    
    y = torch.ones_like(x, device=device)  
    # 或者使用 .to 方法
    x = x.to(device)                       
    z = x + y
    print(z)
    # .to 方法同时也可以改变数据类型
    print(z.to("cpu", torch.double))    

输出:

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

本文主要参考 PyTorch 官方文档: https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py

阅读更多:   PyTorch基础
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif