此系列所有笔记来源参考:
上节中对Titanic数据集利用pytorch做了简单的预测,本节中我们开始从pytorch的基本数据类型入手,掌握pytorch最基本的用法。
本章将分为以下几个部分
- torch张量的简单构造
- torch张量的基本操作
一、torch张量的简单构造
torch的基本数据类型叫做张量,在Python中使用torch.Tensor创建。与任何语言相同,张量也是有其基本数据类型的,且此数据类型与numpy对应,只是不支持str(字符串)类型。torch常见的数据类型有整数型、浮点数型、布尔型和复数型,在模型训练中,我们最常用的是浮点数型。
下表中是pytorch支持的所有数据类型,看看就好。
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 | torch.float16 or torch.half | torch.HalfTensor | torch.cuda.HalfTensor |
16-bit floating point | 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 |
quantized 8-bit integer (unsigned) | torch.quint8 | torch.ByteTensor | / |
quantized 8-bit integer (signed) | torch.qint8 | torch.CharTensor | / |
quantized 32-bit integer (signed) | torch.qfint32 | torch.IntTensor | / |
quantized 4-bit integer (unsigned) | torch.quint4x2 | torch.ByteTensor | / |
一般神经网络建模使用的都是torch.float32类型。
构造一个张量十分简单,只需要利用torch.Tensor函数,传入一个基本数据类型,或是Python的List类型,或是numpy类型即可。我们来试一试:
import torch
import numpy as np
print(torch.tensor(True).dtype)
print(torch.tensor(1).dtype)
print(torch.tensor(1.0).dtype)
与numpy相同,查看其dtype属性就可以看到其数据类型。执行代码,输出如下:
torch.bool
torch.int64
torch.float32
可以看出,整数类型默认被创建为int64,小数默认被创建为float32
torch.tensor中传入dtype属性可以强制指定数据类型
print(torch.tensor(1, dtype=torch.int32).dtype)
print(torch.tensor(1.0, dtype=torch.float64).dtype)
print(torch.tensor(1.0, dtype=torch.double).dtype)
输出如下:
torch.int32
torch.float64
torch.float64
可以看到数据类型变成了我指定的类型。如果你有疑问:为什么我指定的是torch.double,类型却是torch.float64呢?那你可以去查查上面的表格,会发现double和float64是完全相同的dtype,上面的表格中均有注明。
下面来使用List和np.ndarray类型来初始化张量:
a = torch.tensor([[1., -1.], [1., -1.]])
b = torch.tensor(np.array([[1, 2, 3], [4, 5, 6]]))
print(a, a.dtype, b, b.dtype, sep='\n')
使用List类型构造一个二维的张量,List中存放的为float类型的数据;同时使用numpy构造一个二维张量,numpy中数据类型为int64。现在看看构造出的张量:
tensor([[ 1., -1.],
[ 1., -1.]])
torch.float32
tensor([[1, 2, 3],
[4, 5, 6]])
torch.int64
可以看出生成的张量的数据类型是完全对应的。
通过这个例子,也可以看出张量是支持任意维度的。与numpy类似,torch也支持单数据类型的多维矩阵运算。
需要注意的是,torch.tensor总是对数据进行一份拷贝,如果你有一个numpy数组但是不想取拷贝,就应该使用torch.as_tensor()函数。这点有印象即可。
二、torch张量的基本操作
- 使用dim( )查看张量的维度
>>> print(torch.tensor([[1., -1.], [1., -1.]]).dim())
2
2. 使用shape或size( )查看张量的大小
>>> print(torch.tensor([[1., -1.], [1., -1.]]).shape)
torch.Size([2, 2])
>>> print(torch.tensor([[1., -1.], [1., -1.]]).size())
torch.Size([2, 2])
3. 使用view( )或reshape( )改变张量的尺寸
不过要注意view和reshape并不完全相同,区别在于:view只能对满足连续条件的tensor进行操作,而reshape对于不满足连续条件的tensor,会进行一份复制,使得其满足连续条件后在进行操作。
vector = torch.arange(0,12)
print(vector)
print(vector.shape)
matrix34 = vector.view(3,4)
print(matrix34)
print(matrix34.shape)
matrix43 = vector.view(4,-1) #-1表示该位置长度由程序自动推断
print(matrix43)
print(matrix43.shape)
得到结果
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
torch.Size([12])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
torch.Size([3, 4])
tensor([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
torch.Size([4, 3])
但如果进行了转置等会破坏tensor连续性的操作,就会导致view失败,此时就要使用reshape操作,或者先进行contiguous( )操作将其转换为满足连续性条件的tensor再进行view
>>> matrix62 = torch.arange(0,12).view(2,6).t()
>>> print(matrix62.is_contiguous())
False
可以看出,转置后的tensor已不满足连续性条件
此时使用view( )会报错
>>> matrix62.view(3,4)
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
报错提示也提醒我们使用reshape方法
>>> print(matrix62.reshape(3,4))
tensor([[ 0, 6, 1, 7],
[ 2, 8, 3, 9],
[ 4, 10, 5, 11]])
reshape( )其实就相当于view( ) + contiguous( ).view( ),在满足tensor连续性条件时,reshape( )返回的结果与view( )相同,否则返回的结果与contiguous( ).view( )相同。
>>> print(matrix62.contiguous().view(3, 4))
tensor([[ 0, 6, 1, 7],
[ 2, 8, 3, 9],
[ 4, 10, 5, 11]])
4. 切片
>>> matrix = torch.arange(0,12).view(3, 4)
>>> print(matrix[1][2])
tensor(6)
>>> matrix[0][1] = 20
>>> print(matrix)
tensor([[ 0, 20, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
5. 使用item( )从包含单个值的tensor中获得一个Python的数
>>> x = torch.tensor([[1]])
>>> x
tensor([[ 1]])
>>> x.item()
1
>>> x = torch.tensor(2.5)
>>> x
tensor(2.5000)
>>> x.item()
2.5
6. 使用tolist( )将tensor转为List列表
>>> matrix = torch.arange(0,12).view(3, 4)
>>> print(type(matrix))
<class 'torch.Tensor'>
>>> matrix = matrix.tolist()
>>> print(type(matrix))
<class 'list'>
>>> print(matrix)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
7. 使用numpy( )将tensor转为numpy数组
>>> matrix = torch.arange(0,12).view(3, 4)
>>> print(type(matrix))
<class 'torch.Tensor'>
>>> matrix = matrix.tolist()
>>> print(type(matrix))
<class 'numpy.ndarray'>
>>> print(matrix)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
除此之外,tensor的基本操作还有许多,将会在后面的章节中学习。