Pytorch从0到1系列之(1)---Pytorch的基本数据类型

正如numpy包中的array,Pandas包中的Series和Dataframe一样,为了方便计算,Pytorch也在Python数据结构的基础上封装了几个基本的数据结构。

一、张量(Tensor)

没错,就是TensorFlow名字里的Tensor,本来谷歌给TensorFlow命名的时候就是给这个框架赋予了深度学习就是“张量流动”的深刻内涵。因为深度学习处理的数据量和维度都比较大,所以很多深度学习框架借用了张量这个概念作为基本的数据结构。

其实张量虽然听起来非常高大上,数学上也有一些其他的物理世界抽象和运算法则。但是,张量其实就是一个多维的向量,二维张量就是三维向量、一维张量就是二维向量……所以,在深度学习里,我们直接把它看做一个多维的向量就好。

1、创建张量

1)基本创建语法

在Pytorch中,创建张量的方式非常简单,只需要:a = torch.Tensor(参数)即可。
在这里,如果我们需要创建固定维度大小的张量,那么参数可以写成:(n,m,……),如果需要指定每个元素的值,那么就参数就需要写成:([元素1,元素2,元素3,元素4,……])

比如,以下是一个创建张量的例子:

import torth
A = torch.Tensor(2,3) #创建一个维度为(2,3)的张量

b = [[1,2,],[3,4],[5,6]]
B = torch.FloatTensor(b)#创建一个元素为b数组中的元素的张量

print(A)
print(A.type())
print(B)
print(B.type())

输出结果如下:

tensor([[ 9.5016e+21,  1.9249e-37,  1.7228e-34],
        [ 1.8311e-38, -3.7846e-37,  3.8074e+22]])
torch.FloatTensor
tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])
torch.FloatTensor

这里可以看到,两种方式创建的张量都是Float类型。因为这种数据类型即保证了一定的精确度,又不是特别占用内存。

当然,在使用过程中,根据自己的实际情况,可以创建指定元素数据类型的张量:

  • 元素为32位浮点型的张量(同上边效果是一样的):torch.FloatTensor()
  • 元素为64位浮点型的张量:torch.DoubleTensor()
  • 元素为整型的张量(32位):torch.IntTensor()
  • 元素为16位整型的张量:torch.ShortTensor()
  • 元素为64位整型的张量:torch.LongTensor()

如果需要查看某一张量的维度,可以使用A.size()

2)创建一些特殊的张量。

创建全0张量:A = torch.zeros(n,m)

创建全1张量:A = torch.ones(n,m)

创建指定维度的随机数张量:(元素呈正态分布,均值为0,方差为1)A = torch.randn(n,m)

创建指定维度的随机数张量:(元素在0到1之间均匀分布)A = torch.rand(n,m)

创建元素以一定步长递变的张量:A = torch.range(起始值,结束值,步长)
注意,这里生成的值是浮点型,步长也可以设置为浮点型。

2、张量运算

为了便于接下来的运算,我们首先生成几个Tensor变量。

import torch
A = torch.Tensor( [[-1,-2],[-3,-4],[-5,-6]]) 
B = torch.Tensor( [[1,2],[3,4],[5,6]]) 
C = 2

1)对所有元素取绝对值:torch.abs(A)
ab = torch.abs(A)
print(ab)

输出结果:

tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])
2)两个张量对应元素相加:torch.add(A,B)
ad1 = torch.add(A,B)
print(ad1)

ad2 = torch.add(A,C)
print(ad2)

输出结果:

tensor([[0., 0.],
        [0., 0.],
        [0., 0.]])
tensor([[ 1.,  0.],
        [-1., -2.],
        [-3., -4.]])

可以看到,numpy的广播机制在Pytorch中也适用。

3)两个张量对应元素相乘:torch.mul(A,B)
mul1 = torch.mul(A,B)
print(mul1)

mul2 = torch.mul(A,C)
print(mul2)

输出结果:

tensor([[ -1.,  -4.],
        [ -9., -16.],
        [-25., -36.]])
tensor([[ -2.,  -4.],
        [ -6.,  -8.],
        [-10., -12.]])
4)两个张量对应元素相除:torch.div(A,B)
div1 = torch.div(A,B)
print(div1)

div2 = torch.div(A,C)
print(div2)

输出结果:

tensor([[-1., -1.],
        [-1., -1.],
        [-1., -1.]])
