简体   繁体   中英

Comparing elements at specific positions in numpy.ndarray

I don't know if the title describes my question. I have such list of floats obtained from a sigmoid activation function.

  outputs = 
  [[0.015161413699388504,
  0.6720218658447266,
  0.0024502829182893038,
  0.21356457471847534,
  0.002232735510915518,
  0.026410426944494247],
 [0.006432057358324528,
  0.0059209042228758335,
  0.9866275191307068,
  0.004609372932463884,
  0.007315939292311668,
  0.010821194387972355],
 [0.02358204871416092,
  0.5838017225265503,
  0.005475651007145643,
  0.012086033821106,
  0.540218658447266,
  0.010054176673293114]] 

To calculate my metrics, I would like to say if any neuron's output value is greater than 0.5, it is assumed that the comment belongs to the class (multi-label problem). I could easily do that using outputs = np.where(np.array(outputs) >= 0.5, 1, 0) However, I would like to add a condition to consider only the bigger value if class#5 and and any other class have values > 0.5 (as class#5 cannot occur with other classes). How to write that condition? In my example the output should be:

[[0 1 0 0 0 0]
 [0 0 1 0 0 0]
 [0 1 0 0 0 0]]

instead of:

[[0 1 0 0 0 0]
 [0 0 1 0 0 0]
 [0 1 0 0 1 0]]

Thanks,

You can write a custom function that you can then apply to each sub-array in outputs using the np.apply_along_axis() function:

def choose_class(a):
    if (len(np.argwhere(a >= 0.5)) > 1) & (a[4] >= 0.5):
        return np.where(a == a.max(), 1, 0)
    return np.where(a >= 0.5, 1, 0)

outputs = np.apply_along_axis(choose_class, 1, outputs)
outputs
# array([[0, 1, 0, 0, 0, 0],
#       [0, 0, 1, 0, 0, 0],
#       [0, 1, 0, 0, 0, 0]])

One other solution:

# Your example input array
out = np.array([[0.015, 0.672, 0.002, 0.213, 0.002, 0.026],
                [0.006, 0.005, 0.986, 0.004, 0.007, 0.010],
                [0.023, 0.583, 0.005, 0.012, 0.540, 0.010]])

# We get the desired result
val = (out>=0.5)*out//(out.max(axis=1))[:,None]

This solution do the following operation:

  1. Set to zero all the value < 0.5
  2. Set to 1 the maximum value by row (iif this value is >= 0.5)

For the simple mask, you don't need np.where

mask = outputs >= 0.5

If you want an integer instead of a boolean:

mask = (outputs >= 0.5).view(np.uint8)

To check the fifth column, you need to keep a reference to the original data around. You can get the maximum masked value in each relevant row with

rows = np.flatnonzero(mask[:, 4])
keep = (outputs[mask] * mask[rows]).argmax()

Then you can blank out the rows and set only the maximum value:

mask[rows] = 0
mask[rows, keep] = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM