PyTorch数据类型1

PyTorch数据类型

1.综述

​ PyTorch最主要的作用是基于 GPU 的科学计算,所以,并没有一个内建类型来支持 string,如果我们要使用 string,需要的是使用 编码的形式将之转换为数字计算的问题:embedding(比较复杂),one-hot(一维向量)。

​ 我们需要的关注的几个数据类型:

Py CPU GPU
int torch.IntTensor torch.cuda.IntTensor
double torch.DoubleTensor torch.cuda.DoubleTensor
long torch.LongTensor torch.cuda.LongTensor

2.张量

​ 张量(Tensor)可是说是 深度学习 最重要\最基础的概念了。我们可以简单的把他理解成为一个矩阵。其主要包括以下属性:轴、阶、和形状。

2.1.阶(rank)

​ 示例,我们有一个二阶张量,其意味着以下几点:

我们有一个矩阵/二维数组/二维张量

​ 阶,就是一个数组的维度。有一个定义很有意思:

A tensor's rank tells us how many indexes are needed to refer to a specific element within the tensor.

张量的阶告诉我们访问(引用)张量数据结构中的特定数据元素需要多少个索引。

​ 考虑如下张量:

tensor([[1, 2, 3],
        [2, 4, 6],
        [1, 4, 1]])

​ 访问其中任何一个元素,必须以 dd[i][j] 的形式,需要 i 和 j 两个索引,这就说明,我们这个张量的阶是2.显然地,阶是维数,和我们的矩阵的秩(阶)有着截然不同的两个含义。

2.2.轴

​ 对于一个n维数组,n 维的 n 就是数组的 阶,而其中的每一维就是这个张量的一个轴。元素被称为存在或沿着轴运行。这个机制受每个轴的长度限制。从线性代数的角度来理解,轴相当于是 n 维空间中的一个超平面。

​ 考虑如下张量:

tensor([[[1, 2],
         [3, 4]],
        [[5, 6],
         [7, 8]]])
#第一条轴,是一个二维数组
ddd[0]
Out[9]: 
tensor([[1, 2],
        [3, 4]])
#第二条轴,是一个一维数组
ddd[0][1]
Out[10]: tensor([3, 4])
#最后一个轴,就是数字了
ddd[0][1][1]
Out[12]: tensor(4)

2.3.形状

​ 张量的形状,就是每一个轴的长度合在一起的向量。这个的理解可以稍微参考一下 C++ 的多维数组。假设我们创建这样的一个数组 int a[10][3][6] 。那么它的形状就是 (10,3,6)。一个 m*n*p 的张量的形状就是 (m,n,p)。

​ 示例:

print(ddd)
tensor([[[1, 2],
         [3, 4]],
        [[5, 6],
         [7, 8]]])
ddd.shape
Out[14]: torch.Size([2, 2, 2])

