У меня есть следующий цикл, в котором я вычисляю преобразование softmax
для пакетов разных размеров, как показано ниже
import numpy as np
def softmax(Z,arr):
"""
:param Z: numpy array of any shape (output from hidden layer)
:param arr: numpy array of any shape (start, end)
:return A: output of multinum_logit(Z,arr), same shape as Z
:return cache: returns Z as well, useful during back propagation
"""
A = np.zeros(Z.shape)
for i in prange(len(arr)):
shiftx = Z[:,arr[i,1]:arr[i,2]+1] - np.max(Z[:,int(arr[i,1]):int(arr[i,2])+1])
A[:,arr[i,1]:arr[i,2]+1] = np.exp(shiftx)/np.exp(shiftx).sum()
cache = Z
return A,cache
Поскольку цикл for не векторизован, это узкое место в моем коде. Какое возможное решение, чтобы сделать это быстрее. Я попытался использовать @jit
из numba
, что делает его немного быстрее, но недостаточно. Мне было интересно, есть ли другой способ сделать это быстрее или векторизовать / распараллелить это.
Пример входных данных для функции
Z = np.random.random([1,10000])
arr = np.zeros([100,3])
arr[:,0] = 1
temp = int(Z.shape[1]/arr.shape[0])
for i in range(arr.shape[0]):
arr[i,1] = i*temp
arr[i,2] = (i+1)*temp-1
arr = arr.astype(int)
EDIT:
Я забыл подчеркнуть, что количество моих классов варьируется. Например, партия 1 имеет, например, 10 классов, партия 2 может иметь 15 классов. Поэтому я передаю массив arr, который отслеживает, какие строки принадлежат batch1 и так далее. Эти партии отличаются от партий в традиционной структуре нейронной сети
В приведенном выше примере arr
отслеживает начальный индекс и конечный индекс строк. Таким образом, знаменатель в функции softmax будет суммой только тех наблюдений, чей индекс находится между начальным и конечным индексом.