2013-03-25 13 views
6

ठीक है, तो मेरे पास सिम्पी ऑब्जेक्ट्स (एक्सप्रेशन) के कई, बहु-आयामी numpy arrays हैं। उदाहरण के लिए:मैं sypy के साथ अच्छी तरह से खेलने के लिए numpy.einsum कैसे मिलता है?

A = array([[1.0*cos(z0)**2 + 1.0, 1.0*cos(z0)], 
      [1.0*cos(z0), 1.00000000000000]], dtype=object) 

और इसी तरह।

मैं जो करना चाहता हूं वह इन्सम का उपयोग करके इनमें से कई सरणी गुणा करता है, क्योंकि मेरे पास पहले से ही एक संख्यात्मक गणना से सिंटैक्स है जो मैं पहले कर रहा था। समस्या यह है, जब मैं की तरह

einsum('ik,jkim,j', A, B, C) 

मैं एक प्रकार त्रुटि मिलती है कुछ करने के लिए प्रयास करें:

TypeError: invalid data type for einsum 

ज़रूर, तो गूगल पर एक त्वरित खोज मुझे einsum शायद पता चलता ऐसा नहीं कर सकते, लेकिन क्यों कोई कारण नहीं है। विशेष रूप से, उन सरणी पर numpy.dot() और numpy.tensordot() फ़ंक्शंस को कॉल करना एक आकर्षण की तरह काम करता है। मैं कर सकता हूं जो मुझे चाहिए, करने के लिए tensordot का उपयोग करें, लेकिन जब मुझे लगता है कि मेरे ऊपर दिमाग में पचास या इतने ईस्टेन सारांशों को बदलने के बारे में लगता है (जहां indeces का क्रम बहुत महत्वपूर्ण है) नेस्टेड tensordot कॉल के साथ। यहां तक ​​कि और भी दुःस्वप्न उस कोड को डीबग करने और उस गलत स्थान इंडेक्स स्वैप के लिए शिकार करने के बावजूद है।

लंबी कहानी छोटी, क्या किसी को पता है कि टेंसडॉट ऑब्जेक्ट्स के साथ क्यों काम करता है लेकिन ईन्सम नहीं होगा? कामकाज की ओर कोई सुझाव? यदि नहीं, तो कोई सुझाव है कि मैं अपने स्वयं के रैपर को नेस्टेड टेन्सॉर्डॉट कॉल पर लिखने के बारे में कैसे कहूंगा जो कि कुछ हद तक इन्सुम नोटेशन के समान है (अक्षरों की बजाय संख्याएं ठीक हैं)?

+0

ईन्सम के पास डॉट या टेंसॉर्डॉट के साथ कुछ भी नहीं है, यह पूरी तरह से बिल्कुल अलग है। आप हाथ से ईन्सम तर्क कर सकते हैं, यदि संभव हो तो किसी अन्य प्रकार पर डालें या ऑब्जेक्ट प्रकारों के लिए इन्सुम लागू करें। वास्तव में 'object_einsum' को कार्यान्वित करना बहुत मुश्किल नहीं होना चाहिए ... – seberg

+0

@seberg,' पूरी तरह से अलग 'द्वारा आप कार्यान्वयन का संदर्भ देते हैं, न कि गणितीय विचारों, सही? क्या कोई कारण है कि वे अलग-अलग लागू किए गए हैं? उदाहरण के लिए मैं 'tensordot' के संदर्भ में 'einsum' लागू किया जा रहा हूं, लेकिन शायद मुझे कुछ याद आ रहा है। – Krastanov

उत्तर

3

ईन्सम मूल रूप से tensordot (डॉट नहीं, क्योंकि डॉट आमतौर पर अनुकूलित रैखिक बीजगणित पैकेज का उपयोग कर रहा है) को कोड करता है, कोड के अनुसार यह पूरी तरह से अलग है।

यहां एक ऑब्जेक्ट इन्सुम है, इसकी अनचाहे (अधिक जटिल चीजों के लिए), लेकिन मुझे लगता है कि इसे काम करना चाहिए ... सी में एक ही चीज़ करना संभवतः सरल है क्योंकि आप सब कुछ चुरा सकते हैं लेकिन लूप खुद को वास्तविक से ईन्सम समारोह। तो अगर आप ऐसा लग रहा है, इसे लागू से अधिक लोगों को खुश करने के ...

https://gist.github.com/seberg/5236560

मैं कुछ भी गारंटी नहीं है, विशेष रूप से weirder कोने मामलों के लिए नहीं। बेशक आप टिनसॉर्डॉट नोटेशन के लिए इन्सुम नोटेशन का अनुवाद भी कर सकते हैं, मुझे यकीन है, और शायद यह थोड़ा तेज़ है क्योंकि लूप अधिकतर सी में समाप्त हो जाएंगे ...

+0

धन्यवाद, मैं इसे आज़मा दूंगा! मुझे पूरा यकीन नहीं है कि मैं सी के बारे में आपके बिंदु को समझता हूं ... हालांकि मुझे गुणा करने के तरीके के बारे में जानने के लिए ऑब्जेक्ट्स 'मल्टी() फ़ंक्शन तक पहुंच प्राप्त करनी होगी, और मैं इस तरह के एक प्रकार का नया हूं सामान। क्या आप उस पर विस्तार करना चाहते हैं? – vlsd

+1

हां, निश्चित रूप से आपको पायथन सी-एपीआई का उपयोग करने की आवश्यकता है, लेकिन आप इसे पढ़ सकते हैं। मेरा मतलब यह है कि एनआईडीटर भाग स्वयं 'एडवांस्ड न्यू' के साथ लगभग समान है और मौजूदा ईन्सम फ़ंक्शन से लगभग पूरी तरह से कॉपी किया जा सकता है। – seberg

+0

@seberg, मैं दो उत्तरों की तुलना कर रहा हूं। क्या 'tensordot' के संदर्भ में' einsum' को फिर से लिखने के बजाय गहरे numpy API का उपयोग करने का कोई कारण है। क्या मुझे कुछ शुद्धता जांच याद आ रही है? क्या आपके कोड में शुद्धता जांच बेहतर होने के अलावा कुछ है? क्या यह प्रदर्शन है (आखिरकार हम 'ऑब्जेक्ट' के साथ काम करते हैं जो शायद ही कभी अच्छा प्रदर्शन कर रहा है)। – Krastanov

2

यहां एक बहुत ही सरल कार्यान्वयन है जो einsum को अलग करता है एकाधिक tensordot एस।

def einsum(string, *args): 
    index_groups = map(list, string.split(',')) 
    assert len(index_groups) == len(args) 
    tensor_indices_tuples = zip(index_groups, args) 
    return reduce(einsum_for_two, tensor_indices_tuples)[1] 

def einsum_for_two(tensor_indices1, tensor_indices2): 
    string1, tensor1 = tensor_indices1 
    string2, tensor2 = tensor_indices2 
    sum_over_indices = set(string1).intersection(set(string2)) 
    new_string = string1 + string2 
    axes = ([], []) 
    for i in sum_over_indices: 
     new_string.remove(i) 
     new_string.remove(i) 
     axes[0].append(string1.index(i)) 
     axes[1].append(string2.index(i)) 
    return new_string, np.tensordot(tensor1, tensor2, axes) 

पहले यह (सूचकांक, टेंसर) की tuples में einsum तर्क अलग करती है। तो फिर यह सूची में सबसे कम कर देता है इस प्रकार है:

  • पहले दो tuples ले जाता है, और उन पर एक सरल einsum_for_two मूल्यांकन करता है। यह नए सूचकांक हस्ताक्षर भी प्रिंट करता है।
  • einsum_for_two का मान einsum_for_two के लिए नए तर्क के रूप में सूची में अगले टुपल के साथ उपयोग किया जाता है।
  • तब तक जारी रहता है जब तक केवल टुपल नहीं छोड़ा जाता है। सूचकांक हस्ताक्षर को त्याग दिया जाता है और केवल टेंसर वापस कर दिया जाता है।

यह शायद धीमा है (लेकिन फिर भी आप objectdtype का उपयोग कर रहे हैं)। यह इनपुट पर कई शुद्धता जांच नहीं करता है।

जैसा कि @seberg ने नोट किया, मेरा कोड टेंसर के निशान के लिए काम नहीं करता है।

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