​ 备注:一个小技巧:最左边的 [ 的数量,就是我们的张量的阶

​ 形状其实告诉了我们很多信息: 一个张量的 shape 所返回的一维向量:他的长度就是阶\轴的数量,每一个数字就是对应的轴的长度。所以说,size 非常地有用。

2.4.一些函数

2.4.1.获得张量的阶\维数

a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
a.dim()
Out[32]: 3

2.4.2.获得张量的形状(size == shape)

a.shape
Out[33]: torch.Size([2, 2, 2])
a.size()
Out[34]: torch.Size([2, 2, 2])

2.4.3.改变张量的形状:reshape

#改变张量的shape:reshape
a
Out[28]: 
tensor([[[1, 2],
         [3, 4]],
        [[5, 6],
         [7, 8]]])
a = torch.reshape(a,(4,2))
a
Out[36]: 
tensor([[1, 2],
        [3, 4],
        [5, 6],
        [7, 8]])
a.shape
Out[37]: torch.Size([4, 2])

2.4.4.计算张量之中的元素个数:numel

a = torch.randn(2,3)
a
Out[66]: 
tensor([[-1.8256,  0.2332,  0.2376],
        [-0.9922,  0.2779,  0.8320]])
a.numel()
Out[67]: 6

2.4.5.创建一个张量

​ 主要方式类似于 numpy 数组的创建,可以类比下面的一个向量的创建其主要包括以下几种形式:

从 ndarray 数组导入:torch.from_array()
if __name__ == "__main__":
    a = np.array([[1, 2, 3], [1, 2, 3]])
    print(type(a))
    a = torch.from_numpy(a)
    print(a.type())
====Output====
<class 'numpy.ndarray'>
torch.IntTensor
使用 torch.FloatTensor 创建
torch.FloatTensor(2,3)#注意括号的问题
Out[64]: 
tensor([[0., 0., 0.],
        [0., 0., 0.]])
#假设传入的是一个元组,那么,这个函数作用就不再是创建张量了,而是数据类型转换
torch.FloatTensor((2,3))
Out[63]: tensor([2., 3.])
使用 torch.empty 创建

​ 这个函数的使用类比 numpy.empty()

torch.empty(2,3)
Out[70]: 
tensor([[1.4013e-45, 0.0000e+00, 8.4078e-45],
        [0.0000e+00, 1.4013e-45, 0.0000e+00]])
使用 torch.Tensor 创建
a = torch.Tensor(2,3)#注意,同样的没有括号
a
Out[72]: 
tensor([[0.0000e+00, 0.0000e+00, 4.2039e-45],
        [0.0000e+00, 1.4013e-45, 0.0000e+00]])

​ 额外提出一点注意:torch.tensor with torch.Tensor,这两者是不同的,前者我们通常用户数据类型的转换:其参数就是 data ,但是,后者的作用是创建一个随机的张量(default_type = TensorFloat)

​ 由于这个随机数在很多时候,会出现过大\过小的情况,我们用的并不是很多。

3.一点理解

​ PyTorch中的所有数据都是张量(Tensor),区别在于填充 Tensor 的,究竟是什么(long,int,float)。而一般情况下,我们所创建的 Tensor 都是一个多维数组(就像是 Python 之中的 列表),外面的那个 tensor 更像是一种简单的声明而已。真正的数据类型,其实是 tensor() 括号里面的东西。

​ 假设函数里面的参数是 *size ,那么一般而言,似乎都是一个简单的整数序列而已。

4.数据类型转换

4.1.cuda()

4.1.1.综述

​ 我们在之前说过,变量分为 gpu 变量和 cpu 变量,表现在命名上,就是 gpu 变量会有一个 cuda 的中缀。而实现 cpu 变量 -> gpu 变量转换的,就是 .cuda atrribute。

4.1.2.代码示例

a.type()
Out[14]: 'torch.LongTensor'
b = a.cuda()
b.type()
Out[16]: 'torch.cuda.LongTensor'

4.2.torch.from_numpy()

4.2.1.综述

​ 将 numpy 的数据类型:array 转换为 tensor

4.2.2.代码示例

import torch
import numpy as np

if __name__ == "__main__":
    a = (1, 2, 3)
    a = np.array(a)
    print(type(a))
    a = torch.from_numpy(a)
    print(a.type())
======Output======
<class 'numpy.ndarray'>
torch.IntTensor

5.标量

5.1.综述

​ 标量没什么好说的,相较于之前说的具备 shape axis 和 rank 的 tensor,它退化了,退化成为了一个数字,也就成为了标量。(上述的 tensor.LongTensor\tensor.FloatTensor)

5.2.函数与语法

b = torch.tensor(1.)
b
Out[21]: tensor(1.)
b.type()
Out[22]: 'torch.FloatTensor'
a = torch.tensor(1)
a
Out[24]: tensor(1)
a.type()
Out[25]: 'torch.LongTensor'

5.3.一些性质

​ 我们主要来看一下标量作为一种特殊的张量,它的 shape\dim是怎样的

a = torch.tensor(1)
a.shape
Out[39]: torch.Size([])
a.dim()
Out[40]: 0

​ 可以看到,它的 shape 是 [],它的 dim 是 0.

​ 而 dim 为 0 的标量的主要作用就在于表达 loss。

6.向量

​ 向量和标量一样,也是一种特殊的张量:一个一维数组。有很多种创建方式,这在下面会进行讨论。向量的意义是显然地:联想线性代数中我们额外加入的向量对于证明、运算的加速作用。而在神经网络中,向量会作为一个 bias 传入。这一点,会在之后具体的谈到。

6.1.torch.from_numpy()

6.1.1.综述&参数

​ 传入一个 ndarray 类型的数组,然后就会被转换为 tensor 类型,非常简单。

6.1.2.代码

a = np.ones((1, 10),int)
a
Out[54]: array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
type(a)
Out[55]: numpy.ndarray
a = torch.from_numpy(a)
a
Out[57]: tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=torch.int32)

6.2.torch.tensor()

6.2.1.综述&参数

​ 有点类似于数据类型转换,传入的参数是 tuple 或者 list,那么,传入的假如是一个一维的list,自然的,也就会被转换为 一维的张量。

6.2.2.代码示例

torch.tensor([1.,2.,3.])
Out[58]: tensor([1., 2., 3.])

6.3.torch.FloatTensor()

6.3.1.综述&参数

​ 这个东西本身就是一个数据类型,联想一下 C++ 中的 float,那么自然的,对于强制类型转换来说,就可以做到 float(xxx)。不过区别在于这个参数假如是一个数字 n,就会返回一个由 n 个 torch.FloatTensor类型的元素组成张量。这个东西很有意思: torch.FloatTensor(n) 类似于C++的 float a[n]。

6.31.2.代码示例

torch.FloatTensor(3)
Out[59]: tensor([2.6916e+20, 2.1127e-19, 1.1728e-19])#是未初始化的

6.3.3.补充

​ 但是,这个数据类型的作用并不仅仅在于创建一维的向量,这个也很显然,float 作为数据类型的作用,当然不是只能创建一维数组,高维的也是可以的。

​ 事实上,其参数就是 shape,FloatTensor是shape里面的每一个元素的数据类型,这个概念非常重要,会在之后反复提到。

torch.FloatTensor(2,3)#注意括号的问题
Out[64]: 
tensor([[0., 0., 0.],
        [0., 0., 0.]])
#假设传入的是一个元组,那么,这个函数作用就不再是创建张量了,而是数据类型转换
torch.FloatTensor((2,3))
Out[63]: tensor([2., 3.])
posted @ 2021-02-03 21:41  关河梦断  阅读(252)  评论(0)    收藏  举报