【问题标题】:Overcome MemoryError in numpy克服 numpy 中的 MemoryError
【发布时间】:2019-08-21 23:33:41
【问题描述】:

我有一个巨大的数据框:

df.shape = (106, 3364)

当我想运行以下代码时,我得到 MemoryError

i = df.values.T
j = np.nansum((i - i[:, None]) ** 2, axis=2) ** .5

MemoryError Traceback(最近调用 最后)在 ----> 1 j = np.nansum((i - i[:, None]) ** 2, axis=2) ** .5

内存错误:

有什么方法可以避免吗?

【问题讨论】:

  • 我猜轴应该是 0(列)或 1(行)。 axis=2 没有意义,可能会制作数组的完整副本
  • 准确使用np.nansum 有多重要?如果您可以将原始数组中的 nan 值替换为零,您可以使用scipy.spatial.distance.pdist
  • (否则你可以使用 Numba 通过循环快速计算)
  • @jdehesa 不,在我的情况下,不可能用 0 填充 NaN。你能解释一下 numba 吗?
  • @Marat 即使使用轴 0 或 1 仍然出现内存错误

标签: python numpy out-of-memory


【解决方案1】:

一种选择是使用 Numba。它会消耗更少的内存,实际上也更快。

import pandas as pd
import numpy as np
import numba as nb

def compute_distances(df):
    i = df.values.T
    result = np.empty((len(i), len(i)), dtype=i.dtype)
    _compute_distances_nb(i, result)
    return result

@nb.njit(parallel=True)
def _compute_distances_nb(data, result):
    for i in nb.prange(data.shape[0]):
        for j in nb.prange(data.shape[0]):
            s = 0
            for k in nb.prange(data.shape[1]):
                d = data[i, k] - data[j, k]
                if not np.isnan(d):
                    s += np.square(d)
            result[i, j] = np.sqrt(s)

# Original method for comparison
def compute_distances_np(df):
    i = df.values.T
    return np.nansum((i - i[:, None]) ** 2, axis=2) ** .5

# Test
np.random.seed(0)
# Make random data
df = pd.DataFrame(np.random.random((100, 500)))
# Put some NaN values
df[np.random.random(df.shape) < .2] = np.nan
# Compute distances
d1 = compute_distances(df)
d2 = compute_distances_np(df)
print(np.allclose(d1, d2))
# True
%timeit compute_distances(df)
# 8.05 ms ± 698 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit compute_distances_np(df)
# 356 ms ± 14.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

np.random.seed(0)
# Make some random data
df = pd.DataFrame(np.random.random((100, 500)))
# Put some NaN values
df[np.random.random(df.shape) < .2] = np.nan
# Compute distances
d1 = compute_distances(df)
d2 = compute_distances_np(df)
print(np.allclose(d1, d2))

%timeit compute_distances(df)
# 8.05 ms ± 698 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit compute_distances_np(df)
# 356 ms ± 14.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

    猜你喜欢
    • 2017-02-14
    • 2016-04-04
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    相关资源
    最近更新 更多