Numpy argmax - random tie breaking
Solution 1
Use np.random.choice
-
np.random.choice(np.flatnonzero(b == b.max()))
Let's verify for an array with three max candidates -
In [298]: b
Out[298]: array([0, 5, 2, 5, 4, 5])
In [299]: c=[np.random.choice(np.flatnonzero(b == b.max())) for i in range(100000)]
In [300]: np.bincount(c)
Out[300]: array([ 0, 33180, 0, 33611, 0, 33209])
Solution 2
In the case of a multi-dimensional array, choice
won't work.
An alternative is
def randargmax(b,**kw):
""" a random tie-breaking argmax"""
return np.argmax(np.random.random(b.shape) * (b==b.max()), **kw)
If for some reason generating random floats is slower than some other method, random.random
can be replaced with that other method.
Solution 3
Easiest way is
np.random.choice(np.where(b == b.max())[0])
Solution 4
Since the accepted answer may not be obvious, here is how it works:
b == b.max()
will return an array of booleans, with values oftrue
where items are max and values offalse
for other itemsflatnonzero()
will do two things: ignore thefalse
values (nonzero part) then return indices oftrue
values. In other words, you get an array with indices of items matching the max value- Finally, you pick a random index from the array
Solution 5
Additional to @Manux's answer,
Changing b.max()
to np.amax(b,**kw, keepdims=True)
will let you do it along axes.
def randargmax(b,**kw):
""" a random tie-breaking argmax"""
return np.argmax(np.random.random(b.shape) * (b==b.max()), **kw)
randargmax(b,axis=None)
Related videos on Youtube
Jenna Kwon
I am fascinated by machine learning and the potential of computing in many applications. Trying to learn as much as possible on a daily basis!
Updated on June 17, 2022Comments
-
Jenna Kwon almost 2 years
In numpy.argmax function, tie breaking between multiple max elements is so that the first element is returned. Is there a functionality for randomizing tie breaking so that all maximum numbers have equal chance of being selected?
Below is an example directly from numpy.argmax documentation.
>>> b = np.arange(6) >>> b[1] = 5 >>> b array([0, 5, 2, 3, 4, 5]) >>> np.argmax(b) # Only the first occurrence is returned. 1
I am looking for ways so that 1st and 5th elements in the list are returned with equal probability.
Thank you!
-
crypdick over 4 yearsif you have floats instead of ints, you may want to replace
b == b.max()
withnp.isclose(b, b.max())
-
Jaymin over 4 yearsPlease provide some explanation along with the answer.
-
ijuneja almost 3 years
arr.max()
can be replaced bynp.max(arr)
for clarity that numpy array is involved -
Mehdi Abbassi over 2 yearsroughly three times slower!
-
Mehdi Abbassi over 2 yearsroughly 18 times slower!