3 | PyTorch张量操作:元素类型、GPU交互、NumPy交互、存储

张量的元素类型

与列表不同的是,张量只能用来处理数值类型,不像Python列表,什么类型都可以往里面放,下面就是tensor中可以处理的数值类型

  • torch.float32 或 torch.float 32位浮点数
  • torch.float64 或 torch.double 64位双精度浮点数
  • torch.float16 或 torch.half 16位半精度浮点数
  • torch.int8 8位有符号整数
  • torch.uint8 8位无符号整数
  • torch.int16 或 torch.short 16位有符号整数
  • torch.int32 或 torch.int 32位有符号整数
  • torch.int64 或 torch.long 64位有符号整数
  • torch.bool 布尔类型

不同的元素类型直接影响tensor在内存中所占用的内存块大小,比如32位浮点数就占用32个bite,而64位则占用64个bite,所以在需要优化模型性能的时候可以考虑降低精度。
对于PyTorch来说,如果不做特殊处理,在构建浮点数tensor时默认使用float32,也就是32位浮点数,在构建整数tensor的时候使用的是int64,64位有符号整数

关于元素类型的操作:
除了默认情况以外,我们当然可以手动的来修改元素类型。比如在构建tensor的时候在后面加上dtype参数,并指定具体的类型

double_points = torch.ones(10, 2, dtype=torch.double)
short_points = torch.tensor([[1, 2], [3, 4]], dtype=torch.short)

对于tensor也有一个dtype方法,可以用来查看当前tensor的元素类型

short_points.dtype
outs:torch.int16 #这里输出了类型为int16

除了上述的指定类型,我们还可以用转换函数,我理解这些是强制转换函数?

double_points = torch.zeros(10, 2).double()
short_points = torch.ones(10, 2).short()
double_points = torch.zeros(10, 2).to(torch.double)
short_points = torch.ones(10, 2).to(dtype=torch.short)

这里有用到to()方法,这是一个比较神奇的方法,除了转换元素类型,还可以接收其他参数,我们后面会看到。
在进行运算的时候,两个精度不同的tensor如果需要进行操作,那么低精度类型的tensor会自动转成较高精度的tensor。
下面的例子中,一个double类型的与一个short类型的进行运算,结果变成了double类型。

points_64 = torch.rand(5, dtype=torch.double)  # <1>
points_short = points_64.to(torch.short)
points_64 * points_short 
outs:tensor([0., 0., 0., 0., 0.], dtype=torch.float64)

把张量存储到GPU

PyTorch提供了设备的概念,方便在不同的运算单元上转移我们的tensor数据以及运算。前面我们都没有指定设备,默认就是在CPU上进行运算,如果我们像下面这样指定它的设备device,就可以使用GPU来进行加速计算了:

points_gpu = torch.tensor([[4.0,1.0], [5.0, 3.0], [2.0,1.0]], device='cuda')

或者这里也可以用我们前面提到的to()方法,当存在多个GPU的时候也可以根据GPU的序号来指定使用哪个GPU

points_gpu = points.to(device='cuda')
points_gpu = points.to(device='cuda:0')

数据建立在GPU上之后,运算也都是在GPU上进行的,在需要的时候我们可以指定把数据传回CPU,比如

points_cpu = points_gpu.to(device='cpu')
#还有更简略的写法如下,但是我觉得用to()更规范一点,而且to()还可以支持其他的操作
points_gpu = points.cuda()  
points_gpu = points.cuda(0)
points_cpu = points_gpu.cpu()

与NumPy的交互

前面多次提到了NumPy,可能有人不熟悉NumPy,比如像我,但是它确实是Python数据科学中及其重要的一个库,所以PyTorch的很多操作跟NumPy也都是互通的。下面的代码展示了如何把一个PyTorch的tensor转换成NumPy的array,这里需要注意的是,经过这步操作,PyTorch的tensor与NumPy的array是共享底层存储的,也就是这里的tensor和array其实都是底层数据的一个虚拟镜像,当你修改NumPy数组的时候tensor的数据也会发生变化。

points = torch.ones(3, 4)
points_np = points.numpy()
points_np
outs:array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]], dtype=float32)

既然能把tensor转换成NumPy array,那么也可以把NumPy array转换成tensor

points = torch.from_numpy(points_np)

序列化

作为深度学习的框架,对数据的存储和加载当然是十分重要的,对于大模型一次训练都需要很长的时间,没有人喜欢每次都重新训练模型,所以要把这些数据好好的保存下来。PyTorch中提供了序列化方法

# 存储tensor 方法1
torch.save(points, '../data/p1ch3/ourpoints.t')
# 存储tensor 方法2
with open('../data/p1ch3/ourpoints.t','wb') as f:
   torch.save(points, f)
#读取tensor 方法1
points = torch.load('../data/p1ch3/ourpoints.t')
#读取tensor 方法2
with open('../data/p1ch3/ourpoints.t','rb') as f:
   points = torch.load(f)

上面的存储方法把tensor保存到了outpoints文件,但是这个文件只能由PyTorch进行读取,这里作者又介绍了一种额外的方法,可以把tensor保存成其他项目也可以读取的格式。这里使用的库是h5py。

#注意这个库需要单独安装
import h5py

#存储数据,这里输入了一个key‘coords’,我理解这个存储是key-value格式的,这个key应该是可以自定义的?
f = h5py.File('../data/p1ch3/ourpoints.hdf5', 'w')
dset = f.create_dataset('coords', data=points.numpy())
f.close()

#读取数据
f = h5py.File('../data/p1ch3/ourpoints.hdf5', 'r')
dset = f['coords']
last_points = dset[-2:]

#把数据恢复到tensor中
last_points = torch.from_numpy(dset[-2:])
f.close()

关于张量操作的其他API

前面我们介绍了一些tensor操作,不过关于tensor操作还有各种各样的API,作者也没办法都讲一遍,所以作者让大家自己去看PyTorch官方文档,关于API的种类大概有如下几种:

  • 构造张量,像前面提到的zeros,ones,还有从numpy中读取from_numpy()等
  • 索引、切片、连接、转换
  • 张量运算,这里面涉及的API比较多,比如tensor的加减乘除,归约,比较,频谱变换等等
  • 随机采样
  • 存储和加载,比如load()和save(),这个可能会比较频繁的用到
  • 并行计算
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值