PyTorch框架学习二——基本数据结构(张量)
- 一、什么是张量?
- 二、Tensor与Variable(PyTorch中)
- 1.Variable
- 2.Tensor
- 三、Tensor的创建
- 1.直接创建Tensor
- (1)torch.tensor()
- (2)torch.from_numpy()
- 2.依据数值创建
- (1)torch.zeros()
- (2)torch.zeros_like()
- (3)torch.ones()
- (4)torch.ones_like()
- (5)torch.full()
- (6)torch.full_like()
- (7)torch.arange()
- (8)torch.linspace()
- (9)torch.logspace()
- (10)torch.eye()
- 3.依据概率分布创建张量
- (1)torch.normal()
- (2)torch.randn()
- (3)torch.randn_like()
- (4)torch.rand()
- (5)torch.rand_like()
- (6)torch.randint()
- (7)torch.randint_like()
- (8)torch.randperm()
- (9)torch.bernoulli()
一、什么是张量?
先来看一些数学上常见的名词:
标量:0维张量
向量:1维张量
矩阵:2维张量
所以,张量(Tensor)是一个多维数组,是上述提及的标量、向量和矩阵的高维拓展。
二、Tensor与Variable(PyTorch中)
Variable是PyTorch 0.4.0之前的一种数据类型,PyTorch 0.4.0开始,Variable已经并入了Tensor,所以已经不再需要用到Variable,但是为了学习的一个循序渐进的过程,我们还是先来看一下Variable这个数据类型。
1.Variable
是torch.autograd中的数据类型,主要用于封装Tensor,使得Tensor可以自动求导。
Variable这种数据类型包括了五种属性,分别如下所示:
- data:被包装的Tensor
- grad:data的梯度
- grad_fn:创建Tensor的Function,这是自动求导的关键
- requires_grad:指示是否需要计算梯度
- is_leaf:指示是否是叶子结点(张量)
Variable可以看成是给Tensor加上了四个与梯度相关的属性。
2.Tensor
PyTorch 0.4.0 版本开始,Variable并入Tensor。Tensor在Variable的基础上又添加了三个与数据相关的属性,一共有八个属性,分别如下所示:
- data:被包装的Tensor
- dtype:张量的数据类型,如torch.FloatTensor、torch.cuda.FloatTensor等
- shape:张量的形状/维度,如(64,3,224,224)
- device:张量所在设备,GPU/CPU,是加速计算的关键
- grad:data的梯度
- grad_fn:创建Tensor的Function,这是自动求导的关键
- requires_grad:指示是否需要计算梯度
- is_leaf:指示是否是叶子结点(张量)
前四个属性与数据相关,后四个属性与梯度求导相关。
三、Tensor的创建
一般Tensor的创建有三种方式:直接创建、依数值创建和依概率分布创建,下面分别进行介绍:
1.直接创建Tensor
这种创建方式一般是将列表(list)、数组(ndarray)封装数据的形式直接转变为Tensor,常用的有torch.tensor()、torch.from_numpy()。
(1)torch.tensor()
功能:从data创建tensor
先给出官方的函数形式以及参数:
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
下面看一下所有的参数:
- data:要转变为张量的数据,可以是列表、元组、numpy的ndarry、散点和其他数据类型。
- dtype:(可选)张量的数据类型,默认为None,返回data自己的数据类型。
- device:(可选)张量的计算设备,默认为None,使用现有的设备,可以是cuda/cpu。
- requires_grad:(布尔类型,可选)如果autogard需要记录张量的运算,即是否需要计算data的梯度,默认为False。
- pin_memory:(布尔类型,可选)如果设置,张量将被分配到锁页内存中,只为CPU的张量工作,默认为False。
arr = np.ones((3, 3))
print("ndarray数组:", arr)
print("ndarray的数据类型:", arr.dtype)# t = torch.tensor(arr, device='cpu')
t = torch.tensor(arr)
print(t)tens = torch.tensor([1, 2], dtype=torch.int64)
print(tens.data, tens.dtype)
(2)torch.from_numpy()
功能:从numpy.ndarray创建tensor,相比tensor(),数据类型只能是numpy.ndarray。
torch.from_numpy(ndarray)
它只有一个参数,就是输入的ndarry,但是它需要注意的是:torch.from_numpy()创建的tensor与原ndarry是共享内存的,当修改其中一个数据时,另一个也将会被改动。
arr = np.array([[1, 2, 3], [4, 5, 6]])
t = torch.from_numpy(arr)
print("numpy array: ", arr)
print("tensor : ", t)
print("\n修改arr")
arr[0, 0] = 0
print("numpy array: ", arr)
print("tensor : ", t)
print("\n修改tensor")
t[0, 0] = -1
print("numpy array: ", arr)
print("tensor : ", t)
2.依据数值创建
(1)torch.zeros()
功能:依据size创建全0张量
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
看一下所有的参数:
- size:定义输出张量的形状/维度,可以是元组或者列表,如(3,3),(3,3,3)。
- out:(张量,可选)输出张量。
- dtype:(可选)张量的数据类型,默认为None,使用全局默认类型。
- layout:(可选)内存中的布局形式,有strided,sparse_coo等,默认为torch.strided。
- device:同上。
- requires_grad:同上。
>>> torch.zeros(2, 3)
tensor([[ 0., 0., 0.],[ 0., 0., 0.]])>>> torch.zeros(5)
tensor([ 0., 0., 0., 0., 0.])
(2)torch.zeros_like()
功能:依据input形状创建全0张量
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
看一下所有的参数:
- input:(张量)input的尺寸/维度决定输出张量的维度。
- dtype:(可选)默认为None,与input的类型一致。
- layout:(可选)默认为None,与input的layout一致。
- device:(可选)默认为None,与input的device一致。
- requires_grad:(布尔,可选)同上。
- memory_format:(可选)张量的存储格式。
>>> input = torch.empty(2, 3)
>>> torch.zeros_like(input)
tensor([[ 0., 0., 0.],[ 0., 0., 0.]])
(3)torch.ones()
功能:依据size创建全1张量
参数与torch.zeros()类似
(4)torch.ones_like()
功能:依据input形状创建全1张量
参数与torch.ones()类似
(5)torch.full()
功能:创建一个尺寸为size的张量,里面每个元素的值全为fill_value
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
参数如下:
- size:维度
- fill_value:张量内要填充的值
- 其他参数都同上
>>> torch.full((2, 3), 3.141592)
tensor([[ 3.1416, 3.1416, 3.1416],[ 3.1416, 3.1416, 3.1416]])
(6)torch.full_like()
功能:依据input的尺寸创建一个张量,值全为full_value。
torch.full_like(input, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, memory_format=torch.preserve_format)
(7)torch.arange()
功能:创建等差的一维张量。注意数值区间为 [ start, end )
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- start:数列起始值,默认为0。
- end:数列“结束值”。
- step:数列公差,默认为1。
- 其他参数同上。
>>> torch.arange(5)
tensor([ 0, 1, 2, 3, 4])
>>> torch.arange(1, 4)
tensor([ 1, 2, 3])
(8)torch.linspace()
功能:创建均分的一维张量。注意数值区间为 [ start, end ]。
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- start:数列起始值。
- end:数列结束值。
- steps:在start和end之间要采样的个数,默认为100。
- 其他参数同上。
>>> torch.linspace(3, 10, steps=5)
tensor([ 3.0000, 4.7500, 6.5000, 8.2500, 10.0000])
>>> torch.linspace(-10, 10, steps=5)
tensor([-10., -5., 0., 5., 10.])
(9)torch.logspace()
功能:创建对数均分的一维张量,长度为steps,对数的底为base。
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- start:数列的起始值。
- end:数列的结束值。
- steps:数列的长度,默认为100。
- base:对数的底,默认为10。
- 其他参数同上。
>>> torch.logspace(start=-10, end=10, steps=5)
tensor([ 1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
>>> torch.logspace(start=0.1, end=1.0, steps=5)
tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000])
(10)torch.eye()
功能:创建单位对角矩阵(2维张量),默认为方阵。
torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- n:矩阵行数。
- m:(可选)矩阵列数,默认等于n。
- 其他参数同上。
>>> torch.eye(3)
tensor([[ 1., 0., 0.],[ 0., 1., 0.],[ 0., 0., 1.]])
3.依据概率分布创建张量
(1)torch.normal()
功能:返回随机数的张量,这些随机数是从给定平均值和标准差的独立正态分布中提取的。
torch.normal(mean, std, *, generator=None, out=None)
有四种模式:
1.mean是标量,std是标量:这是只有一个高斯分布,这时需要指定张量的尺寸,即在这个高斯分布里采样多少次。
# mean:标量 std: 标量
t_normal = torch.normal(0., 1., size=(4,))
print(t_normal)
2和3. mean和std中有一个是张量,一个是标量:
# mean:张量 std: 标量
mean = torch.arange(1, 5, dtype=torch.float)
std = 1
t_normal = torch.normal(mean, std)
print("mean:{}\nstd:{}".format(mean, std))
print(t_normal)
这里就是从四个高斯分布中分别采样了一次得到的张量。
4. mean和std都为张量:
# mean:张量 std: 张量
mean = torch.arange(1, 5, dtype=torch.float)
std = torch.arange(1, 5, dtype=torch.float)
t_normal = torch.normal(mean, std)
print("mean:{}\nstd:{}".format(mean, std))
print(t_normal)
(2)torch.randn()
功能:生成标准正态分布,normal的特殊情况。
torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
>>> torch.randn(4)
tensor([-2.1436, 0.9966, 2.3426, -0.6366])
>>> torch.randn(2, 3)
tensor([[ 1.5954, 2.8929, -1.0923],[ 1.1719, -0.4709, -0.1996]])
(3)torch.randn_like()
torch.randn_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
(4)torch.rand()
功能:生成[0, 1)之间均匀分布的随机采样张量。
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
>>> torch.rand(4)
tensor([ 0.5204, 0.2503, 0.3525, 0.5673])
>>> torch.rand(2, 3)
tensor([[ 0.8237, 0.5781, 0.6879],[ 0.3816, 0.7249, 0.0998]])
(5)torch.rand_like()
torch.rand_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
(6)torch.randint()
功能:生成[low, high)之间均匀分布的随机采样张量。
torch.randint(low=0, high, size, *, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- low:(可选)均匀分布范围的下限,默认为0。
- high:均匀分布范围的“上限”。
- 其他参数同上。
>>> torch.randint(3, 5, (3,))
tensor([4, 3, 4])>>> torch.randint(10, (2, 2))
tensor([[0, 2],[5, 5]])>>> torch.randint(3, 10, (2, 2))
tensor([[4, 5],[6, 7]])
(7)torch.randint_like()
torch.randint_like(input, low=0, high, dtype=None, layout=torch.strided, device=None, requires_grad=False, memory_format=torch.preserve_format)
(8)torch.randperm()
功能:生成从0到n-1的随机排列。
torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
- n:上界,也是tensor的长度。
- 其他参数同上。
>>> torch.randperm(4)
tensor([2, 1, 0, 3])
(9)torch.bernoulli()
功能:以input为概率,生成伯努利分布(0-1分布,两点分布)。
torch.bernoulli(input, *, generator=None, out=None)
- input:(张量)伯努利分布的概率值,依据这个概率值抽取0/1。
- 其他参数同上。
>>> a = torch.empty(3, 3).uniform_(0, 1) # generate a uniform random matrix with range [0, 1]
>>> a
tensor([[ 0.1737, 0.0950, 0.3609],[ 0.7148, 0.0289, 0.2676],[ 0.9456, 0.8937, 0.7202]])
>>> torch.bernoulli(a)
tensor([[ 1., 0., 0.],[ 0., 0., 0.],[ 1., 1., 1.]])>>> a = torch.ones(3, 3) # probability of drawing "1" is 1
>>> torch.bernoulli(a)
tensor([[ 1., 1., 1.],[ 1., 1., 1.],[ 1., 1., 1.]])
>>> a = torch.zeros(3, 3) # probability of drawing "1" is 0
>>> torch.bernoulli(a)
tensor([[ 0., 0., 0.],[ 0., 0., 0.],[ 0., 0., 0.]])