问题描述
当我尝试使用以下功能时:
x_bounds = np.array([[ 1.,100.],[ 0.01,1.],[ 0.,1.]])
def generate_x_mesh ():
X = np.meshgrid( np.linspace(*x_bounds[0],num=20),# x_1
np.linspace(*x_bounds[1],# x_2
[0,1]) # x_3
return np.vstack(map(np.ravel,X)).T
def training_data (model):
Xsim = generate_x_mesh()
Xsim = np.vstack( (Xsim,Xsim))
我收到以下错误:
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:5:FutureWarning:堆栈的数组必须作为“序列”类型传递,例如列表或元组。从 NumPy 1.16 开始,不推荐使用对非序列迭代器(例如生成器)的支持,并且将来会引发错误。
解决方法
@Ch3steR 在评论中解决了这个问题,这个答案只是为已经很好的答案提供了一些背景。
问题
map(np.ravel,X)
给出一个生成器对象,而不是像列表或元组这样的序列对象。区别并非微不足道,一些过去接受生成器的函数将来可能会删除该功能。这就是这里发生的事情。
解决方案
我们可以解包生成器对象将产生的所有内容,然后将其放入列表中。有几种方法可以做到这一点。
可迭代解包
这是自 PEP 448 以来最简洁的方法。它接受一个可迭代对象(例如生成器)并将其解包为一个序列。您将列表用作 np.vstack
的参数,因此这确实需要方括号,但在某些情况下您可以省略它们。
[*map(np.ravel,X)]
很简单,但还有其他方法可以让其他(或新的)程序员更清楚代码,例如...
列表理解
List comprehension 已经存在一段时间了,它是一种巧妙的表示法,它使用 for 循环迭代某些内容并将结果放入列表中。
[np.ravel(i) for i in X]
这通过使用符号迭代生成器,直到它没有更多的对象,这可能看起来比上面的可迭代解包符号更清晰。 for ... in
表示法应该对大多数(如果不是全部)程序员都很熟悉,而方括号则提示您这将在列表中。
还有另一种可能更清晰的方法......
列表构造器
这种方法可能是最能表达意图的方式。您有一个想要转换为列表的生成器,您可以从中构建一个列表。
list(map(np.ravel,X))
这是有效的,因为您将一个可迭代对象作为 list constructor 的唯一参数传递。构造函数将解压该生成器并返回一个列表。