机器学习需要掌握数据处理工具Pandas、Numpy,同理,深度学习也需要掌握相应的数据处理工具,在Pytorch中数据存储在张量Tensor和变量Variable之中,本篇将介绍它们的基本用法以及与之相关的常用函数。

掌握必要的基础知识,让后期看代码更加流畅,避免陷入太多细节。

Tensor 张量

Tensor用于表示矩阵(多维数据),类似Numpy的ndarray,不同的是,可以使用GPU加速。

1.生成张量

import torch

用Tensor方法将其它格式数据转换成张量:

a = torch.Tensor([[1,2],[3,4],[5,6]])
print(a)
print(a.size())
# 输出结果:
# tensor([[1., 2.],
#         [3., 4.],
#         [5., 6.]])
# torch.Size([3, 2])

另外,也可以使用torch.zeros(),torch.randn()生成张量。

2.修改张量

用赋值的方法即可修改张量,比如将上面生成张量,将其位置1,1的元素赋值成50。

a[1,1]=50
print(a)
# 输出结果:
# tensor([[ 1.,  2.],
#         [ 3., 50.],
#         [ 5.,  6.]])

3.类型转换

张量与numpy数据相互转换

b = a.numpy()
print(b)
# [[ 1.  2.]
#  [ 3. 50.]
#  [ 5.  6.]]
c = torch.from_numpy(b)
print(c)
# tensor([[ 1.,  2.],
#         [ 3., 50.],
#         [ 5.,  6.]])

转换成GPU上运行的cuda数据格式

if torch.cuda.is_available(): # 如果支持cuda硬件加速
    d = a.cuda()

Variable变量

Variable是神经网络计算图中特有的概念,它提供了自动求导的功能。

1.类型转换

将Tensor转成Variable

from torch.autograd import Variable
b = Variable(a, requires_grad=True)

使用了参数requires_grad,用于指定是否求梯度,默认为False。

2.求导

先声明三个变量x,a,b,用它们计算变量y,之后用y.backward()求y对x,a,b三个变量的偏导数,这也是深度学习中常说的“反向”过程。求出的值存储在变量的grad元素中,如x.grad。

x = Variable(torch.Tensor([1]), requires_grad=True)
a = Variable(torch.Tensor([2]), requires_grad=True)
b = Variable(torch.Tensor([3]), requires_grad=True)
y = a * x + b
y.backward()
print(x.grad) # 输出结果: tensor([2.])
print(a.grad) # 输出结果: tensor([1.])
print(b.grad) # 输出结果: tensor([1.])
print(b.data) # 输出结果: tensor([3.])

从输出结果可以看到,Variable包含两个元素,data是它的Tensor值,grad保存的是求得的导数。

常用的数据处理函数

1.增加维度

在深度学习过程中,现有的数据格式和模型要求的格式往往不同,层与层之间的数据也需要转换后才能对接,因此,维度转换是最常用的方法。
squeeze意为压缩,即去掉维度,unsqueeze则相反,为添加维度。

unsqueeze(input, dim, out=None) 

用于增添第dim维度为1。具体用法见以下示例:

a = torch.Tensor([1,2,3])
print(a, a.shape)
# tensor([1., 2., 3.]) torch.Size([3])
b = torch.unsqueeze(a, 1)
print(b, b.shape)
# tensor([[1.],[2.],[3.]]) torch.Size([3, 1])
c = torch.unsqueeze(a, 0)
print(c, c.shape)
# tensor([[1., 2., 3.]]) torch.Size([1, 3])

2.减小维度

squeeze(input, dim=None, out=None) 

用于删除第dim个维度,如果当前不包括指定的维度,则不会进行删除。如果不指定dim,函数将删除值为1的维度。
本例中延用上例中的数据:

print(torch.squeeze(c,0))
# tensor([1., 2., 3.])
print(torch.squeeze(b,1))
# tensor([1., 2., 3.])
print(torch.squeeze(b))
# tensor([1., 2., 3.])

3.转换维度

比squeeze和unsqueeze更简单的方法是直接把张量转换成指定维度,使用view函数实现,它类似于numpy的reshape。

view(*shape) 

将张量转换成指定的形状,示例:

x = torch.Tensor([1,2,3,4])
print(x.view(2,2))
# tensor([[1., 2.], [3., 4.]])
print(x.view(1,4))
# tensor([[1., 2., 3., 4.]])
print(x.view(1,-1)) # 设定为-1时自动计算该维度大小
# tensor([[1., 2., 3., 4.]])
print(x.view(4))
# tensor([1., 2., 3., 4.])

4.cat拼接

cat函数用于在指定维度上拼接多个张量。

cat(tensors, dim=0, out=None) 

将tensors中的多个张量按dim指定的维度拼接成一个张量,拼接后总维数不变。

x = torch.Tensor([[1,2],[3,4]])
y = torch.Tensor([[5,6],[7,8]])
print(torch.cat((x,y),0))
# tensor([[1., 2.],
#        [3., 4.],
#        [5., 6.],
#        [7., 8.]])
print(torch.cat((x,y),1))
# tensor([[1., 2., 5., 6.],
#        [3., 4., 7., 8.]])

一般面对的数据最多三维,并以一两维居多,可以将其理解为横向加或者纵向加。

5.stack拼接

与cat拼接不同的是,stack拼接后维度增加,其用法如下:

stack(tensors, dim=0, out=None)

示例:

x = torch.Tensor([1,2])
y = torch.Tensor([3,4])
print(torch.stack((x,y),dim=0))
# tensor([[1., 2.],
#         [3., 4.]])
print(torch.stack((x,y),dim=1))
# tensor([[1., 3.],
#         [2., 4.]])

从输出内容可以看到,拼接后张量变成了两维,dim=0是最常用的情况,它直接把两个张量拼在一起,当dim=1时,拼接时转换了位置。

6.transpose两维度互换

transpose(input, dim0, dim1)

互换dim0, dim1两个维度,具体方法见示例:

x = torch.Tensor([[1,2],[3,4]])
print(torch.transpose(x,0,1))
# tensor([[1., 3.],
#        [2., 4.]])

7.perumute多维度互换

permute与transpose功能类似,但更加灵活,它可以指定多个维度互换。

permute(dim) 

用于将张量转换成dim指定的维度。

x = torch.rand(2,3,4)
print(x.shape, x.permute(2,1,0).shape)
# torch.Size([2, 3, 4]) torch.Size([4, 3, 2])

本例先产生了一组3维的随机数,每个维度的元素个数分别是2,3,4,然后使用permute将其第2维转成第0维,第1维不变,第0维转成第2维,从打印信息中可以看到各维元素个数的变化。

posted on 2019-11-28 16:50  xieyan0811  阅读(23)  评论(0编辑  收藏  举报