PyTorch 笔记Ⅰ——PyTorch 张量与基本操作

What is PyTorch?

此部分来源于官网文档

PyTorch 是一个基于 Python 的科学计算包,主要定位两类人群:

  • NumPy 的替代品,可以利用 GPU 的性能进行计算。
  • 深度学习研究平台拥有足够的灵活性和速度

开始

Tensors(张量)

Tensors 类似于 NumPy 的 ndarrays ,同时 Tensors 可以使用 GPU 进行计算。

import torch

创建一个 5x3 的空矩阵, 不初始化:

x = torch.empty(5, 3)
print(x)
tensor([[1.5989e-07, 7.6931e-43, 1.5989e-07],
        [7.6931e-43, 1.5989e-07, 7.6931e-43],
        [1.5989e-07, 7.6931e-43, 1.5989e-07],
        [7.6931e-43, 1.5989e-07, 7.6931e-43],
        [1.5989e-07, 7.6931e-43, 1.5989e-07]])

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

x = torch.rand(5, 3)
print(x)
tensor([[0.3236, 0.6139, 0.0540],
        [0.0867, 0.8946, 0.6353],
        [0.0314, 0.8663, 0.9188],
        [0.9622, 0.9310, 0.3130],
        [0.6608, 0.5655, 0.1959]])

创建一个零矩阵,数据类型为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]])

使用常量创建tensor:

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

根据现有的张量创建张量。 这些方法将重用输入张量的属性,例如, dtype等,除非设置新的值进行覆盖,注意,在new_*中不会重用size,因此仍然要指定size。而在torch.randn_like中,所有属性都会重用,包括size以及dype

x = x.new_ones(5, 3, dtype=torch.double)      # new_* 方法来创建对象
print(x)

x = torch.randn_like(x, dtype=torch.float)    # 覆盖 dtype!
print(x)                                      #  对象的size 是相同的,只是值和类型发生了变化
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.4432, -0.5720,  1.0183],
        [-0.2520,  0.0191,  0.9229],
        [ 1.2574, -0.4702,  0.5528],
        [-0.2717, -0.2984,  1.0898],
        [ 0.6737, -1.7505,  0.1010]])

获取张量维度,其功能等同于 numpy 中的 shape 操作以及 tensorflow 中的 shape 操作

print(x.size())
torch.Size([5, 3])

torch.Size 返回值是 tuple类型, 所以它支持tuple类型的所有操作

操作

加法运算。

加法1:

y = torch.rand(5, 3)
print(x + y)
tensor([[ 1.1890,  0.1487,  1.8704],
        [ 0.5246,  0.4035, -1.0128],
        [-0.9750,  1.0738,  0.4958],
        [-0.5518,  0.7156,  0.4769],
        [ 0.2036,  1.3194, -0.2255]])

加法2

print(torch.add(x, y))
tensor([[ 1.1890,  0.1487,  1.8704],
        [ 0.5246,  0.4035, -1.0128],
        [-0.9750,  1.0738,  0.4958],
        [-0.5518,  0.7156,  0.4769],
        [ 0.2036,  1.3194, -0.2255]])

提供输出tensor作为参数

result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
tensor([[ 1.1890,  0.1487,  1.8704],
        [ 0.5246,  0.4035, -1.0128],
        [-0.9750,  1.0738,  0.4958],
        [-0.5518,  0.7156,  0.4769],
        [ 0.2036,  1.3194, -0.2255]])

将x直接加到y上面,并且y变量的值会被替换

# adds x to y
y.add_(x)
print(y)
tensor([[ 1.1890,  0.1487,  1.8704],
        [ 0.5246,  0.4035, -1.0128],
        [-0.9750,  1.0738,  0.4958],
        [-0.5518,  0.7156,  0.4769],
        [ 0.2036,  1.3194, -0.2255]])

任何 以_ 结尾的操作都会用结果替换原变量.
    例如: x.copy_(y), x.t_(), 都会改变 x

你可以使用与NumPy索引方式相同的操作来进行对张量的操作

print(x[:, 1])
tensor([-0.5720,  0.0191, -0.4702, -0.2984, -1.7505])
维度调整

torch.view: 可以改变张量的维度和大小,与 Numpy 的 reshape 以及 tensorflow 中的 reshape 类似

