打开机器学习的根元组的最快、最有效的方法是什么?

2024-10-01 04:44:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在和scikit learn建立一个机器学习项目。输入数据是平根n倍。你知道吗

在过去,我一直使用root\u numpy将NTuples转换为1.数据帧保存在h5文件中。你知道吗

我想知道我是否可以用连根拔起来
a) 完全跳过h5转换?
b) 不像从h5加载数据帧那样占用内存?你知道吗

我天真的第一次尝试是这样的:

'''
Runs preselection, keeps only desired variables in DataFrame
'''
def dropAndKeep(df, dropVariables=None, keepVariables=None, presel=None, inplace=True):

    if ((presel is not None) and (not callable(presel))):
        print("Please either provide a function to 'presel' or leave blank")
        raise ValueError

    if callable(presel):
        if not(inplace):
            df = df.drop(df[~presel(df)].index, inplace=False)
        else:
            df.drop(df[~presel(df)].index, inplace=True)

    if keepVariables is not None:
        dropThese = list( set(df.columns) - set(keepVariables) )
        return df.drop(columns=dropThese, inplace=inplace)

    if dropVariables is not None:
        return df.drop(columns=dropVariables, inplace=inplace)

'''
Loads a TTree from ROOT file into a DataFrame 
'''
def load_root(inFile, key, dropVariables=None, keepVariables=None, presel=None):
    df = uproot.open(inFile)[key].pandas.df()
    dropAndKeep(df, dropVariables, keepVariables, presel=presel, inplace=True)
    return df


inFile = "path/to/file.root"
key = "ntuple"
df = load_root(inFile, key)

这需要很长时间。有没有更好的办法?你知道吗


Tags: 数据keynonetruedfifnotroot
3条回答

我还有一个侧重点。我是在根除->;hdf5阵营;这样我可以做慢的部分(读取文件到hdf5)一次,以及合并较小的文件和做一点处理。我还保持压缩低或关闭。这可能需要4-5分钟将多个文件从根目录读取到<;10秒hdf5读取几个文件。你知道吗

我可以补充的一点是,如果您有“锯齿状”数据,比如真值信息,那么直接使用AwkwardArray(它本机支持hdf5)可以很好地工作。我使用h5py来处理HDF5文件。你可以看到我在这里做什么:https://gitlab.cern.ch/LHCb-Reco-Dev/pv-finder。你知道吗

这以前也是这样设计的,因为我没有一个可以在任何地方同时运行ROOT和ML工具的环境,但是现在我使用一个环境.yml使用Conda-forge-ROOT和ML工具(PyTorch等)对两者进行归档。你知道吗

请注意,对uproot.open(...)file [key]的每次调用都使用纯Python加载TFile和TTree元数据,这是outlot中最慢的部分。如果您多次调用它,请尝试保留TFile和/或TTree对象并重新使用它们。你知道吗

另外,看起来你的dropAndKeep函数只是在删除行(事件),但是如果我读错了,它在做列(分支),那么就使用rubot的数组读取函数的branches参数来只发送你想要的分支。由于根文件中的数据是按列排列的,因此无法避免读取不需要的事件(在任何框架中)必须在事后剪切它们。你知道吗

接下来,请注意,对于过滤事件之类的简单操作,Pandas要比NumPy慢得多。如果你想加快速度,用TTree.arrays而不是TTree.pandas.df得到数组,为你的选择构造一个布尔数的NumPy数组,并将它应用到TTree.arrays返回的dict中的每个数组。然后您可以使用Pandas的DataFrame构造器将所有这些内容放入一个DataFrame中(如果您真的需要Pandas的话)。你知道吗

的确,你不需要通过HDF5,也不需要通过Pandas。你的机器学习框架(TensorFlow?手电筒?)几乎可以肯定的是,它有一个接口可以接受零拷贝的NumPy数组(或者一个拷贝到GPU)。强调HDF5或Pandas的教程之所以这样做,是因为对于大多数用户(非HEP)来说,它们是最方便的接口。他们的数据可能已经在HDF5或Pandas中;我们的数据可能在ROOT中。你知道吗

如果您的机器学习将在GPU上,也许您也希望在GPU上进行事件选择。CuPy是完全在GPU上分配和操作的NumPy克隆,您的TensorFlow/Torch张量可能有一个到CuPy数组的零拷贝接口。原则上,如果将CuPy数组用作asarray interpretation的目标,则outlot应该能够直接从根文件写入CuPy数组。不过,我还没试过。你知道吗

如果您对要处理的根文件有控制权,请尝试使它们的篮子变大(增加刷新大小)并且使它们的数据结构简单(例如纯数字或数字的数组/向量,不要更深)。也许最重要的是,使用像lz4这样的轻量级压缩,而不是重量级的lukelzma。你知道吗

rubot可以并行读取篮子,但是只有当它有很多非Python计算要做时,比如解压缩lzma时,它才被证明是有用的。你知道吗

如果要反复读取这些数组,可能需要使用numpy.save来编写中间文件,这实际上只是磁盘上的原始字节。这意味着在读回时没有反序列化,而不是解码根文件或HDF5文件所需的工作。因为它是如此简单的格式,你甚至可以用numpy.memmap读回它,当它从磁盘懒洋洋地加载数据,甚至删除字节的显式副本时,它会窥视操作系统的页面缓存。你知道吗

并非所有这些技巧都同样有用。我试着把最重要的放在第一位,但在进行一个可能不会有太大影响的大型代码重写之前先做实验。有些技巧不能与其他技巧结合使用,例如CuPy和memmap(memmap总是懒洋洋地加载到主内存,而不是GPU内存)。但有些组合可能是有成效的。你知道吗

祝你好运!你知道吗

每个人都忘记了一个明显的因素:RDataFrame.AsNumpy(),参见https://root.cern.ch/doc/master/df026__AsNumpyArrays_8py.html

这样,就不需要临时文件,也不需要将所有内容都加载到内存中。阅读发生在本机C++速度。很高兴看到关于在https://root-forum.cern.ch工作得更好的报告!你知道吗

相关问题 更多 >