0

当我尝试使用以下功能时:

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], num=20),   # 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:arrays to stack 必须作为“序列”类型传递,例如列表或元组。自 NumPy 1.16 起,对非序列迭代器(如生成器)的支持已被弃用,并且将来会引发错误。

4

1 回答 1

1

@Ch3steR 在评论中解决了这个问题,这个答案只是为已经很好的答案提供了一些背景。

问题

map(np.ravel, X)给出一个生成器对象,而不是像列表或元组这样的序列对象. 区别并非微不足道,一些用于接受生成器的函数将来可能会删除该功能。这就是这里发生的事情。

解决方案

我们可以解压缩生成器对象将生成的所有内容,然后将其放入列表中。有几种方法可以做到这一点。

可迭代拆包

这是自PEP 448以来最简洁的方法。它需要一个可迭代的对象(例如生成器)并将其解压缩成一个序列。您将列表用作参数,np.vstack因此这确实需要方括号,但在某些情况下您可以省略它们。

[*map(np.ravel, X)]

很简单,但是还有其他方法可以使其他(或更新的)程序员更清楚代码,例如...

列表理解

列表理解已经存在了一段时间,它是一种巧妙的符号,它使用 for 循环迭代某些内容并将结果放入列表中。

[np.ravel(i) for i in X]

这通过使用似乎比上面的可迭代拆包表示法更清晰的表示法迭代生成器,直到它没有更多对象。for ... in大多数(如果不是全部)程序员应该熟悉该符号,方括号会提示您这将在列表中。

还有另一种方法可能更清楚......

列表构造函数

这种方法可能是显示最清晰意图的方式。您有一个想要转换为列表的生成器,您可以从中构造一个列表。

list(map(np.ravel, X))

这是有效的,因为您将可迭代对象作为列表构造函数的唯一参数传递。构造函数将解压该生成器并返回一个列表。

于 2021-06-03T12:35:39.343 回答