4

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,

3 Answers 3

1

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]])
Sign up to request clarification or add additional context in comments.

1 Comment

This is not very efficient
1

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

Comments

1

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)

5 Comments

You won't get a comparison error from multiplying by exactly one
If you use // instead of /, you don't need to compare: integer division will set everything to zero except the max
Assuming that each row has a value >= 0.5, negative values don't matter
My Thanks'o'meter is empty, but _ you again.
I really like your answer, so I keep finding improvements

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.