按最大大小将 numpy 数组拆分为块

2024-01-01

我有一些very大型二维 numpy 数组。一个数据集有 55732 x 257659 个元素,超过 140 亿个元素。因为有些操作我需要执行 throwMemoryErrors,我想尝试将数组分割成一定大小的块,然后针对这些块运行它们。 (我可以在每个部分运行操作后汇总结果。)我的问题是MemoryErrors这意味着我可以以某种方式限制数组的大小,而不是将它们分成恒定数量的部分,这一点很重要。

例如,让我们生成一个 1009 x 1009 的随机数组:

a = numpy.random.choice([1,2,3,4], (1009,1009))

我的数据不一定可以均匀分割,并且绝对不能保证可以按我想要的大小分割。所以我选择了 1009,因为它是素数。

假设我希望它们不大于 50 x 50 的块。由于这只是为了避免非常大的数组出现错误,所以如果结果不准确也没关系。

我怎样才能把它分成所需的块?

我正在使用 Python 3.6 64 位和 numpy 1.14.3(最新)。

Related

我见过这个函数使用reshape https://stackoverflow.com/a/16858283/1394393,但如果行数和列数不能完全除以大小,则该方法不起作用。

这个问题 https://stackoverflow.com/q/14406567/1394393(以及其他类似的)有解释如何分割成一定数量的块的答案,但这并没有解释如何分割成一定大小的块。

我也看到了这个问题 https://stackoverflow.com/q/39877999/1394393,因为这实际上是我的问题。答案和评论建议切换到 64 位(我已经有了)并使用numpy.memmap。都没有帮助。


这样做可以使所得数组的形状稍微小于所需的最大值,或者使得它们恰好具有所需的最大值,除了末尾的一些剩余部分。

基本逻辑是计算分割数组的参数,然后使用array_split https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.array_split.html沿数组的每个轴(或维度)分割数组。

我们需要numpy and math模块和示例数组:

import math
import numpy

a = numpy.random.choice([1,2,3,4], (1009,1009))

略小于最大值

逻辑

首先将最终块大小的形状沿着您想要将其分割成元组的每个维度存储:

chunk_shape = (50, 50)

array_split一次仅沿一个轴(或维度)或一个数组进行分割。因此,让我们从第一个轴开始。

  1. 计算我们需要将数组分割成的部分的数量:

    num_sections = math.ceil(a.shape[0] / chunk_shape[0])
    

    在我们的示例中,这是 21 (1009 / 50 = 20.18).

  2. 现在将其分开:

    first_split = numpy.array_split(a, num_sections, axis=0)
    

    这为我们提供了 21 个(请求的部分的数量)numpy 数组的列表,这些数组被分割,因此它们在第一维中不大于 50:

    print(len(first_split))
    # 21
    print({i.shape for i in first_split})
    # {(48, 1009), (49, 1009)}
    # These are the distinct shapes, so we don't see all 21 separately
    

    在本例中,它们沿着该轴分别为 48 和 49。

  3. 我们可以对第二个维度的每个新数组执行相同的操作:

    num_sections = math.ceil(a.shape[1] / chunk_shape[1])
    second_split = [numpy.array_split(a2, num_sections, axis=1) for a2 in first_split]
    

    这给了我们一个列表的列表。每个子列表包含我们想要的大小的 numpy 数组:

    print(len(second_split))
    # 21
    print({len(i) for i in second_split})
    # {21}
    # All sublists are 21 long
    print({i2.shape for i in second_split for i2 in i})
    # {(48, 49), (49, 48), (48, 48), (49, 49)}
    # Distinct shapes
    

功能齐全

我们可以使用递归函数实现任意维度:

def split_to_approx_shape(a, chunk_shape, start_axis=0):
    if len(chunk_shape) != len(a.shape):
        raise ValueError('chunk length does not match array number of axes')

    if start_axis == len(a.shape):
        return a

    num_sections = math.ceil(a.shape[start_axis] / chunk_shape[start_axis])
    split = numpy.array_split(a, num_sections, axis=start_axis)
    return [split_to_approx_shape(split_a, chunk_shape, start_axis + 1) for split_a in split]

我们这样称呼它:

full_split = split_to_approx_shape(a, (50,50))
print({i2.shape for i in full_split for i2 in i})
# {(48, 49), (49, 48), (48, 48), (49, 49)}
# Distinct shapes

精确形状加上余数

逻辑