x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  #  size -1 从其他维度推断
print(x.size(), y.size(), z.size())
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

如果你有只有一个元素的张量,使用.item()来得到Python数据类型的数值,或者使用.numpy()操作将获得的torch tensor转为numpy数组,利用下标获取数值

x = torch.randn(1)
print(x)
print(x.item())
print(x.numpy()[0])
tensor([0.5512])
0.5511747598648071
0.55117476
a = 1
b = a
a,b
(1, 1)
a=2
a,b
(2, 1)

NumPy 转换

Torch Tensor 与 NumPy 数组可以互相转换

Torch Tensor与NumPy数组共享底层内存地址,修改一个会导致另一个的变化。

将一个Torch Tensor转换为NumPy数组

a = torch.ones(5)
print(a)
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
print(b)
[1. 1. 1. 1. 1.]

观察numpy数组的值是如何改变的。

a.add_(1)
print(a)
print(b)
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]

NumPy Array 转化成 Torch Tensor

使用from_numpy自动转化

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)

所有的 Tensor 类型默认都是基于CPU, CharTensor 类型不支持到
NumPy 的转换.

CUDA 张量

使用.to 方法 可以将Tensor移动到任何设备中

# is_available 函数判断是否有cuda可以使用
# ``torch.device``将张量移动到指定的设备中
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA 设备对象
    y = torch.ones_like(x, device=device)  # 直接从GPU创建张量
    x = x.to(device)                       # 或者直接使用``.to("cuda")``将张量移动到cuda中
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # ``.to`` 也会对变量的类型做更改
tensor([1.5512], device='cuda:0')
tensor([1.5512], dtype=torch.float64)

PyTorch 基础 : 张量

此部分来源于总结

在第一章中我们已经通过官方的入门教程对PyTorch有了一定的了解,这一章会详细介绍PyTorch 里面的基础知识。
全部掌握了这些基础知识,在后面的应用中才能更加快速进阶,如果你已经对PyTorch有一定的了解,可以跳过此章

# 首先要引入相关的包
import torch
import numpy as np
#打印一下版本
torch.__version__
'1.6.0'

张量(Tensor)

张量的英文是Tensor,它是PyTorch里面基础的运算单位,与Numpy的ndarray相同都表示的是一个多维的矩阵。
与ndarray的最大区别就是,PyTorch的Tensor可以在 GPU 上运行,而 numpy 的 ndarray 只能在 CPU 上运行,在GPU上运行大大加快了运算速度。

下面我们生成一个简单的张量

x = torch.rand(2, 3)
x
tensor([[0.9021, 0.7231, 0.2909],
        [0.1218, 0.3663, 0.9550]])

以上生成了一个,2行3列的的矩阵,我们看一下他的大小:

# 可以使用与numpy相同的shape属性查看
print(x.shape)
# 也可以使用size()函数,返回的结果都是相同的
print(x.size())
torch.Size([2, 3])
torch.Size([2, 3])

张量(Tensor)是一个定义在一些向量空间和一些对偶空间的笛卡儿积上的多重线性映射,其坐标是|n|维空间内,有|n|个分量的一种量, 其中每个分量都是坐标的函数, 而在坐标变换时,这些分量也依照某些规则作线性变换。r称为该张量的秩或阶(与矩阵的秩和阶均无关系)。 (来自百度百科)

下面我们来生成一些多维的张量:

y=torch.rand(2,3,4,5)
print(y.size())
y
torch.Size([2, 3, 4, 5])





