DeepLearning学习笔记-HDF5

前言

理论上,HDF5与深度学习是半毛钱关系没有的,因为它定义了一种数据格式与解析方法,同时,也提供了开源库代码,但是,是因为PointNet才接触的这个库,PointNet的数据集是*.h5的文件,要想解析这个文件,就得了解下HDF5这个格式。

一、HDF5简介

HDF5全称Hierarchical Data Format翻译成中文为层次性数据格式第5版,是一种存储相同数据类型的大数据组的机制,适用于可被层次性组织且数据集需要被元数据标记的数据模型。上述介绍晦涩难懂,翻译成人话就是,可存储多组类型一致,数量一致的数据。

1.1 组织结构

在这里插入图片描述
整个文件格式的组织结构如上图所示(经典图,百度盗图,应该不算是侵权吧)。
先看左边的图吧,GroupDataset是两个核心概念,Group类似与一个文件夹(容器),其中包含多个Dataset,而Dataset中则包含数据的属性与数据本身的信息,可以将这个过程看做是win下的文件管理模式,Group是文件夹,Dataset是文件夹里面的数据,采用这种机制的目的是为了更高效的实现数据的管理,从某种意义上说,h5是实现了将多种数据存在同一个文件中进行保存与传递。
需要注意的是,Group的名字可以随便设置,但是,root点的group name是恒定的,叫做/,对于一个陌生的h5文件,只需要找到/,就可以随意访问子Group了。ps : 利用C++进行数据访问的时候就采用从root入手的方式进行遍历的。

1.2 数据构成

在这里插入图片描述
介绍图之二,介绍的是Dataset的组成关系,对于一组数据而言,需要了解一下数据的组成部分,比如,数据类型是什么,比如该数据中包含的数据的组数,以及数据本身的一些属性,在这里,会有一个Metadata的构造,其中存储的就是有关于数据本身的一系列属性,例如,Dataspace中的Dimensions可以指导如何解析Data
解释下上图中的一些数字,首先看Dataspace里面的数据Rank = 3该数据表示,在Dimensions中有3(Rank)个数据Dim 1,Dim 2, Dim 3来介绍数据;接下来讲解下Dimensions中的4,5,6,其中,4,5表示每个数据中有4行5列,6则表示有6个数据。

二、HDF5库介绍

2.1下载与安装

由于我的系统是win10,所以在这里我主要提供win下的一些方法,HDF5的下载链接为:
下载地址

2.2数据查看

数据查看,可使用的方法有:

  • HDFView
  • H5dump
    第一个工具,我下载下来了,但是,win下运行闪退,相关文档介绍需要配置java的环境,不专业,所以放弃了;
    H5dump是在py下用的,使用方法为:
H5dump *.h5

即可显示该文件中存放的数据。如果想要校验下自己文件中的数据是否正常或了解数据形式,可以通过该命令查看。

三、读取*.h5文件

vs2015相关的库可从链接中下载:
下载地址

#include <iostream>
#include <H5Cpp.h>
#include <fstream>
using namespace std;
using namespace H5;

