3.3 改变数据集的形状
目前为止,我们已经了解数据集有形状和类型。类型是固定的,不可更改。但是形状可以在一定范围内被改变。
让我们创建一个具有4个元素的数据集看看:
查看一下dset的特征,我们会看到除了.shape特征以外,还有一个叫maxshape的特征:
Dataset对象还有一个叫resize的方法。让我们看看当我们试图将数据集从(2, 2)缩小为(1, 1)时会发生什么:
很明显我们漏掉了某些东西。究竟如何才能改变一个数据集的形状呢?
3.3.1 创建可变形数据集
在你创建数据集时,除了设置其形状,你还可以通过h5py设置是否允许它改变形状,称为maxshape。
和shape一样,maxshape在创建数据集时指定,且无法更改。如前所见,如果你不指定一个maxshape,HDF5会创建一个不可变形的数据集,并设置maxshape = shape。数据集还可以被创建为使用连续存储,这也将导致resize不可用。第四章会对连续存储和分块存储做更详细的说明。我们现在先忽视其细节。
让我们再试一次,这次我们为数据集指定一个maxshape:
成功!改回来行不行呢?
maxshape这个名字告诉你,你不能将一个数据集的shape变的大于maxshape。但如果你在创建数据集的时候还不知道最后形状会变得多大怎么办?是不是应该提供一个超大的数值给maxshape来跨过这个障碍呢?
谢天谢地没这个必要。HDF5有一个“无限”维度的概念来处理这种情况。如果一个维度被声明为“无限”,你可以使其变得任意大。你只需要在maxshape参数上指定该维度为None:
你可以将任意维度声明为无限。
最后,无论maxshape参数为何,你都不能改变维度的个数。这被称为数据集的阶数(rank),阶数是固定的,永远不能改变:
3.3.2 用resize重新组织数据
在你改变数据集形状时NumPy会遵循一组规则。以下面这个形状为(2, 2)的4元素方形数组为例:
现在我们将其resize为(1, 4),保持元素总个数不变,那么所有的值都在,但是会被重新组织:
最后我们将其resize为(1, 10),增加新的元素,那么增加的新元素会被初始化为0。
如果你以前曾经改变过NumPy数组的形状,你应该已经习惯了这种重新组织的行为。HDF5则不同,不会进行重新组织。让我们创建一个具有两个无限维度的Dataset对象进行实验:
现在我们尝试如上例NumPy那样对其进行resize:
发生了什么?当我们将形状从(2, 2)改变为(1, 4)时,位于dset[1,0]和dset[1,1]的数据没有被重新组织,它们被丢掉了。所以在使用resize时你必须非常当心。你在NumPy世界里习以为常的重新组织的把戏很快会产生问题。
最后,你会注意到上例中的新元素都被初始化为0。它们通常都会被设置为数据集的fill value(见25页,默认填充值)。
3.3.3 何时以及如何进行resize
HDF5最常见的问题之一是如何给数据集添加数据。resize可以做到这一点,但是要注意性能。
假设我们已经有一个数据集记录了很多条时序,每条时序有1 000个元素。不过我们的应用程序不知道一共需要存储多少条时序,可能是10、100或1 000条。一种方案如下:
每当我们新增一条1 000元素的时序,数据集都会扩展一条记录。但是如果调用resize的次数等于插入的次数,性能不会很好,特别是当需要新增成千上万条记录时。
另一种方案是记住插入的次数并在结束时“削减”数据集:
在真实世界里,为了获得最佳性能,还有更多的工作要做。如果不讨论HDF5是如何存储数据的,我们就只能讲到这里。所以接下来我们就进入第4章去讨论存储,或者更精确地说,分块存储。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论