tensor([[[[0.3608, 0.2341, 0.7449, 0.2273, 0.0767],
          [0.8826, 0.1952, 0.6882, 0.1852, 0.0324],
          [0.5118, 0.7542, 0.1401, 0.4395, 0.9141],
          [0.0998, 0.1936, 0.9417, 0.8459, 0.1106]],

         [[0.6193, 0.9188, 0.9058, 0.4982, 0.9744],
          [0.3164, 0.3069, 0.8765, 0.3899, 0.2779],
          [0.8015, 0.7960, 0.4541, 0.2846, 0.9723],
          [0.1232, 0.1719, 0.4083, 0.5277, 0.3099]],

         [[0.2295, 0.9148, 0.0095, 0.8720, 0.4099],
          [0.8734, 0.1698, 0.3172, 0.8624, 0.4462],
          [0.3748, 0.7684, 0.6080, 0.5535, 0.2073],
          [0.4695, 0.0886, 0.5452, 0.8353, 0.1007]]],


        [[[0.7090, 0.0563, 0.6193, 0.7464, 0.4248],
          [0.6674, 0.1305, 0.2476, 0.0790, 0.5798],
          [0.2115, 0.1001, 0.3890, 0.3777, 0.8117],
          [0.7709, 0.7029, 0.5017, 0.3924, 0.9483]],

         [[0.8832, 0.5198, 0.7987, 0.2761, 0.3525],
          [0.7932, 0.8993, 0.8831, 0.9356, 0.5567],
          [0.8657, 0.4393, 0.6616, 0.9381, 0.3337],
          [0.9825, 0.2287, 0.1781, 0.1158, 0.7819]],

         [[0.1964, 0.5276, 0.4228, 0.7117, 0.5417],
          [0.9459, 0.6197, 0.0609, 0.0450, 0.3865],
          [0.3918, 0.5710, 0.0290, 0.4509, 0.9952],
          [0.7719, 0.1701, 0.8916, 0.8781, 0.4435]]]])

在同构的意义下,第零阶张量 (r = 0) 为标量 (Scalar),第一阶张量 (r = 1) 为向量 (Vector), 第二阶张量 (r = 2) 则成为矩阵 (Matrix),第三阶以上的统称为多维张量。

其中要特别注意的就是标量,我们先生成一个标量:

#我们直接使用现有数字生成
scalar =torch.tensor(3.1433223)
print(scalar)
#打印标量的大小
scalar.size()
tensor(3.1433)
torch.Size([])

对于标量,我们可以直接使用 .item() 从中取出其对应的python对象的数值

scalar.item()
3.143322229385376

特别的:如果张量中只有一个元素的tensor也可以调用tensor.item方法

tensor = torch.tensor([3.1433223]) 
print(tensor)
tensor.size()
tensor([3.1433])
torch.Size([1])
tensor.item()
3.143322229385376

基本类型

Tensor的基本数据类型有五种:

  • 32位浮点型:torch.FloatTensor。(默认)
  • 64位整型:torch.LongTensor。
  • 32位整型:torch.IntTensor。(默认)
  • 16位整型:torch.ShortTensor。
  • 64位浮点型:torch.DoubleTensor。

除以上数字类型外,还有
byte和chart型

# 转为64位整型,舍弃小数点
long=tensor.long()
long
tensor([3])
# 转为16维浮点型,保留4位小数
half=tensor.half()
half
tensor([3.1426], dtype=torch.float16)
# 转为32位整型
int_t=tensor.int()
int_t
tensor([3], dtype=torch.int32)
# 转为16维浮点型
flo = tensor.float()
flo
tensor([3.1433])
# 转为16位整型
short = tensor.short()
short
tensor([3], dtype=torch.int16)
# 转为8位整型
ch = tensor.char()
ch
tensor([3], dtype=torch.int8)
# 转为8位整型
bt = tensor.byte()
bt
tensor([3], dtype=torch.uint8)

Numpy转换

使用numpy方法将Tensor转为ndarray

a = torch.randn((3, 2))
# tensor转化为numpy
numpy_a = a.numpy()
print(numpy_a)
[[ 0.868098   -1.5622252 ]
 [-1.1009778  -0.63940954]
 [-0.20064461  1.4787067 ]]

numpy转化为Tensor

torch_a = torch.from_numpy(numpy_a)
torch_a
tensor([[ 0.8681, -1.5622],
        [-1.1010, -0.6394],
        [-0.2006,  1.4787]])

Tensor和numpy对象共享内存,所以他们之间的转换很快,而且几乎不会消耗什么资源。但这也意味着,如果其中一个变了,另外一个也会随之改变。

设备间转换

一般情况下可以使用.cuda方法将tensor移动到gpu,这步操作需要cuda设备支持

cpu_a=torch.rand(4, 3)
cpu_a.type()
'torch.FloatTensor'
gpu_a=cpu_a.cuda()
gpu_a.type()
'torch.cuda.FloatTensor'

使用.cpu方法将tensor移动到cpu