如果我们想要更花哨一点并且让所有新数组都是exactly除了尾部剩余数组之外的指定大小,我们可以通过传递要分割的索引列表来做到这一点array_split.

  1. 首先建立索引数组:

    axis = 0
    split_indices = [chunk_shape[axis]*(i+1) for i  in range(math.floor(a.shape[axis] / chunk_shape[axis]))]
    

    这给出了一个索引列表,每个索引从最后一个开始:

    print(split_indices)
    # [50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000]
    
  2. 然后拆分:

    first_split = numpy.array_split(a, split_indices, axis=0)
    print(len(first_split))
    # 21
    print({i.shape for i in first_split})
    # {(9, 1009), (50, 1009)}
    # Distinct shapes, so we don't see all 21 separately
    print((first_split[0].shape, first_split[1].shape, '...', first_split[-2].shape, first_split[-1].shape))
    # ((50, 1009), (50, 1009), '...', (50, 1009), (9, 1009))
    
  3. 然后再次对于第二个轴:

    axis = 1
    split_indices = [chunk_shape[axis]*(i+1) for i  in range(math.floor(a.shape[axis] / chunk_shape[axis]))]
    second_split = [numpy.array_split(a2, split_indices, axis=1) for a2 in first_split]
    print({i2.shape for i in second_split for i2 in i})
    # {(9, 50), (9, 9), (50, 9), (50, 50)}
    

功能齐全

调整递归函数:

def split_to_shape(a, chunk_shape, start_axis=0):
    if len(chunk_shape) != len(a.shape):
        raise ValueError('chunk length does not match array number of axes')

    if start_axis == len(a.shape):
        return a

    split_indices = [
        chunk_shape[start_axis]*(i+1)
        for i in range(math.floor(a.shape[start_axis] / chunk_shape[start_axis]))
    ]
    split = numpy.array_split(a, split_indices, axis=start_axis)
    return [split_to_shape(split_a, chunk_shape, start_axis + 1) for split_a in split]

我们以完全相同的方式称呼它:

full_split = split_to_shape(a, (50,50))
print({i2.shape for i in full_split for i2 in i})
# {(9, 50), (9, 9), (50, 9), (50, 50)}
# Distinct shapes

额外说明

表现

这些功能看起来相当快。我能够使用以下任一函数在 0.05 秒内将示例数组(包含超过 140 亿个元素)拆分为 1000 x 1000 个形状块(产生超过 14000 个新数组):

print('Building test array')
a = numpy.random.randint(4, size=(55000, 250000), dtype='uint8')
chunks = (1000, 1000)
numtests = 1000
print('Running {} tests'.format(numtests))
print('split_to_approx_shape: {} seconds'.format(timeit.timeit(lambda: split_to_approx_shape(a, chunks), number=numtests) / numtests))
print('split_to_shape: {} seconds'.format(timeit.timeit(lambda: split_to_shape(a, chunks), number=numtests) / numtests))

Output:

Building test array
Running 1000 tests
split_to_approx_shape: 0.035109398348040485 seconds
split_to_shape: 0.03113800323300747 seconds

我没有测试更高维数组的速度。

形状小于最大尺寸

如果任何维度的大小小于指定的最大值,这些函数都可以正常工作。这不需要特殊的逻辑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

按最大大小将 numpy 数组拆分为块 的相关文章

