为了账号安全,请及时绑定邮箱和手机立即绑定

numpy.Array形状(R,1)和(R,)之间的差异

numpy.Array形状(R,1)和(R,)之间的差异

慕田峪7331174 2019-07-03 11:06:05
numpy.Array形状(R,1)和(R,)之间的差异在……里面numpy,一些操作将恢复形状。(R, 1)但有些人回来了(R,)..这将使矩阵乘法由于显式而变得更加繁琐。reshape是必需的。例如,给定一个矩阵M,如果我们想numpy.dot(M[:,0], numpy.ones((1, R)))哪里R行数(当然,同样的问题也发生在列上)。我们会得到matrices are not aligned错误自M[:,0]形似(R,)但numpy.ones((1, R))形似(1, R).所以我的问题是:形状之间有什么区别(R, 1)和(R,)..我知道字面上是数字列表和列表,其中所有列表都只包含一个数字。只是想知道为什么不设计numpy所以它更喜欢形状(R, 1)而不是(R,)为了更容易的矩阵乘法。是否有更好的方法来做上面的例子?而不像这样显式地重塑:numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))
查看完整描述

3 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

1.NumPy中形状的含义

你写,“我知道字面上是数字列表和列表,其中所有的列表只包含一个数字”,但这是一个有点无助的方式来思考它。

考虑NumPy数组的最佳方法是,它们由两个部分组成,数据缓冲器它只是一个原始元素块,而视点描述如何解释数据缓冲区。

例如,如果我们创建一个由12个整数组成的数组:

>>> a = numpy.arange(12)>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

然后a由一个数据缓冲区组成,如下所示:

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘


以及描述如何解释数据的视图:

>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False>>> a.dtype
dtype('int64')>>> a.itemsize8>>> a.strides(8,)>>> a.shape(12,)

在这里形形 (12,)表示数组由一个从0到11的索引。i,数组a看起来是这样的:

i= 0    1    2    3    4    5    6    7    8    9   10   11

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘


如果我们重塑数组,这不会改变数据缓冲区。相反,它创建了一个新视图,该视图描述了解释数据的不同方法。因此,在此之后:

>>> b = a.reshape((3, 4))

阵列b具有与a,但现在它的索引是指数分别从0到2和0到3。如果我们给这两个指数贴上标签ij,数组b看起来是这样的:

i= 0    0    0    0    1    1    1    1    2    2    2    2

j= 0    1    2    3    0    1    2    3    0    1    2    3

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘


这意味着:

>>> b[2,1]9

您可以看到,第二个索引变化很快,而第一个索引变化缓慢。如果您希望采用相反的方法,则可以指定order参数:

>>> c = a.reshape((3, 4), order='F')

它会产生一个像这样索引的数组:


i= 0    1    2    0    1    2    0    1    2    0    1    2

j= 0    0    0    1    1    1    2    2    2    3    3    3

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

这意味着:

>>> c[2,1]5

现在应该清楚,数组具有一个或多个尺寸为1的形状意味着什么。

>>> d = a.reshape((12, 1))

阵列d由两个索引,第一个索引从0到11个,第二个索引总是0:

i= 0    1    2    3    4    5    6    7    8    9   10   11

j= 0    0    0    0    0    0    0    0    0    0    0    0

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘


因此:

>>> d[10,0]10

长度1的维度是“免费的”(从某种意义上说),所以没有什么能阻止你进城:

>>> e = a.reshape((1, 2, 1, 6, 1))

给出一个像这样索引的数组:

i= 0    0    0    0    0    0    0    0    0    0    0    0

j= 0    0    0    0    0    0    1    1    1    1    1    1

k= 0    0    0    0    0    0    0    0    0    0    0    0

l= 0    1    2    3    4    5    0    1    2    3    4    5

m= 0    0    0    0    0    0    0    0    0    0    0    0

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐

│  0 │  1 │  2 │  3 │  4 │  5 │  6 │  7 │  8 │  9 │ 10 │ 11 │

└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘


因此:

>>> e[0,1,0,0,0]6

NumPy内部文档有关如何实现数组的更多详细信息。

2.怎么办?

numpy.reshape只要创建一个新视图,您就不应该害怕在必要时使用它。当您想以不同的方式索引数组时,它是正确的工具。

然而,在长时间的计算中,通常可以首先安排构造具有“正确”形状的数组,从而最小化整形和转置的数量。但是,没有看到导致需要重塑的实际背景,很难说应该改变什么。

你问题中的例子是:

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

但这是不现实的。首先,这个短语:

M[:,0].sum()

计算结果更简单。第二,列0真的有什么特别之处吗?也许你真正需要的是:

M.sum(axis=0)


查看完整回答
反对 回复 2019-07-03
?
喵喔喔

TA贡献1735条经验 获得超5个赞

.之间的区别(R,)(1,R)字面上是你需要使用的索引的数量。ones((1,R))是碰巧只有一行的二维数组。ones(R)是一个向量。通常,如果变量有多个行/列没有意义,则应该使用向量,而不是单例维度的矩阵。

对于您的具体情况,有几个选项:

1)只需将第二个参数设为向量即可。下列各项运作良好:

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

2)如果您想要类似于matlab的矩阵运算,请使用以下类matrix而不是ndarray..所有的矩阵都被迫形成二维数组和运算符。*做矩阵乘法而不是按元素计算(所以你不需要点)。在我的经验,这是更多的麻烦,这是值得的,但它可能是不错的,如果你习惯了MATLAB。


查看完整回答
反对 回复 2019-07-03
?
富国沪深

TA贡献1790条经验 获得超9个赞

这个形状是一个元组。如果只有一维,则形状将是一个数字,在逗号后为空白。对于2+维,在所有逗号之后都会有一个数字。

# 1 dimension with 2 elements, shape = (2,). # Note there's nothing after the comma.z=np.array([  # start dimension
    10,       # not a dimension
    20        # not a dimension])            # end dimensionprint(z.shape)

(2,)

# 2 dimensions, each with 1 element, shape = (2,1)w=np.array([  # start outer dimension 
    [10],     # element is in an inner dimension
    [20]      # element is in an inner dimension])            # end outer dimensionprint(w.shape)

(2,1)


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 1434 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信