【问题标题】:MemoryError with large data frame in deep learning深度学习中大数据框的 MemoryError
【发布时间】:2019-11-30 19:17:30
【问题描述】:

序言

大家好,

我正在尝试使用 StellarGraph 包制作几何深度学习模型。对于较小的数据集,它工作得很好,但不幸的是它不能扩展到更大的数据集。机器、环境、使用的数据和产生的错误信息如下。

机器规格:

  • CPU:英特尔酷睿 i5-8350U
  • 内存:8GB DDR4
  • SWAP:4 GB + 4 GB(在不同 SSD 中分为两个交换文件)
  • SSD:250 GB + 250 GB(2280 和 2242 NVMe)

环境:

  • Linux 5.3.11_1 64 位
  • Python 3.6.9

使用的数据(从sys.getsizeof()获取的大小):

  • 稀疏块对角矩阵(形状:158,950 x 158,950;大小:56)
  • 密集特征矩阵(形状:158,950 x 14,450;大小:9,537,152)

模块:

  • networkx 2.3
  • numpy 1.15.4
  • pandas 0.25.3
  • scipy 1.1.0
  • scikit-learn 0.21.3
  • stellargraph 0.8.2
  • tensorflow 1.14.0

问题描述

我的目标是创建一种几何深度学习,以根据从静息状态功能性 MRI 获得的邻接矩阵对主题进行分类。邻接矩阵假设有 55 个感兴趣区域,从而为所有主题生成 55x55 个矩阵。在构建深度学习模型时,我使用了来自StellarGraph 的谱图卷积网络模型,它以图对象和节点特征作为输入。我从通过组合来自所有主题的邻接矩阵获得的稀疏块对角矩阵创建了图形对象。而节点特征是每个节点的特征(1个节点有5个特征值),构造成密集块对角矩阵。

之前,我使用人口样本的一个子集(大约 170 个)制作模型。它运行得很好,我认为我可以使用更大的数据集来做同样的事情。不幸的是,在注册StellarGraph 对象时,使用相同的代码我得到了MemoryError。代码和错误将在下一节中介绍。

代码和错误

# Data parsing with scipy.io as sio and pandas as pd
data = sio.mmread('_data/sparse.mtx')
feature = sio.mmread('_data/sparse-feature.mtx')
feature = pd.DataFrame.sparse.from_spmatrix(feature)

# Create graph object using networkx as nx
g = nx.from_scipy_sparse_matrix(data)

# Create StellarGraph object and its generator
gs = StellarGraph(g, node_features=feature) # MemoryError
generator = FullBatchNodeGenerator(gs)

很抱歉,由于保密原因,我没有提供sparse.mtxsparse-feature.mtx 文件,但我希望前面关于数据形状和大小的描述可以帮助您理解它的构造。使用上面的代码,python给了我以下错误:

>>> gs = StellarGraph(g, node_features=feature) # MemoryError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lam/.local/lib/python3.6/site-packages/stellargraph/core/graph.py", line 786, in __init__
    super().__init__(incoming_graph_data, **attr)
  File "/home/lam/.local/lib/python3.6/site-packages/stellargraph/core/graph.py", line 381, in __init__
    node_features, type_for_node, node_types, dtype
  File "/home/lam/.local/lib/python3.6/site-packages/stellargraph/core/graph.py", line 216, in _convert_from_node_data
    {node_type: data}, node_type_map, node_types, dtype
  File "/home/lam/.local/lib/python3.6/site-packages/stellargraph/core/graph.py", line 182, in _convert_from_node_data
    data_arr = arr.values.astype(dtype)
  File "/home/lam/.local/lib/python3.6/site-packages/pandas/core/generic.py", line 5443, in values
    return self._data.as_array(transpose=self._AXIS_REVERSED)
  File "/home/lam/.local/lib/python3.6/site-packages/pandas/core/internals/managers.py", line 822, in as_array
    arr = mgr._interleave()
  File "/home/lam/.local/lib/python3.6/site-packages/pandas/core/internals/managers.py", line 840, in _interleave
    result = np.empty(self.shape, dtype=dtype)
MemoryError

在监控内存消耗时,我观察到 RAM 仅使用了其总容量的 55%,并且根本没有使用交换空间。在运行代码时,我只使用了 TTY + tmux,并且只运行了 vimtoppython 会话。此外,我还确保没有其他占用内存的进程在后台运行。所以我确定内存瓶颈很可能是由python引起的。

我尝试过的

为了利用内存消耗,我尝试使用dask 来管理密集的feature 数据帧。不幸的是,StellarGraph 函数只能将 pandas 数组、pandas 数据框、字典、元组或其他可迭代对象作为其输入。

除了dask,我还尝试使用稀疏矩阵(因为无论如何我的数据集几乎 80% 都是零值)。但是,它给了我TypeError,因为StellarGraph 不能将稀疏矩阵作为其node_features

我还阅读了几种管理大型数据集的解决方案,这些解决方案(大部分)建议将数据迭代解析到 python 会话中。但是,我在StellarGraph 中找不到关于这种方法的任何文档。

另一种选择是使用硬件更好的计算机,但遗憾的是,由于资金有限,我无法做到这一点。我是学生,暂时买不起更好的机器。

可能的解决方案

  • 升级内存。我会尝试从其他计算机上抢救 RAM,但我目前的最大大小为 16 GB。我不确定这是否足够。
  • 使用较小的feature 数据集块。我设法采用了这个解决方案,但模型的准确度真的很差(50-ish %)。

问题

  1. 为什么python 在没有动态交换分配的情况下只使用我总 RAM 的 55%?
  2. 应该如何有效管理大数据框?
  3. 在创建StellarGraph 对象时如何处理MemoryError
  4. 我实际需要多少 RAM? 32GB 就够了吗?

【问题讨论】:

    标签: python-3.x dataframe deep-learning bigdata graph-theory


    【解决方案1】:

    Python 工作正常。这是由 StellarGraph 引起的实现问题。

    我认为到目前为止 StellarGraph 不支持巨大的矩阵。

    File "/home/lam/.local/lib/python3.6/site-packages/stellargraph/core/graph.py", line 182, in _convert_from_node_data
    data_arr = arr.values.astype(dtype)
    

    从您的代码开始到这里,您的所有数据都存储为稀疏数组,不会占用太多内存。在这里,arr 应该是一个 DataFrame,其列为 pandas.SparseArray。这行代码将数据结构转换为普通的numpy数组,导致内存使用崩溃。

    import numpy as np
    a = np.empty((158950,14450),float)
    print(a.nbytes/2**30)
    17.112698405981064
    

    这里一个空的numpy数组实际占用17G内存。我可以在我的 16 G 计算机上初始化 3 个数组。然后,如果我尝试获得超过 3 个,则会出现内存错误。而且我无法初始化 158,950 x 158,950 numpy 数组。

    【讨论】:

    • 您好,感谢您测试内存问题并确认 StellarGraph 的限制。是的,不幸的是 StellarGraph 目前不支持稀疏矩阵作为输入。有没有办法执行批量模型训练以利用内存消耗?
    • 你想在这里运行哪种学习算法?也许你可以切换到另一个开源库。
    猜你喜欢
    • 2017-10-20
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2018-11-05
    • 2020-04-23
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多