Как я могу преобразовать выходные данные функции активации сигмоида в 0 и 1? - PullRequest
0 голосов
/ 21 апреля 2019

У меня есть следующий массив:

array([8.1837177e-05, 1.0788739e-03, 4.4837892e-03, 3.4919381e-04, 7.6085329e-05, 7.6562166e-05, 5.3864717e-04, 5.4001808e-04,  3.3849746e-02, 2.9903650e-04], dtype = float32)

Я хочу преобразовать его в это:

array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0], dtype = float32)

Мне нужно найти максимальное значение для строки, заменить его на 1затем замените остальные 9 значений для этой строки на 0.

Мне нужно, чтобы это было сделано для двумерного массива (серии массивов, которые выглядят как в примере)

Ответы [ 4 ]

2 голосов
/ 21 апреля 2019

Используйте np.where в сочетании с max:

a = np.array([8.1837177e-05, 1.0788739e-03, 4.4837892e-03, 3.4919381e-04, 7.6085329e-05, 7.6562166e-05, 5.3864717e-04, 5.4001808e-04,  3.3849746e-02, 2.9903650e-04])

np.where(a == a.max(), 1, 0)

Выход:

array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0])

В 2D-случае мы берем максимум каждой строки:

np.where(a == a.max(axis=1)[:, np.newaxis], 1, 0)

Тем не менее, я чувствую, что keras должен иметь что-то встроенное, чтобы сделать это для вас ...

1 голос
/ 21 апреля 2019

Этот метод занимает две строки, но избегает сравнения каждого элемента массива с максимумом и хорошо работает в 2D. Я не знаю, что это действительно будет быстрее (не асимптотически, конечно), но я думаю, что две строки лучше, чем делать цикл for для 2D в python, и удобочитаемость может быть лучше, чем использование np.where.

import numpy as np

# here's your example input
# note - the input must be 2D even if there's just one row
# it's easy to adapt this to the 1D case, but you'll be working with 2D arrays for this anyway
class_probs = np.array([[
    8.1837177e-05, 1.0788739e-03, 4.4837892e-03, 3.4919381e-04, 7.6085329e-05,
    7.6562166e-05, 5.3864717e-04, 5.4001808e-04, 3.3849746e-02, 2.9903650e-04,
]])
pred_classes = np.zeros_like(class_probs)
pred_classes[range(len(class_probs)), class_probs.argmax(-1)] = 1
print(pred_classes) # [[0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]]

# and here's showing the same code works for multiple rows
class_probs = np.random.rand(100, 10)
pred_classes = np.zeros_like(class_probs)
pred_classes[range(len(class_probs)), class_probs.argmax(-1)] = 1
pred_classes

(это не ваш реальный вопрос, но вы хотели использовать функцию активации сигмоида? И не softmax? Выходные данные, которые вы получаете здесь, не являются единым распределением по 10 возможным классам (вы можете видеть, что это даже не нормализовано. Скорее, у вас есть 10 распределений, по одному для каждого класса (таким образом, вероятность того, что вход был классом 0, равна 8.1837177e-05, а вероятность того, что он не является классом 0, равна 1 - 8.1837177e-05). Это имеет смысл, когда выполнять классификацию по нескольким меткам (где может применяться более одной метки), но тогда вам не захочется находить класс с наибольшей вероятностью, вы будете прогнозировать все классы с вероятностью выше порогового значения (например, 0,5).

1 голос
/ 21 апреля 2019

Вы можете использовать понимание списка следующим образом:

x = [5,6,7,8,9]
y = [1 if num == max(x) else 0 for num in x]
0 голосов
/ 21 апреля 2019
x = array([1, 2, 3, 4])


x = np.where(x == max(x), 1, 0) # will replace max with 1 and the others with 0

это создаст:

array([0, 0, 0, 1])

для 2D-массива вы можете сделать следующее:

x = array([[0, 3, 4, 5],
           [1, 2, 3, 1],
           [6, 9, 1, 2]])

x = np.array([np.where(l == max(l), 1, 0) for l in x])

это создаст:

array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 0, 0]])`

...