0

when I try to use the following functions:

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))

I receive the following error:

C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:5: FutureWarning:arrays to stack must be passed as a "sequence" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.

Ch3steR
  • 20,090
  • 4
  • 28
  • 58
  • 1
    `map(np.ravel, X)` this gives a generator object, change that to `list(map(np.ravel, X))` or `[np.ravel(i) for i in X]` or `[*map(np.ravel, X)]`. – Ch3steR Feb 25 '21 at 10:15
  • @Ch3steR your comment would make a good answer. – FlippingBinary Jun 02 '21 at 18:34
  • @FlippingBinary I'll add it as an answer when I have some free time. If you have some time to spare please feel free to add it as an answer. :) – Ch3steR Jun 03 '21 at 09:53

1 Answers1

1

@Ch3steR solved the problem in a comment and this answer just provides some context to the already excellent answer.

The Problem

map(np.ravel, X) gives a generator object rather than a sequence object like a list or tuple. The difference is not trivial, and some functions which used to accept generators may remove that functionality in the future. That is what happened here.

The Solution(s)

We can unpack everything the generator object will produce, then put that into a list. There are several ways of doing this.

Iterable Unpacking

This is the most concise way to do it since PEP 448. It takes an iterable object such as a generator and unpacks it into a sequence. You're using the list as an argument of np.vstack so this does need the square brackets, but you could omit them in some cases.

[*map(np.ravel, X)]

Pretty simple, but there are other ways which may make the code clearer to other (or newer) programmers, such as...

List Comprehension

List comprehension has been around for a while and is a clever notation which iterates something with a for loop and puts the result in a list.

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

This iterates the generator until it has no more objects by using notation which might seem a bit clearer than the iterable unpacking notation above. The for ... in notation should be familiar to most, if not all, programmers and the square brackets clue you off that this will be in a list.

There is another way which might be clearer still...

List Constructor

This method might be the way that shows the clearest intentions. You have a generator that you want to convert to a list, and you can construct a list from it.

list(map(np.ravel, X))

This works because you are passing an iterable object as the only argument of the list constructor. The constructor will unpack that generator and return a list.

FlippingBinary
  • 1,357
  • 10
  • 21