随机推荐

  • Java:调用目标异常

    我在 Java 中动态创建类并尝试调用其中的方法 但是 有时我会得到一个java lang reflect InvocationTargetException PageGenerator1 java 动态创建 import java io
  • 无法使用 Mono Soft Debugger 远程调试,因为“调试器代理:DWP 握手失败”错误

    我已在我的应用程序中嵌入了单声道 该应用程序是支持插件的控制台应用程序 插件是 NET 程序集 一切都很好 但我想调试它们 为了在我的 C 代码中启用调试 我有 mono set dirs ASSEMBLIES DIR NAME ASSEM
  • 在 UpSetR 中使用矩阵点的调色板

    下面我构建了一个心烦意乱的情节 https www ncbi nlm nih gov pmc articles PMC4720993 我使用调色板来定义条形颜色 有没有办法对连接点的矩阵也做到这一点 library dplyr librar
  • “netcoreapp1.0”是不受支持的框架。 - Asp.Net Core 音乐商店

    我只是第一次尝试 asp net core 打开刚刚更新的音乐商店应用程序 https github com aspnet MusicStore但我无法构建 Nuget 告诉我 Errors in C development MusicSt
  • Spring Boot 基于角色的身份验证

    我有一个关于 Spring Boot 基于角色的身份验证的问题 基本上 我希望拥有用户和管理员 并且我想阻止用户访问管理资源 所以我创建了一个 SecurityConfig 类 package test import org springf
  • Javascript:将字符串拆分为二维数组

    我有一串月份和年份 var months 2010 1 2010 3 2011 4 2011 7 我想将其制作成一个二维数组 其中年份位于每个数组的第一个位置 月份位于第二个位置 换句话说 我想以这样的方式结束 var monthArray
  • IOS 应用程序加载器显示捆绑错误

    我已经浪费了3天的时间 解决 这个问题 实际上我已经尝试了我能想象到的一切 但一无所获 当我的应用程序二进制上传时 我收到以下错误 错误 ITMS 9000 此捆绑包无效 armv7 需要包含 armv7 架构 在软件资产 软件资产 MZI
  • 如何禁用特定 @FeignClient 上的 eureka 查找

    我有一个微服务使用 FeignClient主要是与其他微服务对话 使用 Eureka 服务发现机制可以完美地实现这一点 现在我迫切需要使用 FeignClient连接到外部系统并仍然使用如下所示的配置执行负载平衡 Feign client
  • WPF MEF + Prism 初始区域加载

    我在 WPF 中使用 MEF 和 Prism 编写了一个具有三个不同区域的 MVVM 应用程序 代码跨两个模块 在 App Config 中发现 我的所有导航命令和结构都工作得很好 但我感到困惑的一件事是如何设置在应用程序启动时加载到每个区
  • 如何在不序列化的情况下将对象作为输入传递给 WorkManager?

    我需要将复杂的对象传递给 WorkManager 或者我需要序列化包含 Livedata 和 Date 的对象 它抛出 java lang IllegalArgumentException Key cabId2 has invalid ty
  • R 中嵌套随机效应模型的模型预测?

    我正在尝试拟合具有随机效应的混合模型 lmer基于数据集 df 的模型这个例子在这里 https stackoverflow com a 76510072 7258020 但是 我遇到了一个错误 指出 times 参数无效 有关如何修复它的
  • 强制打开“另存为...”弹出窗口,在文本链接中打开,单击查看 HTML 格式的 PDF

    我的网站上有一些大尺寸的 PDF 目录 我需要将它们链接为下载 当我用谷歌搜索时 我发现了下面提到的这样的事情 它应该打开 另存为 点击链接时弹出 但它不起作用 当我链接到如下文件时 它只是链接到文件并尝试打开该文件 a href file
  • Java中解析固定宽度文本日志的策略

    我试图找出如何最好地解析以下日志文 件 分割由水平线分隔的每个部分并提取各种数据 例如 COMPANY123 BIMMU 日期 2 18 等 然后创建一个字符串 其中包含由水平线分隔的部分中包含的所有其他数据 即 我想创建一个 语句 对象数
  • 如何关闭冻结的 SSH 会话?

    有时 由于互联网连接不良 与远程服务器的 SSH 会话会无限期冻结 是否可以在不关闭终端的情况下关闭会话 按以下三个键 Enter 波形符 时期 这是 断开连接 功能 如ESCAPE CHARACTERS的部分ssh man page
  • 快速聚焦文本字段

    我在注册屏幕上有 4 个文本字段 我将其设置为当用户在每个文本字段上按 下一步 时 下一个文本字段将获得焦点 代码如下 func textFieldShouldReturn textField UITextField gt Bool if
  • Enterprise Architect 项目编程语言

    在Enterprise Architect中 当我对类进行建模并指定该类的实现语言 然后在用例中使用该类的实例时 用例中实例的实现语言不是该类的实现语言 而是默认值 有没有办法让Enterprise Architect使用该类设定的实现语言
  • 输出具有多个工作表的单个 Excel 文件

    Talend Open Studio for Data Integration 中是否有一个组件能够输出单个 Excel 文件 但其中包含 2 个单独的工作表 我想将原始文件中的一些列分隔到另一个工作表中 并将另一组列分隔到第二个工作表中
  • 使用 ksoap2-android 订阅共享点 Web 服务时出现身份验证错误

    我正在编写一个Android应用程序 它将使用sharepoint 2010中lists amx服务的getlist 方法 我正在使用kso ap2 android来处理我的soap消息 当我尝试进行身份验证时 出现预期的 xmlpullp
  • AlarmManager 阻塞主线程

    我已经实现了一个调用服务的 AlarmManager 问题是 虽然我在 AsyncTask 中启动它 但它阻塞了主线程 这是我的 AsyncTask 的来源 private class NotificationsServiceTask ex
  • 按最大大小将 numpy 数组拆分为块

    我有一些very大型二维 numpy 数组 一个数据集有 55732 x 257659 个元素 超过 140 亿个元素 因为有些操作我需要执行 throwMemoryErrors 我想尝试将数组分割成一定大小的块 然后针对这些块运行它们 我