int main(int argc, char **argv)
{
	//打开文件
	H5File file(argv[1], H5F_ACC_RDONLY);
	//获取根节点并打印root的子节点数量
	Group root(file.getObjId("/"));
	cout << "size() = " << root.getNumObjs() << endl;

	//for循环,依次访问root的子节点
	for (hsize_t i = 0; i < root.getNumObjs(); i++)
	{
		// 用 Index 为参数获取 Object 名字
		const H5std_string name = root.getObjnameByIdx(i);
		cout << "Obj_name_" << i + 1 << ": " << name.c_str() << endl;
		//打开数据
		DataSet dset(root.getObjId(name));
		DataSpace dsp = dset.getSpace();
		//记录该dataspace中的数据维度,是指有rank个维度记录数据的维度属性
		//例如,有rank个数据来记录data所包含的信息
		int rank = dsp.getSimpleExtentNdims();

		//创建数组存储数据本身的维度:2048*2048*3
		//表示:2048个数据,每组数据有2048个点位,每个点位有3个维度(xyz)组成
		//创建数组存储维度大小
		hsize_t *dims = new hsize_t[rank];
		int ndims = dsp.getSimpleExtentDims(dims);

		for (int i = 0; i < rank; i++)
			cout << "Dimension_ " << i + 1 << " = " << dims[i] << endl;

		DataType dt = dset.getDataType();
	
		//将data读取到buf中
		hsize_t data_size = dset.getInMemDataSize() / sizeof(float);
		float *buf = new float[data_size];
		dset.read(buf, dt);

		//根据属性信息,解析buf
		char file[50];
		int elementSize = 1;
		if (rank == 3) elementSize = dims[2];

		for (int count = 0; count < dims[0]; count++) {
			sprintf(file, "data//%d.asc", count);
			ofstream ofout(file);
			for (int i = dims[1] * count * elementSize; i < dims[1] * (count +1) * elementSize; i++)
			{
				if (i % elementSize != 0 && i != dims[1] * count * elementSize) ofout << buf[i] << " ";
				else ofout << endl << buf[i] << " ";
			}
			ofout.close();
		}

		delete[]dims;
		dims = nullptr;

		delete[]buf;
		buf = nullptr;
		dt.close();
		dsp.close();
		dset.close();
		system("pause");
	}
	root.close();
	file.close();

	system("pause");
	return 0;
}

四、写入*.h5文件

折腾了一上午,总算是可以将数据保存为*.h5文件了,对我而言,我用的事最简单的方法,当然,此方法可能还存在诸多bug,但目前没有过多的纠结,先以实现功能,满足需求为主,对了,在这里,我需要重申下我的需求:可手动制作PointNet的数据集。

//filename表示要保存的文件名,后缀名为h5
//indata表示要保存的数据
void createFile(char *filename, std::vector<std::vector<point>> indata)
{
	int i, j;
	int data[2][5][3] = {0};          // buffer for data to write
	for (j = 0; j <2; j++)
	{
		for (i = 0; i < 5; i++) {
			data[j][i][0] = indata[j][i](0);
			data[j][i][1] = indata[j][i](1);
			data[j][i][2] = indata[j][i](2);
		}
	}
	
	//新建文件
	H5File file(filename, H5F_ACC_TRUNC);
	//根据数据描述信息构建space
	size_t dimsf[3];
	dimsf[0] = 2;
	dimsf[1] = 5;
	dimsf[2] = 3;
	DataSpace dataspace(3, dimsf);
	//设定保存数据的类型
	IntType datatype(PredType::NATIVE_INT);
	datatype.setOrder(H5T_ORDER_LE);
	
	//创建dataset
	DataSet dataset = file.createDataSet("first", datatype, dataspace);
	//写入文件
	dataset.write(data, PredType::NATIVE_INT);
	
	//关闭数据集与文件
	dataset.close();
	file.close();
}

测试程序

int main(int argc, char **argv) 
{
	if (argc == 1) {
		//模拟数据
		std::vector<std::vector<point>> data;
		std::vector<point> epch;
		epch.push_back(point(1, 2, 4));
		epch.push_back(point(3, 2, 9));
		epch.push_back(point(4, 2, 3));
		epch.push_back(point(6, 7, 1));
		epch.push_back(point(9, 1, 8));
		data.push_back(epch);
		std::vector<point> epch1;
		epch1.push_back(point(11, 2, 4));
		epch1.push_back(point(31, 2, 9));
		epch1.push_back(point(41, 2, 3));
		epch1.push_back(point(61, 7, 1));
		epch1.push_back(point(91, 1, 8));
		data.push_back(epch1);

		createFile("out.h5", data);
	}
		
	if (argc == 2) 
		readFile(argv[1]);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值