【问题标题】:Stacking multidimensional numpy arrays with one different dimension堆叠具有一个不同维度的多维 numpy 数组
【发布时间】:2017-12-23 21:54:53
【问题描述】:

好吧 - 假设我有两个 numpy 数组,形状是:

(185, 100, 50, 3)

(64,  100, 50, 3)

包含的值是 185 或 64 帧视频(对于每一帧,宽度为 100 像素,高度为 50,3 个通道,这些只是图像。图像的细节保持不变 - 唯一改变的值是每个视频的帧数) 我需要将它们都放入一个具有某种形状的数组中,例如

(2, n, 100, 50, 3)

包含两个视频的位置(通过神经网络作为批次运行)

我已经尝试过使用 np.stack - 但我明白了

ValueError: all input arrays must have the same shape

【问题讨论】:

  • 那么,n 一定是什么?
  • 为什么不是形状数组(185+64、100、50、3)?您希望 NN 学习什么任务以及这两个视频如何与该任务相关?
  • @Divakar 在我的网络维度中 - 我可以分配“无”,它允许不明确的长度。 numpy 有什么类似的吗,还是我必须制作数组 (2,185,100,50,3) 并用零填充 (64,100,50,3)...?
  • 从带有数值的较小样本(5,3) 和(4,3) 开始,然后您可能会期望得到(2,n,3) 形状的数组。那么,预期的输出必须是什么?
  • 通过用零填充然后连接/堆栈/随便什么,使较小的数组与较大的数组大小相同。

标签: python arrays numpy multidimensional-array neural-network


【解决方案1】:

这是我的一个快速集思广益的想法,以及策略和 Python 代码。注意:我打算只发表评论,但为了说明这个想法,我需要输入一些代码。所以我们开始吧! (喝杯咖啡/建议喝点烈酒……)

 当前状态

  • 我们有视频 1 vid1 4D 形状 (185, 100, 50, 3)
  • 我们有视频 2 vid2 4D 形状 (64, 100, 50, 3)
  • ... 其中形状代表(frame ID, width, height, RGB channels)
  • 我们希望将两个视频“堆叠”在一起,作为一个具有 5D 形状 (2, n, 100, 50, 3) 的 numpy 数组。注意:2 因为我们正在堆叠 2 个视频。 n 是我们可以选择的超参数。我们保持视频大小不变 (100 width x 50 height x 3 RGB channels)

 机会

我看到的第一件事是vid1 的帧数大约是vid2 的 3 倍。我们用60 作为公因数呢?即让我们将超参数n 设置为60。 (注意:可能需要一些“帧裁剪”/“帧丢弃” - 这将在下面介绍。)

 策略

 第 1 阶段 - 裁剪两个视频(丢弃一些帧)

让我们将vid1 和vid2 裁剪为60 的倍数的整数(我们的n - 超参数)。具体来说:

  • 裁剪vid1,使形状变为(180, 100, 50, 3)。 (即我们丢弃最后 5 帧)。我们将此新裁剪的视频称为vid1_cropped。
  • 裁剪vid2,使形状变为(60, 100, 50, 3)。 (即我们丢弃最后 4 帧)。我们将此新裁剪的视频称为vid2_cropped。

 第 2 阶段 - 将两个视频都设为 60 帧

  • vid2_cropped 已经是 60 帧,形状为 (60, 100, 50, 3)。所以我们不要管它。
  • vid1_cropped 但是是 180 帧。所以我建议我们通过平均 3 帧批次中的 RGB 通道值来将此视频减少到 60 帧 - 对于所有像素位置(沿宽度和高度)。在这个过程结束时,我们将得到一个有点“稀释”(平均)的视频,其形状与vid2_cropped - (60, 100, 50, 3) 相同。我们将这个稀释视频称为vid1_cropped_diluted。

第 3 阶段 - 将两个相同形状的视频堆叠在一起

现在vid2_cropped 和vid1_cropped_diluted 都具有相同的4D 形状(60, 100, 50, 3)。我们可以将它们堆叠在一起以获得最终的 5D 形状的 numpy 数组(2, 60, 100, 50, 3) - 我们称之为vids_combined。

我们完成了!

演示

将策略转化为代码。我是在 Python 3.6(使用 Jupyter Notebook / Jupyter Console)中完成的。


一些注意事项:

  • 我尚未验证代码(并根据需要进行修改)。同时,如果您发现任何错误,请大声疾呼-我很乐意更新。

  • 我有一种直觉,下面的第 10 行关于“稀释”(np.average 步骤)可能包含错误。即我的意思是对所有像素位置仅针对 RGB 通道值执行 3 帧平均。我需要仔细检查语法。 (同时请检查第 10 行!)

  • 这篇文章说明了概念和一些代码实现。理想情况下,我会通过更小的视频尺寸更深入地了解这一点,这样我们就可以逐个像素地获得更好的直觉/可视化每一步。 (当我有时间时,我可能会回到这个)。目前,我相信 numpy 数组形状分析足以传达这个想法。


In [1]: import numpy as np

In [2]: vid1 = np.random.random((185, 100, 50, 3))

In [3]: vid1.shape
Out[3]: (185, 100, 50, 3)

In [4]: vid2 = np.random.random((64, 100, 50, 3))

In [5]: vid2.shape
Out[5]: (64, 100, 50, 3)

In [6]: vid1_cropped = vid1[:180]

In [7]: vid1_cropped.shape
Out[7]: (180, 100, 50, 3)

In [8]: vid2_cropped = vid2[:60]

In [9]: vid2_cropped.shape
Out[9]: (60, 100, 50, 3)

In [10]: vid1_cropped_diluted = np.average(vid1_cropped.reshape(3,60,100,50,3),
       : axis=0)

In [11]: vid1_cropped_diluted.shape
Out[11]: (60, 100, 50, 3)

In [12]: vids_combined = np.stack([vid1_cropped_diluted, vid2_cropped])

In [13]: vids_combined.shape
Out[13]: (2, 60, 100, 50, 3)

【讨论】:

  • 哇 - 非常感谢您提供如此详细的回复。目前我正在用零填充数据,以使较小的视频与较大的视频长度相同,但我会四处寻找,看看是否可以使用这个答案中的想法编写解决方案。
  • 非常欢迎你 Robbie - 我有一种感觉,我很快就会遇到类似的挑战,很高兴看到你第一个到达那里!请随时告诉我们事情进展如何,祝你好运! :)
【解决方案2】:

您不能堆叠具有不同维度的数组,因为您需要为每个维度设置一个值。

因此,您的选择是:

  1. 根本不使用数组,只使用python列表
  2. 用零填充数组,直到它们的形状相同
  3. 将数组重新采样为相同的形状

Atlas7 的答案是 3 的实现,但您最好以某种方式使用 scipy.ndimage.zoom,以获得更灵活的解决方案

【讨论】:

    猜你喜欢
    • 2021-12-29
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2017-11-04
    • 2020-06-01
    • 1970-01-01
    相关资源
    最近更新 更多