क्या किसी 2D विरल मैट्रिक्स को 3D numpy array से गुणा करने का कोई तरीका है? उदाहरण के लिए मेरे पास यह कार्य है

def myFun(x, p):
    r = 2
    out = x * np.log(p) + r * np.log(1-p)
    return out

जहां x आयाम की एक सरणी है 3500, 90 और p आयाम के साथ एक और सरणी 3500, 90, 70। इस समय दोनों x और p घने सरणी हैं और जब मैं फ़ंक्शन को कॉल करता हूं तो मैं केवल प्रसारण कर रहा हूं:

out = myFun(x[..., None], p)

हालाँकि, सरणी x काफी विरल है, इसके केवल 7% तत्व गैर-शून्य हैं। दूसरी ओर, p में कोई शून्य नहीं है, केवल शून्य और एक के बीच तैरता है। मैं उम्मीद कर रहा हूं कि एक विरल मैट्रिक्स के साथ (शायद scipy.sparse से) मुझे गति में सुधार दिखाई देगा। हालांकि, मुझे नहीं पता कि यह ऑपरेशन कैसे करना है या यदि यह अधिक कुशल है तो कृपया।

मैं अजगर 3 का उपयोग कर रहा हूँ।

बहुत धन्यवाद

1
Aenaon 7 पद 2018, 16:59

2 जवाब

सबसे बढ़िया उत्तर

आप where कीवर्ड का उपयोग करके x की विरलता का फायदा उठा सकते हैं।

def sprse(x, p):
    r = 2
    out = x * np.log(p, where=x.astype(bool)) + r * np.log(1-p)
    return out

from timeit import timeit
x = np.random.uniform(-13, 1, (3500, 90, 1)).clip(0, None)
p = np.random.random((3500, 90, 70))
assert np.all(sprse(x, p)==myFun(x, p))
def f():
    return myFun(x, p)
print(timeit(f, number=3))
def f():
    return sprse(x, p)
print(timeit(f, number=3))

नमूना रन:

5.171174691990018
3.2122434769989923
1
Paul Panzer 7 पद 2018, 17:24

आप निम्नलिखित कार्यान्वयन का प्रयास कर सकते हैं। इस सरल कार्य के लिए यह थोड़ा अतिरंजित लगता है, लेकिन मुझे इंटेल एसवीएमएल के साथ काम करने के लिए numexpr प्राप्त करने में भी परेशानी हुई (अन्यथा मैं numexpr पसंद करूंगा)। यह समाधान क्वाडकोर i7 पर प्रति कॉल 0.07s देना चाहिए और अधिक कोर पर काफी अच्छी तरह से स्केल करना चाहिए। कृपया यह भी ध्यान दें कि पहली कॉल में लगभग 0.5 का संकलन ओवरहेड होता है।

इंटेल एसवीएमएल स्थापित करना

import numpy as np
import numba as nb

x = np.random.uniform(-13, 1, (3500, 90, 1)).clip(0, None)
p = np.random.random((3500, 90, 70))

@nb.njit(parallel=True,fastmath=True)
def nb_myFun_sp(x, p):
    out=np.empty(p.shape,p.dtype)
    r = 2.

    for i in nb.prange(p.shape[0]):
      for j in range(p.shape[1]):
        if x[i,j,0]!=0.:
          x_=x[i,j,0]
          for k in range(p.shape[2]):
            out[i,j,k] = x_ * np.log(p[i,j,k]) + r * np.log(1.-p[i,j,k])
        else:
          for k in range(p.shape[2]):
            out[i,j,k] = r * np.log(1.-p[i,j,k])

    return out

@nb.njit(parallel=True,fastmath=True)
def nb_myFun(x, p):
    out=np.empty(p.shape,p.dtype)
    r = 2.

    for i in nb.prange(p.shape[0]):
      for j in range(p.shape[1]):
        x_=x[i,j,0]
        for k in range(p.shape[2]):
          out[i,j,k] = x_ * np.log(p[i,j,k]) + r * np.log(1.-p[i,j,k])
    return out
1
max9111 10 पद 2018, 16:09