2017-04-22 8 views
7

मैं निम्नलिखित समस्या को numpy में कार्यान्वित करना चाहता हूं और यहां मेरा कोड है।मैं इस फ़ंक्शन पर गणना को निष्क्रिय में कैसे अनुकूलित कर सकता हूं?

मैंने लूप के लिए इस समस्या के लिए निम्नलिखित numpy कोड का प्रयास किया है। मैं सोच रहा हूं कि क्या इस गणना करने का कोई और अधिक प्रभावी तरीका है? मैं वास्तव में उसकी सराहना करता हूँ!

k, d = X.shape 
m = Y.shape[0] 

c1 = 2.0*sigma**2 
c2 = 0.5*np.log(np.pi*c1) 
c3 = np.log(1.0/k) 

L_B = np.zeros((m,)) 
for i in xrange(m): 
    if i % 100 == 0: 
     print i 
    L_B[i] = np.log(np.sum(np.exp(np.sum(-np.divide(
       np.power(X-Y[i,:],2), c1)-c2,1)+c3))) 

print np.mean(L_B) 

मैं एक 3 डी टेन्सर इसलिए निम्नलिखित गणना प्रसारण द्वारा किया जा सकता बनाने के द्वारा np.expand_dims(X, 2).repeat(Y.shape[0], 2)-Y के बारे में सोचा है, लेकिन है कि स्मृति का एक बहुत बर्बाद होगा जब m बड़ी है।

मुझे यह भी विश्वास है कि np.einsum() लूप के लिए कुछ भी नहीं उपयोग करता है, इसलिए यह कुशल नहीं हो सकता है, अगर मैं गलत हूं तो मुझे सही करें।

कोई विचार?

उत्तर

5

अनुकूलन स्टेज # 1

एक broadcasting को दीवाना कोड का एक सीधा अनुवाद का उपयोग अनुकूलन के मेरी पहली स्तर आधारित एक नया अक्ष शुरू करने पर है और इस तरह तो स्मृति कुशल नहीं एक के रूप में नीचे सूचीबद्ध के रूप में -

p1 = (-((X[:,None] - Y)**2)/c1)-c2 
p11 = p1.sum(2) 
p2 = np.exp(p11+c3) 
out = np.log(p2.sum(0)).mean() 

अनुकूलन स्टेज # 2

में मन में कुछ अनुकूलन रखने वें लाना

c10 = -c1 
c20 = X.shape[1]*c2 

subs = (X[:,None] - Y)**2 
p00 = subs.sum(2) 
p10 = p00/c10 
p11 = p10-c20 
p2 = np.exp(p11+c3) 
out = np.log(p2.sum(0)).mean() 

अनुकूलन स्टेज # 3

इसके साथ आगे जा रहे हैं और और स्थानों को देखने जहां संचालन किया जा सकता है - हम स्थिरांक पर कार्रवाई को अलग करने का इरादा रखते हैं पर, मैं निम्नलिखित के साथ समाप्त हो गया अनुकूलित, मैं Scipy's cdist का उपयोग करके स्क्वायरिंग और sum-reduction के भारी वजन वाले काम को प्रतिस्थापित करने के लिए समाप्त हुआ। यह सुंदर स्मृति कुशल हो सकता है और जैसा कि नीचे दिखाया हमें अंतिम कार्यान्वयन दिया, चाहिए -

प्रयास

from scipy.spatial.distance import cdist 

# Setup constants 
c10 = -c1 
c20 = X.shape[1]*c2 
c30 = c20-c3 
c40 = np.exp(c30) 
c50 = np.log(c40) 

# Get stagewise operations corresponding to loopy ones 
p1 = cdist(X, Y, 'sqeuclidean') 
p2 = np.exp(p1/c10).sum(0) 
out = np.log(p2).mean() - c50 

रनटाइम परीक्षण -

def loopy_app(X, Y, sigma): 
    k, d = X.shape 
    m = Y.shape[0] 

    c1 = 2.0*sigma**2 
    c2 = 0.5*np.log(np.pi*c1) 
    c3 = np.log(1.0/k) 

    L_B = np.zeros((m,)) 
    for i in xrange(m): 
     L_B[i] = np.log(np.sum(np.exp(np.sum(-np.divide(
        np.power(X-Y[i,:],2), c1)-c2,1)+c3))) 

    return np.mean(L_B) 

def vectorized_app(X, Y, sigma): 
    # Setup constants 
    k, d = D_A.shape 
    c1 = 2.0*sigma**2 
    c2 = 0.5*np.log(np.pi*c1) 
    c3 = np.log(1.0/k) 

    c10 = -c1 
    c20 = X.shape[1]*c2 
    c30 = c20-c3 
    c40 = np.exp(c30) 
    c50 = np.log(c40) 

    # Get stagewise operations corresponding to loopy ones 
    p1 = cdist(X, Y, 'sqeuclidean') 
    p2 = np.exp(p1/c10).sum(0) 
    out = np.log(p2).mean() - c50 
    return out 

समय और सत्यापन -

In [294]: # Setup inputs with m(=D_B.shape[0]) being a large number 
    ...: X = np.random.randint(0,9,(100,10)) 
    ...: Y = np.random.randint(0,9,(10000,10)) 
    ...: sigma = 2.34 
    ...: 

In [295]: np.allclose(loopy_app(X, Y, sigma),vectorized_app(X, Y, sigma)) 
Out[295]: True 

In [296]: %timeit loopy_app(X, Y, sigma) 
1 loops, best of 3: 225 ms per loop 

In [297]: %timeit vectorized_app(X, Y, sigma) 
10 loops, best of 3: 23.6 ms per loop 

In [298]: # Setup inputs with m(=Y.shape[0]) being a much large number 
    ...: X = np.random.randint(0,9,(100,10)) 
    ...: Y = np.random.randint(0,9,(100000,10)) 
    ...: sigma = 2.34 
    ...: 

In [299]: np.allclose(loopy_app(X, Y, sigma),vectorized_app(X, Y, sigma)) 
Out[299]: True 

In [300]: %timeit loopy_app(X, Y, sigma) 
1 loops, best of 3: 2.27 s per loop 

In [301]: %timeit vectorized_app(X, Y, sigma) 
1 loops, best of 3: 243 ms per loop 

लगभग 10x गतिशील वहाँ!

+0

कमाल! 10x से अधिक! – xxx222

+0

@ xxx222 आप अपने वास्तविक डेटासेट पर क्या गति प्राप्त कर रहे हैं? – Divakar

+0

लगभग 20x या तो, क्योंकि मेरे पास एक बहुत बड़ा डेटासेट है इसलिए दूरी मैट्रिक्स की गणना करना मुश्किल हो जाता है। – xxx222

संबंधित मुद्दे