在numpy中,有些操作以形状(R, 1)返回,但有些返回(R,)。这将使矩阵乘法更加繁琐,因为需要显式重塑。例如,给定一个矩阵M,如果我们想要numpy。点(M [: 0], numpy。ones((1, R))),其中R是行数(当然,列方面也存在同样的问题)。我们将得到矩阵不是对齐错误,因为M[:,0]是在形状(R,),而是numpy。ones((1, R))的形状是(1,R)。

所以我的问题是:

形状(R, 1)和(R,)的区别是什么?我知道字面上它是一个数字的列表和列表的列表所有的列表都只包含一个数字。只是想知道为什么不设计numpy,使它更喜欢形状(R, 1)而不是(R,),以便于矩阵乘法。 对于上面的例子有没有更好的方法?不需要像这样显式地重塑:numpy.dot(M[:,0]。重塑(R, 1), numpy。((R)))


当前回答

(R,)和(1,R)之间的差就是你需要使用的索引的数量。ones((1,R))是一个恰好只有一行的二维数组。R是一个向量。一般来说,如果变量有多行/多列是没有意义的,你应该使用一个向量,而不是一个单维矩阵。

对于您的特定情况,有几个选项:

1)将第二个参数设为向量。以下工作很好:

    np.dot(M[:,0], np.ones(R))

2)如果你想要matlab一样的矩阵运算,使用类矩阵而不是ndarray。所有矩阵都被强制转换为2-D数组,运算符*执行矩阵乘法而不是元素乘法(因此不需要dot)。根据我的经验,这比它值得的麻烦多了,但如果你习惯了matlab,它可能会很好。

其他回答

(R,)和(1,R)之间的差就是你需要使用的索引的数量。ones((1,R))是一个恰好只有一行的二维数组。R是一个向量。一般来说,如果变量有多行/多列是没有意义的,你应该使用一个向量,而不是一个单维矩阵。

对于您的特定情况,有几个选项:

1)将第二个参数设为向量。以下工作很好:

    np.dot(M[:,0], np.ones(R))

2)如果你想要matlab一样的矩阵运算,使用类矩阵而不是ndarray。所有矩阵都被强制转换为2-D数组,运算符*执行矩阵乘法而不是元素乘法(因此不需要dot)。根据我的经验,这比它值得的麻烦多了,但如果你习惯了matlab,它可能会很好。

1)不喜欢(R, 1)形状而不喜欢(R,)形状的原因是,它不必要地使事情复杂化。此外,为什么长度为R的向量默认使用shape (R, 1)而不是(1,R)会更好呢?当您需要额外的维度时,最好保持简单和明确。

2)对于你的例子,你正在计算一个外部产品,所以你可以通过使用np.outer来实现这一点,而不需要一个重塑调用:

np.outer(M[:,0], numpy.ones((1, R)))

这里已经有很多好的答案了。但对我来说,很难找到一些例子,形状或数组可以破坏所有的程序。

下面是一个例子:

import numpy as np
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])


from sklearn.linear_model import LinearRegression
regr = LinearRegression()
regr.fit(a,b)

这将失败并产生错误:

ValueError:期望的2D数组,得到的是1D数组

但如果我们对a加上重塑:

a = np.array([1,2,3,4]).reshape(-1,1)

这是正确的!

形状(n,)的数据结构称为秩1数组。它的行为不像行向量或列向量那样一致,这使得它的一些操作和效果不直观。如果你对这个(n,)数据结构求转置,它看起来是一样的点积会给你一个数字而不是一个矩阵。 形状为(n,1)或(1,n)的行向量或列向量更直观和一致。

对于其基数组类,2d数组并不比1d或3d数组更特殊。有些操作保留维度,有些操作减少维度,有些操作合并甚至扩展维度。

M=np.arange(9).reshape(3,3)
M[:,0].shape # (3,) selects one column, returns a 1d array
M[0,:].shape # same, one row, 1d array
M[:,[0]].shape # (3,1), index with a list (or array), returns 2d
M[:,[0,1]].shape # (3,2)

In [20]: np.dot(M[:,0].reshape(3,1),np.ones((1,3)))

Out[20]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

In [21]: np.dot(M[:,[0]],np.ones((1,3)))
Out[21]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

给出相同数组的其他表达式

np.dot(M[:,0][:,np.newaxis],np.ones((1,3)))
np.dot(np.atleast_2d(M[:,0]).T,np.ones((1,3)))
np.einsum('i,j',M[:,0],np.ones((3)))
M1=M[:,0]; R=np.ones((3)); np.dot(M1[:,None], R[None,:])

MATLAB从2D数组开始。新版本允许更多维度,但保留了2的下界。但是你还是要注意行矩阵和列矩阵之间的区别,列矩阵的形状是(1,3)v (3,1)你多久写一次[1,2,3]?我要写行向量和列向量,但是有了二维的约束,在MATLAB中没有任何向量至少在数学意义上的向量是一维的。

你看过np吗?至少2d(也_1d和_3d版本)?

在新的Python/numpy中,有一个matmul操作符

In [358]: M[:,0,np.newaxis]@np.ones((1,3))
Out[358]: 
array([[0., 0., 0.],
       [3., 3., 3.],
       [6., 6., 6.]])

在numpy中,元素乘法在某种意义上比矩阵乘法更基本。对于大小为1的积和,不需要使用dot/matmul:

In [360]: M[:,0,np.newaxis]*np.ones((1,3))
Out[360]: 
array([[0., 0., 0.],
       [3., 3., 3.],
       [6., 6., 6.]])

它使用广播,这是numpy一直拥有的强大功能。MATLAB最近才添加了它。