Boole maskesi ile verimli numpy değer ataması

0

Soru

Verimli boole maskesi işlemi gerektiren bir boole maskesi değeri atama sorunum var.

Bu çok boyutlu bir maske ve kullanıyorum einsum sonuca ulaşmak için, ancak işlem çok verimli değil ve bununla ilgili biraz yardım alabilir miyim diye merak ediyorum İşte şu anki çözümüm: (her ikisi de mask, truth_value, false_value dtype ve shape ile kukla veriler sorunumla eşleşiyor.

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)

Almak için daha hızlı bir yol var mı objective verilmiş mask, truth_value, false_value ?

Beklerken daha hızlı bir yol buldum.

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

Ama daha hızlı bir alternatif var mı ?

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

En iyi cevabı

0

Bunu daha verimli yapmak için Numba jit'i kullanabilirsiniz.

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)

Hesaplama objective makinemde 4.8 kat daha hızlı.

Bu yeterince hızlı değilse, parametreyi kullanarak kodu paralelleştirmeyi deneyebilirsiniz parallel=True ve kullanarak nb.prange yerine range ı tabanlı döngüde. Bu, yeni iş parçacığı oluşturma yükü nedeniyle daha hızlı olmayabilir. Makinemde (6 çekirdekli) paralel sürüm 7.4 kat daha hızlıdır (iş parçacıklarının oluşturulması yürütme süresine kıyasla oldukça pahalıdır).

Başka bir olası en iyi duruma getirme, sonucu doğrudan vaktinden önce ayrılmış bir arabelleğe yazmaktır (bu, yalnızca bu işlevi aynı dizi boyutuyla birden çok kez çağırırsanız daha iyidir).

İşte makinemdeki genel zamanlamalar:

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

teşekkürler! bu gerçekten benimkinden daha hızlı einsum çözüm! benimkinden biraz daha hızlı np.where +np.broadcast_to tabanlı çözüm.
yupbank

Diğer dillerde

Bu sayfa diğer dillerde

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