Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python NumPy中方便经济的病媒操作_Python_Python 3.x_Numpy_Numerical Methods - Fatal编程技术网

Python NumPy中方便经济的病媒操作

Python NumPy中方便经济的病媒操作,python,python-3.x,numpy,numerical-methods,Python,Python 3.x,Numpy,Numerical Methods,是否有一种方法可以在NumPy中操纵矩阵而不过度使用flant()、ravel()、创建用于创建每个矩阵的元组等 我知道这不是matlab,但写40个字符而不是4个字符似乎不是很有效 例如: A = ones(2,2) # doesn't work A = ones((2,2)) # works with tuple v = np.matlib.rand(2) dot(v, A@v) # doesn't work: shapes are not aligned vdot(v,A@v) # wor

是否有一种方法可以在NumPy中操纵矩阵而不过度使用
flant()
ravel()
、创建用于创建每个矩阵的元组等

我知道这不是matlab,但写40个字符而不是4个字符似乎不是很有效

例如:

A = ones(2,2) # doesn't work
A = ones((2,2)) # works with tuple
v = np.matlib.rand(2)
dot(v, A@v) # doesn't work: shapes are not aligned
vdot(v,A@v) # works 
现在我想更新矩阵列:

A[:,0]=A@v # nope! shapes are not aligned
# beautiful solution:
c = v.reshape(2,1)
c = A@c
c = c.flatten()
A[:,0]=c

我假设
A
的初始化是使用
ones
numpy.ones
进行的。我们可以有一艘班轮,就像这样-

A[:,[0]] = A@v.T
LHS:
A[:,[0]]
A[:,0]
相比,A[:,[0]]将维度数保持为
2D
,从而允许我们分配
A@v.T
,也是
2D

RHS:
A@v.T
处理前两行代码:

c = v.reshape(2,1)
c = A@c
我们不需要
c=c.flatte()
的第三步,因为对于
LHS
,我们使用了
2D
视图和
a[:,[0]]
,如前所述

因此,我们只剩下一个修改过的第四步,这是本文中列出的第一个代码


另一种方式

A[:,0]
将是一个
(2,)
数组,而
A@v.T
将是一个
(2,1)
数组。所以,
(A@v.T).T
将是一个
(1,2)
数组,可针对
a[:,0]
进行广播。所以,这给了我们另一种方法-

A[:,0] = (A@v.T).T

ones
的参数签名为:

ones(shape, dtype=None, order='C')
shape
是一个参数,不是一个开放的
*args

one(2,2)
2
作为
shape
传递,将
2作为
dtype`;所以它不起作用

one((2,2))
将元组
(2,2)
作为
形状传递

有时编写函数是为了接受元组或扩展元组,例如
foo((1,2))
foo(*(1,2))
foo(1,2)
。但这需要在函数内部进行额外的检查。试着编写这样一个函数,自己看看

另外,
元组
不会增加计算成本。Python一直在创建和使用元组;只需在表达式中使用逗号即可创建元组(如果它不是创建列表的一部分)

只需定义一个函数以获取开放式参数“列表”,即可创建一个元组:

def foo(*args):
    print(type(args))
    return args
In [634]: foo(1)
<class 'tuple'>
Out[634]: (1,)
In [635]: foo(1,2)
<class 'tuple'>
Out[635]: (1, 2)
In [636]: foo((1,2))
<class 'tuple'>
Out[636]: ((1, 2),)
In [637]: foo(*(1,2))
<class 'tuple'>
Out[637]: (1, 2)

让我们试试双点:

In [647]: v=matlib.rand(2)
In [648]: A=np.ones((2,2))
In [649]: A@v
...
ValueError: shapes (2,2) and (1,2) not aligned: 2 (dim 1) != 1 (dim 0)
为什么它对你有用?对于二维阵列,我们可以直接使用
dot
@
有时作为操作员工作,但增加了它自己的一些怪癖

(编辑-以后使用
A@c
其中
c
是一个经过整形的
v
,相当于
v.T
(转置)。)

想想看,既然
v
是np.matrix,那么它也可以:
v*A*v.T


我们不需要使用
matlib
来创建随机浮点的2d数组:

In [662]: v1 = np.random.rand(1,2)
In [663]: v1.shape
Out[663]: (1, 2)
In [668]: np.dot(A,v1.T)
Out[668]: 
array([[ 1.63412808],
       [ 1.63412808]])
In [669]: np.dot(v1,np.dot(A,v1.T))
Out[669]: array([[ 2.67037459]])
或者如果我们跳过2d,使
v1
1d

In [670]: v1 = np.random.rand(2)
In [671]: np.dot(A,v1)
Out[671]: array([ 0.8922862,  0.8922862])
In [672]: np.dot(v1, np.dot(A,v1))
Out[672]: 0.79617465579446423
注意,在最后一个例子中,我们得到的是标量,而不是(1,1)数组(或矩阵)

np.random.rand
是接受扩展的“元组”的函数之一


在上一个示例中,您必须使用
flat
,因为
A[:,0]
插槽是(2,)(如果
A
np.matrix
它仍然是(2,1)),而@生成一个(2,1),它必须被展平以适应(2,)

对于我的1d
v1
A[:,0]=np。点(A,v1)
无需进一步整形即可工作

通常,
matlib
np.matrix
函数会增加混淆。这是为了让任性的MATLAB程序员更容易理解


最简单的计算方法是:

In [681]: np.einsum('i,ij,j',v1,A,v1)
Out[681]: 0.77649708535481299
但使用(1,2)版本,我们可以做到:

In [683]: v2 = v1[None,:]
In [684]: v2
Out[684]: array([[ 0.20473681,  0.68754938]])
In [685]: v2 @ A @ v2.T
Out[685]: array([[ 0.77649709]])

展平和整形并不昂贵。字符计数并没有告诉我们多少关于计算速度的信息。发布的解决方案对你有用吗?@Divakar Yours是最接近于NumPy中不存在的解决方案。谢谢你详细的回答。然而,问题仍然是一样的。我不太在乎机器时间,但我在乎我的。这就是为什么我使用
matlib
:访问任何矩阵生成器都是同一个子模块,我不必记住
rand()
在另一个子模块中。按照MATLAB惯例,您也可以创建一个np.matrix,使用
v*A*v.t
,而不需要展平或重塑。你的复杂是混合了这两种习惯的结果。这是一个
matlib.ones
。关于我的第一个问题,
np.matrix
*
每次都会让我检查操作,比如,
np.matrix(…)+np.array([[1,2],[3,4]])而不是从matlib
(或任何其他)向数组广播矩阵,从而导致元素乘法。所以,给我多做点工作,给NumPy少做点。谢谢。您的回答启发了我,默认的NumPy向量是一行,这与我所知道的大多数数学约定相矛盾。@HomoComputers是的,从MATLAB的角度考虑,1D NumPy数组最好被认为是行向量。关于“另一种方式”:我有
A@v.T数组([2,4,2.])
,它不是(2,1),明显地因为向量是一维张量,也就是一个变量的函数,所以转置向量是没有意义的。然而,NumPy将遵从并返回完全相同的对象。(来自使用Python 3的科学计算)
In [675]: A@v.T
Out[675]: 
matrix([[ 0.63976046],
        [ 0.63976046]])
In [676]: A[:,0].shape
Out[676]: (2,)
In [681]: np.einsum('i,ij,j',v1,A,v1)
Out[681]: 0.77649708535481299
In [683]: v2 = v1[None,:]
In [684]: v2
Out[684]: array([[ 0.20473681,  0.68754938]])
In [685]: v2 @ A @ v2.T
Out[685]: array([[ 0.77649709]])