tensor([[-0.5000, -1.0000],
        [-1.5000, -2.0000],
        [-2.5000, -3.0000]])
5)两个张量按照矩阵乘法规则结合:torch.mm(A,B)

特别注意,这个函数要和torch.mul(A,B)区分,这个函数需要两个张量满足矩阵乘法运算规则才可以运算。

mm = torch.mm(A,torch.t(B))#对B矩阵转置之后与A矩阵相乘
print(mm)

输出结果:

tensor([[ -5., -11., -17.],
        [-11., -25., -39.],
        [-17., -39., -61.]])
6)显示张量元素的值:torch.clamp(A,min,max)

会使超出[min,max]元素的值被限制在这个范围内。

cla = = torch.clamp(A,-4,-1)
print(cla)

输出结果:

tensor([[-1., -2.],
        [-3., -4.],
        [-4., -4.]])

另外,还有一些操作,例如:

  • 求张量A的n次幂:torch.pow(A,n)
  • 求矩阵和向量的乘积:torch.mv(A,B)。其中A是矩阵B是向量,也需要维度符合规则。

通过上边的例子可以看到,torch的张量和numpy数组非常类似。的确,Pytorch中的张量可以理解为可以在GPU上运行的numpy数组。两者也可以通过torch.from_numpy()A.numpy这两个函数相互转换。看下边这个例子:

A = np.array([[1,2,3],[4,5,6]])#生成一个numpy数组
print("A的数据类型是:",type(A)) #将numpy数组转换成torch张量
At = torch.from_numpy(A)
print("At的数据类型是:",type(At))  
An = At.numpy()   #将torch张量转换成numpy数组
print("An的数据类型是:",type(An))

输出结果如下:

A的数据类型是: <class 'numpy.ndarray'>
At的数据类型是: <class 'torch.Tensor'>
An的数据类型是: <class 'numpy.ndarray'>

二、变量(Variable)

在Pytorch中,张量就是个死气沉沉的数组,只可以执行简单的加减乘除以及矩阵操作,而这对于深度学习是远远不够的。变量赋予了张量自动求导这一深度学习反向传播所需要的重要能力。

其基本原理就是,变量相当于把张量放到了一个计算图中(计算图这概念再TensorFlow中也有,不过TensorFlow中需要用户手动创建计算图,而Pytorch中需要用户执行的操作相对较少)。

要想使用Variable函数,需要先导入自动求梯度包:from torch.autograd import Variable

Variable有三个属性:data,grad和grad_fn。
data属性存放了Variable的张量值,grad属性可以得到这个张量反向传播的梯度,grad_fn可以得到这个Variable的操作【进一步解释】。看这样一个例子:

import torch
from torch.autograd import Variable

x1= Variable(torch.Tensor([3]),requires_grad = True)
y1 = 3*x1 +1
y1.backward()
print(x1.grad)

x2 = Variable(torch.Tensor([3]),requires_grad = True)
y2 = 3*torch.pow(x2,2) +1
y2.backward()
print(x2.grad)

其中,requires_grad = True的意思是在反向传播的时候要对这个变量求梯度。输出如下:

tensor([3.])
tensor([18.])

可以看到,可能有人会觉得,这明显就是对函数 y 1 = 3 x 1 + 1 y1 = 3x_1+1 y 2 = 3 x 2 2 + 1 y2 = 3x_2^2+1 求了个导数嘛,有什么了不起的。但是,Variable最厉害的是对于复杂的函数和复合函数也可以用一条语句求梯度,另外也可以求矩阵的梯度,比如:

import torch
from torch.autograd import Variable

x = Variable(torch.Tensor([1,2,3,4]),requires_grad = True)
y = 3*torch.pow(x,2) +1
y.backward(torch.Tensor([1,1,1,1]))#这里必须要写入参数,与被求导的张量维数相同。
print(x.grad)

输出如下:

tensor([ 6., 12., 18., 24.])

这样,就可以分别得到x = 1,2,3,4时,y的导数值,其中,y.backward(torch.Tensor([1,1,1,1]))中的[1,1,1,1]分别会和对应维数得到的导数相乘,代表向量的每个维度反向传播的更新系数 α \alpha

总结:

本文主要介绍了Pytorch的基本数据类型:Tensor和Variable的使用。

发布了63 篇原创文章 · 获赞 189 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u013044310/article/details/92002437
今日推荐