Python 是否可以使用numpy压缩除N个维度以外的所有维度?

Python 是否可以使用numpy压缩除N个维度以外的所有维度?,python,numpy,Python,Numpy,我想知道是否有一种方法可以将大小为1的所有维度压缩到一个数组中,而不压缩N个维度(即使这些维度的大小为1) 为什么??假设我有一个函数接收一个数组,它返回数组的矩阵积及其转置,但数组的形状未知(最大2个DIM,大小大于1,但可能有更多DIM,大小为1) 可能的矩阵形状示例: A.shape -> (M,N) B.shape -> (M,N,1[...,1]) C.shape -> (M,1[...,1]) 为了执行矩阵积,我希望始终保持A(ndim=2)的形状 我可以使用np

我想知道是否有一种方法可以将大小为1的所有维度压缩到一个数组中,而不压缩N个维度(即使这些维度的大小为1)

为什么??假设我有一个函数接收一个数组,它返回数组的矩阵积及其转置,但数组的形状未知(最大2个DIM,大小大于1,但可能有更多DIM,大小为1)

可能的矩阵形状示例:

A.shape -> (M,N)
B.shape -> (M,N,1[...,1])
C.shape -> (M,1[...,1])
为了执行矩阵积,我希望始终保持A(ndim=2)的形状

我可以使用
np.squence(X)
,就是这样,但在C的情况下,这将导致以下问题:

import numpy as np

def my_function(arr):
    arr = np.squeeze(arr)
    return np.dot(arr, arr.transpose())

x = np.arange(1, 6)  # shape (5,)
x = x.reshape((x.size, 1, 1))  # shape (5, 1, 1)
y = my_function(x)
print(y)
# Actual y.shape -> () [is a number]
# Expected y.shape -> (5, 5) [matrix]

我希望
np.squence()
函数有一个参数
axis\u保持
。你知道有没有一种方法可以轻松做到这一点吗?我知道一些方法,但我需要最有效的方法,因为我必须多次执行这些操作。

我想的解决方案之一是:

def my_squeeze(arr, axis=None, keep=0):
    arr = np.squeeze(arr, axis=axis)
    while arr.ndim < keep:
        arr = np.expand_dims(arr, axis=-1)
    return arr

如果有人知道不创建
my_squence()
函数的更好方法,我很乐意听到。

使用
轴挤压以保持
参数

这里有一个用于一般n-dim阵列的参数,该参数具有所请求的保持这些轴的
axes\u to\u keep
param-

def squeeze_generic(a, axes_to_keep):
    out_s = [s for i,s in enumerate(a.shape) if i in axes_to_keep or s!=1]
    return a.reshape(out_s)
样本运行-

In [105]: a = np.random.rand(3,4,5,1,1,6,1)

In [106]: squeeze_generic(a, axes_to_keep=(3,4)).shape
Out[106]: (3, 4, 5, 1, 1, 6)

In [107]: squeeze_generic(a, axes_to_keep=(3,4,6)).shape
Out[107]: (3, 4, 5, 1, 1, 6, 1)

# For cases when axes_to_keep lists axes that aren't singleton
In [108]: squeeze_generic(a, axes_to_keep=(0,1)).shape
Out[108]: (3, 4, 5, 6)
解决您的问题以保持前两个轴

因此,要解决保留前两个轴的具体情况,它将是——

squeeze_generic(a, axes_to_keep=range(2))
让我们看看这方面的示例案例-

In [55]: a = np.random.rand(3,5)

In [56]: squeeze_generic(a, axes_to_keep=range(2)).shape
Out[56]: (3, 5)

In [57]: a = np.random.rand(3,5,1)

In [58]: squeeze_generic(a, axes_to_keep=range(2)).shape
Out[58]: (3, 5)

In [59]: a = np.random.rand(3,1)

In [60]: squeeze_generic(a, axes_to_keep=range(2)).shape
Out[60]: (3, 1)
如果保证第二个轴之后的所有轴都是单轴(长度轴=1)如果有,那么简单的重塑也可以完成这项工作-

a.reshape(a.shape[0],-1)

你试过
np.挤压(arr,-1)
?@Chris是的,当输入形状为
(M,N)
时会给我一个错误,因为被挤压的轴的长度不是1。另外,如果我有输入形状
(M,N,1,1,1)
,它只会挤压最后一个轴,我需要挤压除前2个以外的每个轴(在这种情况下)。效率不是什么大问题。像这样的形状更改只会生成一个视图,与复制和计算相比几乎没有成本。请查看
expand\u dims
的代码。请注意它是如何构造元组并在
重塑
中使用它的。这就是@Divakar正在做的事情。@hpaulj哦,我没想到
expand\u dims
会使用
restrape
。我认为它会使用更“有效”的东西。我想我的解决方案不太好,因为是while循环。在大多数情况下,
重塑
不会产生效率低下的效果,它会生成具有新形状和步幅的视图。无副本或元素计算。谢谢。我认为这是最好的解决办法。
a.reshape(a.shape[0],-1)