机器/深度学习代码中适用于图像和音频的一个常见用例是加载和操纵图像或音频片段的大型数据集。这些数据集中的条目几乎总是由图像/音频片段和元数据(例如课程标签,培训/测试实例等)表示。
例如,在我的语音识别的特定用例中,数据集几乎总是由具有以下属性的条目组成:
在熊猫和/或dask中表示这种数据集的推荐方式是什么-强调 wav数据(在图像数据集中,这就是图像数据本身)?
在熊猫中,使用few tricks可以将一列numpy数组嵌套在列中,但这不能很好地序列化,也不能使用dask。似乎这是一个非常普通的用例,但我找不到任何相关建议。
也可以将这些数组序列化/反序列化为二进制格式(Uber的petastorm确实something like this),但这似乎错过了dask和pandas等库的意义,在这些库中,自动魔术序列化是核心优势之一。 >
欢迎任何实用的评论或对不同方法的建议。
答案 0 :(得分:1)
您拥有的数据组织确实确实听起来很像xarray:多维数据,在每个维和变量属性上都有规则的坐标。 xarray允许您以类似于熊猫的方式对数组进行操作(文档非常详细,因此我不再赘述)。值得注意的是,xarray直接与Dask交互,因此,当您在高级数据结构上进行操作时,实际上是在操纵Dask数组,因此可以计算核外和/或分布式。
尽管受netCDF分层数据表示形式(通常存储为HDF5文件)的启发,但是您可以使用许多可能的存储选项,包括zarr,它特别适用于作为云格式来并行访问数据库。表单Dask想要使用。
答案 1 :(得分:0)
一种(也许很丑陋的)方式是修补熊猫和dask木地板API以支持多维数组:
# these monkey-patches into the pandas and dask I/O API allow us to save multi-dimensional numpy
# arrays# in parquet format by serializing them into byte arrays
from dask import dataframe as dd
import pandas as pd
from io import BytesIO
def _patched_pd_read_parquet(*args, **kwargs):
return _orig_pd_read_parquet(*args, **kwargs).applymap(
lambda val: np.load(BytesIO(val)) if isinstance(val, bytes) else val)
_orig_pd_read_parquet = pd.io.parquet.PyArrowImpl.read
pd.io.parquet.PyArrowImpl.read = _patched_pd_read_parquet
def _serialize_ndarray(arr: np.ndarray) -> bytes:
if isinstance(arr, np.ndarray):
with BytesIO() as buf:
np.save(buf, arr)
return buf.getvalue()
return arr
def _deserialize_ndarray(val: bytes) -> np.ndarray:
return np.load(BytesIO(val)) if isinstance(val, bytes) else val
def _patched_pd_write_parquet(self, df: pd.DataFrame, *args, **kwargs):
return _orig_pd_write_parquet(self, df.applymap(_serialize_ndarray), *args, **kwargs)
_orig_pd_write_parquet = pd.io.parquet.PyArrowImpl.write
pd.io.parquet.PyArrowImpl.write = _patched_pd_write_parquet
def _patched_dask_read_pyarrow_parquet_piece(*args, **kwargs):
return _orig_dask_read_pyarrow_parquet_piece(*args, **kwargs).applymap(_deserialize_ndarray)
_orig_dask_read_pyarrow_parquet_piece = dd.io.parquet._read_pyarrow_parquet_piece
dd.io.parquet._read_pyarrow_parquet_piece = _patched_dask_read_pyarrow_parquet_piece
def _patched_dd_write_partition_pyarrow(df: pd.DataFrame, *args, **kwargs):
return _orig_dd_write_partition_pyarrow(df.applymap(_serialize_ndarray), *args, **kwargs)
_orig_dd_write_partition_pyarrow = dd.io.parquet._write_partition_pyarrow
dd.io.parquet._write_partition_pyarrow = _patched_dd_write_partition_pyarrow
然后,您可以使用问题中指定的技巧在pandas细胞(内存中)中获取嵌套数组,并且上述方法将充当“穷人”编解码器,将数组序列化为字节流(不同的序列化方案例如镶木地板可以处理)