【问题标题】:Making matrix within a function with an array as parameter in Python在Python中以数组作为参数的函数内制作矩阵
【发布时间】:2020-08-04 16:19:00
【问题描述】:

我正在尝试在 Python 中实现一个包含两个参数的函数,我想稍后再进行隐式绘图。

此函数通过使用其两个参数返回在其中定义的矩阵的行列式。

为了制作绘图,我定义了两个 numpy 数组,每个参数一个,这将是我稍后绘图中的两个轴。

当我将这两个数组作为参数传递给我的函数时,我的问题出现了:它告诉我"ValueError: setting an array element with a sequence". 我认为 numpy 是为了处理这类事情而构建的,这就是为什么我很困惑并且无法解决这是我自己的。

您可以在下面找到我使用的代码。任何帮助将不胜感激。

import numpy as np

def F(a,b):
    M = np.matrix([[a,2.0],[0.0,b]],dtype=np.float)
    return np.linalg.det(M)
    
X = np.linspace(0.0, 5.0, num=200)
Y = np.linspace(0.0, 5.0, num=200)
    
F(X,Y)

【问题讨论】:

  • 哪一行导致错误?您是否在谷歌上搜索了错误以查看已经有哪些解决方案?
  • 你希望M = np.matrix([[a,2.0],[0.0,b]],dtype=np.float) 做什么?
  • 如果你运行相同的代码但使用X = 2;Y = 3,你会看到F(X,Y)=6.0 ...小心你的类型。 X 和 Y 都不是 np.float 类型
  • 当您尝试将多个事物放入 numpy 数组的单个元素槽时会发生该错误。在您的情况下,您将所有 linspace 元素同时放入 ab ,这显然是行不通的。在F 上使用@np.vectorize 装饰器应该可以工作,但可能不是最快的方式。也不要使用np.matrix,而是使用常规的np.array
  • 鉴于XY,您希望M 是什么?这是一个基本的数组构造问题。

标签: python arrays function numpy matrix


【解决方案1】:

问题在于您如何尝试创建矩阵(这里我将使用 np.array 而不是旧的(并且几乎已弃用)np.matrix

使用标量值:

In [263]: a,b = 3,6                                                                                  
In [264]: np.array([[a,2.0],[0.0,b]], np.float)                                                      
Out[264]: 
array([[3., 2.],
       [0., 6.]])

但对于列表或数组:

In [265]: a,b = [1,2],[3,4]                                                                          
In [266]: np.array([[a,2.0],[0.0,b]], np.float)                                                      
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: float() argument must be a string or a number, not 'list'

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-266-49cf30d8a5ca> in <module>
----> 1 np.array([[a,2.0],[0.0,b]], np.float)

ValueError: setting an array element with a sequence.

如果我允许它创建一个对象,而不是浮点数、数组,我会得到:

In [267]: np.array([[a,2.0],[0.0,b]], object)                                                        
Out[267]: 
array([[list([1, 2]), 2.0],
       [0.0, list([3, 4])]], dtype=object)

看到它试图将该列表(或数组)放入二维数组的槽中。如果我们允许对象,那没关系,就像 Python 列表那样,但如果我们期望一个浮点数组,那就不行了。

您究竟想通过将数组放入矩阵中来完成什么?解释逻辑。


简单迭代:

In [273]: def F(a,b): 
     ...:     M = np.array([[a,2.0],[0.0,b]],dtype=np.float) 
     ...:     return np.linalg.det(M) 
     ...:      
     ...: X = np.linspace(0.0, 5.0, num=6) 
     ...: Y = np.linspace(0.0, 5.0, num=6)                                                           
In [274]:                                                                                            
In [274]: np.array([F(a,b) for a,b in zip(X,Y)])                                                     
Out[274]: array([ 0.,  1.,  4.,  9., 16., 25.])

3d 数组

查看det 的文档。

如果您想要det 用于M (2,2) 数组,则需要创建一个 (M,2,2) 形状的数组。

det 中的例子是:

>>> a = 
>>> a.shape
(3, 2, 2)
>>> np.linalg.det(a)
array([-2., -3., -8.])

In [269]: np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ])                         
Out[269]: 
array([[[1, 2],
        [3, 4]],

       [[1, 2],
        [2, 1]],

       [[1, 3],
        [3, 1]]])

从您的XY 创建这样的M

In [276]: M = np.zeros((X.shape[0],2,2))                                                             
In [277]: M[:,0,0]=X                                                                                 
In [278]: M[:,0,1]=2                                                                                 
In [279]: M[:,1,1]=Y                                                                                 
In [280]: M                                                                                          
Out[280]: 
array([[[0., 2.],
        [0., 0.]],

       [[1., 2.],
        [0., 1.]],

       [[2., 2.],
        [0., 2.]],

       [[3., 2.],
        [0., 3.]],

       [[4., 2.],
        [0., 4.]],

       [[5., 2.],
        [0., 5.]]])
In [281]: np.linalg.det(M)                                                                           
Out[281]: array([ 0.,  1.,  4.,  9., 16., 25.])

2d X 与 Y

到目前为止,我展示了一个一维结果,并行迭代 XY。如果你想要一个笛卡尔积,XY 作为两个轴,我们必须做一些不同的事情。

In [283]: np.array([[F(a,b) for b in Y] for a in X])                                                 
Out[283]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])

通过广播矢量化

在构造 XY 结果时,np.vectorize 很有用:

In [284]: f = np.vectorize(F, otypes=[float])                                                        
In [285]: f(X,Y)                                                                                     
Out[285]: array([ 0.,  1.,  4.,  9., 16., 25.])
In [286]: f(X[:,None],Y)                                                                             
Out[286]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])

同样的功能可以两种方式使用。

对于完全矢量化的结果,我们需要制作一个 4d M:

In [287]: M = np.zeros((X.shape[0],Y.shape[0],2,2))                                                  
In [288]: M[:,:,0,0]=X[:,None]                                                                       
In [289]: M[:,:,0,1]=2                                                                               
In [290]: M[:,:,1,1]=Y[None,:]                                                                       
In [291]: np.linalg.det(M)                                                                           
Out[291]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])

【讨论】:

  • 感谢您的回答。我正在尝试隐式地绘制这个函数:F(a,b) = 0。为了制作这个图,我需要一个用于 a 的数组和一个用于 b 的数组。
  • 他想替换 ab 中的每个元素并返回一个形状为 (200,) 的数组。解决方案(可能不是最快的)只是添加 np.vectorize 装饰器。问题不清楚。
  • @PéterLeéh,为什么不建议对XY 的元素进行迭代?这更直接、更快捷。
  • @hpaulj 嗯,在 cmets 中字符更少且易于理解。数以百万计的问题都有详细的答案。
  • @PéterLeéh,大多数涉及np.vectorize 的 SO 都处理了它的陷阱。表面上它很容易使用,但经常被误用。我不鼓励使用它,除非您确实需要相互广播多个数组,并且该函数不能以适当的方式“矢量化”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
相关资源
最近更新 更多