'float' object is unsliceable

2019-08-08 16:34发布

问题:

I'm trying to generate two classes of random 2D points, one having a mean of [1,1] and the other a mean of [-1,-1]. I have written a function but I get an error that can't figure out. I googled it but didn't find anything. Here's my function :

def gen_arti_Bis(nbex=10,centerx=1,centery=1,sigma=0.1,epsilon=0.02):
    xpos=np.random.multivariate_normal([centerx,centery],np.diag([sigma,sigma]),nbex/2)
    xneg=np.random.multivariate_normal([-centerx,-centery],np.diag([sigma,sigma]),nbex/2)
    data=np.vstack((xpos,xneg))
    y=np.hstack((np.ones(nbex/2),-np.ones(nbex/2)))
    return data,y

and here's the error message when I type gen_arti():

Traceback (most recent call last):
  File "<ipython-input-64-a173cf922dac>", line 1, in <module>
    gen_arti_Bis()
  File "<ipython-input-63-da8720093c11>", line 2, in gen_arti_Bis
    xpos=np.random.multivariate_normal([centerx,centery],np.diag([sigma,sigma]),nbex/2)
  File "mtrand.pyx", line 4308, in mtrand.RandomState.multivariate_normal (numpy/random/mtrand/mtrand.c:23108)
TypeError: 'float' object is unsliceable

回答1:

In Python 3, division using the / operator always does floating point division, even if the numbers on both sides of the operator are integers. In several places you're computing nbex / 2, and passing the result as an argument where numpy expects an integer.

Specifically, np.random.multivariate's last argument is supposed to be either an int or a tuple of ints. You're passing in a float, which it won't accept, even if the float's value is actually an integer (e.g. 5.0). You're also passing a float to np.ones, but that function seems to handle it OK (it ignores any fractional part of the input number).

The most basic fix for this is to explicitly perform integer division using the // operator. Replace each place you have nbex / 2 with nbex // 2 and it should work as you intended it to.

Note that the integer division performed by // will always pick the floor value (i.e. it rounds down, towards negative infinity). If you want to round differently in some situations, you may want to do your division with / and then convert the float result to an integer with round (which will round a value that is half way between two integers to which ever one is even) or math.ceil (which will always round up).