Efektywne przypisanie wartości numpy za pomocą logicznej maski

0

Pytanie

Mam problem z nadaniem wartości logicznej maski, wymaga skutecznej operacji logicznej maską.

To wielowymiarowy maska, i używam einsum dla osiągnięcia rezultatu, ale operacja nie jest bardzo wydajny, i zastanawiam się, czy mogę uzyskać jakąś pomoc w tym Oto moja aktualna decyzja: (oba mask, truth_value, false_value są fałszywymi danymi z typem dtype i formą, odpowiednimi moim problemie.

mask = np.random.randn(1000, 50)> 0.5
truth_value = np.random.randn(50, 10)
false_value = np.random.randn(10)
objective = np.einsum('ij,jk->ijk', mask, truth_value) + np.einsum('ij,k->ijk', ~mask, false_value)

Czy jest jakiś szybszy sposób, aby dostać się objective prezent mask, truth_value, false_value ?

A ja czekałem, wymyślił szybszy sposób

objective = np.where(mask[...,np.newaxis], np.broadcast_to(truth_value, (1000, 50, 10)), np.broadcast_to(false_value,  (1000, 50, 10)))

Ale czy jest szybsza alternatywa ?

mask numpy python
2021-11-21 23:00:26
1

Najlepsza odpowiedź

0

Można użyć JIT Numba, aby robić to bardziej efektywnie.

import numpy as np
import numba as nb

@nb.njit('float64[:,:,::1](bool_[:,::1], float64[:,::1], float64[::1])')
def blend(mask, truth_value, false_value):
    n, m = mask.shape
    l = false_value.shape[0]
    assert truth_value.shape == (m, l)
    result = np.empty((n, m, l), dtype=np.float64)
    for i in range(n):
        for j in range(m):
            if mask[i, j]:
                result[i, j, :] = truth_value[j, :]
            else:
                result[i, j, :] = false_value[:]
    return result

mask = np.random.randn(1000, 50) > 0.5
truth_value = np.random.randn(50, 10)
false_value = np.random.randn(10)
objective = blend(mask, truth_value, false_value)

Obliczenie objective na moim aucie to w 4,8 razy szybciej.

Jeśli to za mało, można spróbować równoległą kod za pomocą opcji parallel=True i za pomocą nb.prange zamiast range w cyklu na podstawie i. To może być szybciej z powodu nakładów na tworzenie nowych wątków. W moim samochodzie (z 6 rdzeni) równoległa wersja w 7,4 razy szybciej (tworzenie wątków jest dość drogie w porównaniu z czasem wykonania).

Inna możliwa optymalizacja polega na bezpośrednim zapisem wyniku do bufora, dedykowany z góry (to lepiej, tylko jeśli wywoła tę funkcję kilka razy z tym samym rozmiarze tablicy).

Oto ogólne czasy na moim aucie:

np.einsum:         4.32 ms
np.where:          1.72 ms
numba sequential:  0.89 ms
numba parallel:    0.58 ms
2021-11-21 23:52:43

Dziękuję! to naprawdę szybciej, niż mój einsum decyzja! trochę szybciej niż mój np.where +np.broadcast_to rozwiązanie oparte.
yupbank

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................