如何在给定密钥列表的情况下将h5py文件的数据集内容读入numpy数组?

时间:2017-06-19 22:52:42

标签: python arrays numpy h5py

我的函数输入是一个h5py文件和一个文本文件。文本文件有两列。第一列有一些话语信息,第二列有说话者信息(对于那个话语)。 h5py文件的密钥(使用create_datasets创建)是话语(文件的第一列)。每个数据集都有一个固定维度(600,)的numpy数组(只有一个)。 h5py文件比文本文件中的话语具有更多的话语。 h5py文件中可能不存在文本文件中的某些话语。

我的函数的预期输出:两个numpy数组

第一个数组(我们称之为X)应该是形状的((nutts,600),dtype ='float')

第二个数组(我们称之为y)应该是形状的((nutts,),dtype ='int')

其中,nutts是h5文件中(实际)存在的文本文件的发音数量(nutts< = total_lines_in_text_file)

注意:我不提前知道坚果。我必须动态创建X和y。

从上面的描述中可以清楚地看到创建X的方法:

对于文本文件中的第一个话语,我检查该话语是否作为h5file中的键存在。如果它存在,我拿numpy数组(600维)并放入X的第一行然后迭代(提醒我不知道'nutts'提前所以我不能用零预先初始化X.所以我把它们保存为dict并尝试将dict转换为numpy数组,一旦我将它们全部到位

更多关于y: 所有的坚果可以对应于nspkrs(nspkrs< = nutts)。多个话语可以映射到同一个发言者。我想用numpy数组格式编码每个话语的扬声器信息。对于spkr1,我给出一个0的标签,对于spkr n,我给出一个n-1的标签。

这是我做的:

h5f = h5py.File('some.h5', 'r')

import pandas as pd

import numpy as np


def load_data(h5f, src_u2s_list):

    with open(src_u2s_list) as f:

        content = f.read().splitlines()

    utt2ivec = {}
    utt2lbl = {}
    spk2spk_class = {}
    spk_id = -1
    for u2s in content:
        utt, spk = u2s.split()
        if spk not in spk2spk_class.keys():
            spk_id += 1
            spk2spk_class[spk] = spk_id

        if utt in h5f.keys():
            utt2ivec[utt] = h5f[utt][:]
            utt2lbl[utt] = spk2spk_class[spk]
        else:
            print("Utterance {0} does not exist in h5file".format(utt))

    data_X = pd.Series(utt2ivec)
    data_y = pd.Series(utt2lbl)

    return data_X.values, data_y.values

主要考虑因素:

  1. h5file有大约100,000个话语,文本文件大约有70000个话语。因此,此代码运行非常慢
  2. 我是使用h5py文件的新手。欢迎提出建议或整个代码重组。
  3. 我想避免使用熊猫。
  4. 非常重要:X和y中的话语顺序应该相同。这意味着X和y的行应该对应于相同的话语。
  5. 很抱歉有很长的描述。我想说清楚,以避免混淆。

    提前谢谢

1 个答案:

答案 0 :(得分:0)

通常,当我们想要将一堆数组(大小相等)收集到2d数组中时,我们首先将它们附加到列表中,然后从最后创建数组:

utt2ilist = []
...
    if utt in h5f.keys():
        utt2ilist.append(h5f[utt][:])
    ...
utt2iarr = np.array(utt2ilist)

我不知道有任何方法可以同时加载多个数据集,至少不能加载h5py。您只需找到相关的key并按原样加载即可。如果你有大量的数据集,每个数据集相对较小(600个元素),这可能需要时间。注意数据集的大小是否不同 - 然后结果将是对象dtype数组,而不是2d数组。

我认为可以在类似的列表中收集spk2spk_class[spk]

使用这样的列表将按照读取的顺序对它们进行排序。使用字典和pandas将按utt索引它们。使用字典中介,您可能会丢失有关阅读顺序的信息。

我打算为defaultdict建议spk2spk_class,但你不是在计算对象,而只是给它们唯一的ID。

我的猜测是,缓慢来自于阅读大量的话语,而不是来自收集机制本身。但是我没有测试你的数据。