张量(Tensors)是pytorch中一种特殊的数据结构,类似于NumPy中的ndarrays,此外,Tensors可以用GPU进行计算
在高中和线性代数基本内容的学习中,我们对于标量(Scalar),向量(Vector),矩阵(Matrix)等有了比较深的认识。而张量,个人以为,其维数变化更加自由。
下面一张图来自于《Deep Learning with Pytorch》
PyTorch中的Tensor与NumPy中的arrays非常相似,但PyTorch可以在GPU上或CPU上并行运算,并记录跟踪计算过程,这是Tensor的一大优势。
在Python中,常常用List来处理向量。下面是List与Tensor的对比
print("下面是对List的操作")
a = [1.0,1.0,1.0]
print(a[0])
a[2] = 3.0
print(a)
print("下面是对Tensor的操作")
b = torch.ones(3)
print(b)
print(b[1])
print(float(b[1]))
b[2] = 2.0
print(b)
输出结果如下
看起来,这两者区别不大
但在底层实现上,这两种方法却有明显的区别
Python中List和Tuple里,每个元素是一个Python对象,在内存中松散排列(下图中左部),相较之下,Tensor和Arrays中,使用了一个连续的内存块,每个元素为C数据类型,而非Python对象。
至于面对高维向量,List固然也能表示,但比较繁琐。相对而言,还是Tensor更香。下面用Tensor表示一个三角形
points = torch.tensor([[1.0,4.0],[2.0,1.0],[3.0,5.0]])
print(points)
print("points.shape:",points.shape)
torch.Size([3,2])
是一个元组,所以torch.Size([3,2])
支持左右的元组操作。上文提过,Tensor使用了一个连续的内存块。事实上,一块连续的内存(storage),可以对应多个不同的Tensor,而每一个Tensor,就是对这一块内存的一种view方法,就好像对于一串汉字,用不同的断句方式会产生不同的意思。
从而,view方法成了改变Tensor的shape的一种很好的方法。在之后的操作部分会有介绍。
关于指向storage的方法,有几个量可以进行描述:size(shape),storage offset,strides
转置操作是非常常见的,那么在Tensor中,就是把stride的两个数调换位置
这些数据类型在之后的Tensor创建中都可以使用。
import torch
x = torch.empty(5,3) #这是构建了一个未初始化的5*3矩阵
print(x)
输出见下图
如果要初始化,则应为x=torch.rand(5,3)
定义矩阵中每个元素的数据类型,就需要加上dtype=torch.
x = torch.zeros(5,3,dtype=torch.long)
现在有了张量X,就可以根据已有的张量创建新的张量
x = x.new_ones(5, 3, dtype=torch.double)
x = torch.randn_like(x, dtype=torch.float)
x = torch.rand(5, 3)
y = torch.rand(5, 3)
x + y #直接使用+号
torch.add(x, y)
torch.add(x, y, out=result)#提供了一个输出张量作为参数
y.add_(x) #这一句是把x加到y上
#获得只有一个元素的Tensor的值
x = torch.randn(1)
x.item()
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)
points[1:] #只去掉第一行
points[1:, :]
points[1:, 0]#只去第一行,只取第一列
points = torch.ones(3, 4)
points_np = points.numpy()
如果这个Tensor在GPU上,在转到NumPy后,会分到CPU上
#save
torch.save(points, '../data/p1ch3/ourpoints.t')
#或者
with open('../data/p1ch3/ourpoints.t','wb') as f:
torch.save(points, f)
#load
points = torch.load('../data/p1ch3/ourpoints.t')
#或者
with open('../data/p1ch3/ourpoints.t','rb') as f:
points = torch.load(f)
points_gpu = torch.tensor([[1.0,4.0],[2.0,1.0],[3.0,5.0]],device='cuda') #这里用device='cuda'
points_gpu = points_gpu+4
print(points_gpu)
ngpu= 1
# Decide which device we want to run on
device = torch.device("cuda:0" if (torch.cuda.is_available() and ngpu > 0) else "cpu")
print(device)
print(torch.cuda.get_device_name(0))
print(torch.rand(3,3).cuda()) #使用.cuda()更为快捷,也可以用.cuda(0)或.cuda(1)来指定设备