cpu_b=gpu_a.cpu()
cpu_b.type()
'torch.FloatTensor'

如果我们有多GPU的情况,可以使用to方法来确定使用那个设备,这里只做个简单的实例:

#使用torch.cuda.is_available()来确定是否有cuda设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
#将tensor传送到设备
gpu_b=cpu_b.to(device)
gpu_b.type()
cuda





'torch.cuda.FloatTensor'

初始化

Pytorch中有许多默认的初始化方法可以使用

# 使用[0,1]均匀分布随机初始化二维数组
rnd = torch.rand(5, 3)
rnd
tensor([[0.9463, 0.6583, 0.2713],
        [0.1039, 0.2138, 0.2138],
        [0.2021, 0.0531, 0.5797],
        [0.4528, 0.9166, 0.7963],
        [0.9315, 0.4659, 0.2938]])
# 初始化,使用1填充
one = torch.ones(2, 2)
one
tensor([[1., 1.],
        [1., 1.]])
# 初始化,使用0填充
zero=torch.zeros(2,2)
zero
tensor([[0., 0.],
        [0., 0.]])
# 初始化一个单位矩阵,即对角线为1 其他为0
eye=torch.eye(2,2)
eye
tensor([[1., 0.],
        [0., 1.]])

常用方法

PyTorch中对张量的操作api 和 NumPy 非常相似,如果熟悉 NumPy 中的操作,那么他们二者基本是一致的:

x = torch.randn(3, 3)
print(x)
tensor([[-0.3830,  0.9858, -0.2048],
        [ 2.1059,  0.1554,  0.8260],
        [-1.1152,  0.8000, -0.1410]])
# 沿着行取最大值,返回最大值以及最大值索引
max_value, max_idx = torch.max(x, dim=1)
print(max_value, max_idx)
tensor([0.9858, 2.1059, 0.8000]) tensor([1, 0, 1])
# 每行 x 求和
sum_x = torch.sum(x, dim=1)
print(sum_x)
tensor([ 0.3980,  3.0874, -0.4562])
y=torch.randn(3, 3)
z = x + y
print(z)
tensor([[ 1.8947,  1.7645,  1.0793],
        [ 3.6871, -2.8621,  1.0421],
        [ 0.3706,  0.7725, -1.1966]])

正如官方60分钟教程中所说,以_为结尾的,均会改变调用值

# add 完成后x的值改变了
x.add_(y)
print(x)
tensor([[ 1.8947,  1.7645,  1.0793],
        [ 3.6871, -2.8621,  1.0421],
        [ 0.3706,  0.7725, -1.1966]])

张量的基本操作都介绍的的差不多了,下一章介绍PyTorch的自动求导机制

torch.Tensor 基本张量类型

数据来源于 Pytorch 1.6.0
torch.Tensor 是包含单一数据类型元素的多维矩阵。

Torch定义了10种具有CPU和GPU变量的张量类型:

Data type

dtype

CPU tensor

GPU tensor

32-bit floating point

torch.float32 or torch.float

torch.FloatTensor

torch.cuda.FloatTensor

64-bit floating point

torch.float64 or torch.double

torch.DoubleTensor

torch.cuda.DoubleTensor

16-bit floating point 1

torch.float16 or torch.half

torch.HalfTensor

torch.cuda.HalfTensor

16-bit floating point 2

torch.bfloat16

torch.BFloat16Tensor

torch.cuda.BFloat16Tensor

32-bit complex

torch.complex32

64-bit complex

torch.complex64

128-bit complex

torch.complex128 or torch.cdouble

8-bit integer (unsigned)

torch.uint8

torch.ByteTensor

torch.cuda.ByteTensor

8-bit integer (signed)

torch.int8

torch.CharTensor

torch.cuda.CharTensor

16-bit integer (signed)

torch.int16 or torch.short

torch.ShortTensor

torch.cuda.ShortTensor

32-bit integer (signed)

torch.int32 or torch.int

torch.IntTensor

torch.cuda.IntTensor

64-bit integer (signed)

torch.int64 or torch.long

torch.LongTensor

torch.cuda.LongTensor

Boolean

torch.bool

torch.BoolTensor

torch.cuda.BoolTensor

参考链接:PyTorch官方教程中文版
参考链接:yunjey-pytorch-tutorial

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值