NumPy 1.14 - NumPy internals

न्यूमपी इंटर्नल




numpy

न्यूमपी इंटर्नल

सुन्न सरणियों का आंतरिक संगठन

यह थोड़ा समझने में मदद करता है कि सुन्न को बेहतर ढंग से समझने में मदद करने के लिए कवर के नीचे सुन्न सरणियों को कैसे नियंत्रित किया जाता है। यह खंड महान विस्तार में नहीं जाएगा। पूर्ण विवरण को समझने की इच्छा रखने वालों को ट्रैविस ओलिपंट की पुस्तक "गाइड टू न्यूपी" में भेजा जाता है।

NumPy सरणियों में दो प्रमुख घटक होते हैं, कच्चे सरणी डेटा (अब से, डेटा बफर के रूप में संदर्भित), और कच्चे सरणी डेटा के बारे में जानकारी। डेटा बफ़र आमतौर पर लोग सी या फोरट्रान में सरणियों के रूप में सोचते हैं, जो एक निश्चित आकार के डेटा आइटम वाले मेमोरी का एक सन्निहित (और निश्चित) ब्लॉक है। NumPy में डेटा का एक महत्वपूर्ण सेट होता है जो डेटा बफर में डेटा की व्याख्या करने का तरीका बताता है। इस अतिरिक्त जानकारी में (अन्य बातों के अलावा) शामिल हैं:

  1. बाइट्स में मूल डेटा तत्व का आकार
  2. डेटा बफर के भीतर डेटा की शुरुआत (डेटा बफर की शुरुआत के सापेक्ष एक ऑफसेट)।
  3. आयामों की संख्या और प्रत्येक आयाम का आकार
  4. प्रत्येक आयाम ('स्ट्राइड') के लिए तत्वों के बीच अलगाव। यह तत्व आकार के एक से अधिक होने की जरूरत नहीं है
  5. डेटा का बाइट क्रम (जो मूल बाइट ऑर्डर नहीं हो सकता है)
  6. क्या बफर केवल पढ़ने के लिए है
  7. बुनियादी डेटा तत्व की व्याख्या के बारे में जानकारी (dtype ऑब्जेक्ट के माध्यम से)। मूल डेटा तत्व इंट या फ्लोट के रूप में सरल हो सकता है, या यह एक यौगिक वस्तु (उदाहरण के लिए, संरचना जैसी), एक निश्चित चरित्र क्षेत्र, या पायथन ऑब्जेक्ट पॉइंटर्स हो सकता है।
  8. सरणी को सी-ऑर्डर या फोरट्रान-ऑर्डर के रूप में व्याख्या करना है या नहीं।

यह व्यवस्था सरणियों के बहुत लचीले उपयोग की अनुमति देती है। एक चीज जो इसे अनुमति देती है वह है सरणी बफर की व्याख्या को बदलने के लिए मेटाडेटा का सरल परिवर्तन। सरणी के बाइटऑर्डर को बदलना एक सरल परिवर्तन है जिसमें डेटा की कोई पुनर्व्यवस्था नहीं होती है। डेटा बफ़र या किसी भी डेटा कॉपी में कुछ भी बदले बिना ऐरे के आकार को बहुत आसानी से बदला जा सकता है

अन्य चीज़ों के बीच जो संभव हो जाता है, वह एक नई सरणी मेटाडेटा ऑब्जेक्ट बना सकता है जो डेटा बफ़र का एक नया दृश्य बनाने के लिए एक ही डेटा बफ़र का उपयोग करता है जिसमें बफ़र की एक अलग व्याख्या होती है (जैसे, अलग-अलग आकार, ऑफ़सेट, बाइट ऑर्डर, strides, आदि) लेकिन एक ही डेटा बाइट्स साझा करता है। सुन्न में कई ऑपरेशन बस ऐसे करते हैं जैसे कि स्लाइस। अन्य ऑपरेशन, जैसे कि ट्रांज़ोज़, सरणी में डेटा तत्वों को इधर-उधर नहीं करते हैं, बल्कि आकृति के बारे में जानकारी बदलते हैं और आगे बढ़ते हैं ताकि सरणी का अनुक्रमण बदल जाए, लेकिन डेटा स्थानांतरित नहीं होता है।

आमतौर पर सरणी मेटाडेटा के ये नए संस्करण लेकिन समान डेटा बफर डेटा बफर में नए 'दृश्य' होते हैं। एक अलग ndarray ऑब्जेक्ट है, लेकिन यह एक ही डेटा बफर का उपयोग करता है। यही कारण है कि अगर यह वास्तव में डेटा बफर की एक नई और स्वतंत्र प्रतिलिपि बनाना चाहता है, तो .copy () पद्धति के उपयोग के माध्यम से प्रतियों को बाध्य करना आवश्यक है।

सरणियों में नए विचारों का मतलब है डेटा बफर वृद्धि के लिए ऑब्जेक्ट संदर्भ मायने रखता है। मूल सरणी ऑब्जेक्ट के साथ बस करने से डेटा बफर नहीं हटेगा यदि इसके अन्य दृश्य अभी भी मौजूद हैं।

बहुआयामी ऐरे अनुक्रमण आदेश मुद्दे

बहुआयामी सरणियों को अनुक्रमित करने का सही तरीका क्या है? इससे पहले कि आप बहु-आयामी सरणियों को अनुक्रमित करने के लिए एक और सही तरीके के बारे में निष्कर्ष पर जाएं, यह समझने के लिए भुगतान करता है कि यह एक भ्रमित करने वाला मुद्दा क्यों है। यह खंड विस्तार से समझाने की कोशिश करेगा कि सुन्न अनुक्रमण कैसे काम करता है और हम छवियों के लिए हम जो सम्मेलन करते हैं उसे क्यों अपनाते हैं, और जब यह अन्य सम्मेलनों को अपनाने के लिए उपयुक्त हो सकता है।

समझने वाली पहली बात यह है कि 2-आयामी सरणियों को अनुक्रमित करने के लिए दो परस्पर विरोधी सम्मेलन हैं। मैट्रिक्स नोटेशन यह इंगित करने के लिए पहली इंडेक्स का उपयोग करता है कि किस पंक्ति को चुना जा रहा है और दूसरा इंडेक्स यह इंगित करने के लिए कि कौन सा कॉलम चुना गया है। यह उन छवियों के लिए ज्यामितीय रूप से उन्मुख-सम्मेलन के विपरीत है जहां लोग आमतौर पर सोचते हैं कि पहला सूचकांक x स्थिति (यानी, स्तंभ) का प्रतिनिधित्व करता है और दूसरा y स्थिति (यानी, पंक्ति) का प्रतिनिधित्व करता है। यह अकेला बहुत भ्रम का स्रोत है; मैट्रिक्स-उन्मुख उपयोगकर्ता और छवि-उन्मुख उपयोगकर्ता अनुक्रमण के संबंध में दो अलग-अलग चीजों की अपेक्षा करते हैं।

समझने के लिए दूसरा मुद्दा यह है कि सरणी स्मृति में संग्रहीत आदेश के अनुरूप कैसे है। फोरट्रान में पहला इंडेक्स सबसे तेजी से बदलता हुआ इंडेक्स है जो दो डायमेंशनल एरे के तत्वों के माध्यम से आगे बढ़ता है क्योंकि यह मेमोरी में स्टोर होता है। यदि आप अनुक्रमण के लिए मैट्रिक्स कन्वेंशन को अपनाते हैं, तो इसका मतलब है कि मैट्रिक्स को एक बार में एक कॉलम संग्रहीत किया जाता है (चूंकि पहली अनुक्रमणिका अगली पंक्ति में स्थानांतरित होती है क्योंकि यह बदल जाती है)। इस प्रकार फोरट्रान को एक कॉलम-प्रमुख भाषा माना जाता है। C के ठीक विपरीत सम्मेलन है। सी में, अंतिम इंडेक्स सबसे तेजी से बदलता है क्योंकि एक मेमोरी में संग्रहीत सरणी के माध्यम से चलता है। इस प्रकार C एक रो-प्रमुख भाषा है। मैट्रिक्स को पंक्तियों द्वारा संग्रहीत किया जाता है। ध्यान दें कि दोनों स्थितियों में यह माना जाता है कि अनुक्रमण के लिए मैट्रिक्स सम्मेलन का उपयोग किया जा रहा है, यानी, फोरट्रान और सी दोनों के लिए, पहला सूचकांक पंक्ति है। ध्यान दें कि इस कन्वेंशन का तात्पर्य है कि इंडेक्सिंग कन्वेंशन अपरिवर्तनीय है और ऐसा करने के लिए डेटा ऑर्डर बदलता रहता है।

लेकिन यह देखने का एकमात्र तरीका नहीं है। मान लीजिए कि किसी के पास बड़ी द्वि-आयामी सरणियाँ (चित्र या मैट्रीस) हैं, जो डेटा फ़ाइलों में संग्रहीत हैं। मान लें कि डेटा स्तंभों के बजाय पंक्तियों द्वारा संग्रहीत किए जाते हैं। यदि हम अपने सूचकांक सम्मेलन (चाहे मैट्रिक्स या छवि) को संरक्षित करने का मतलब है कि इसका मतलब है कि हम जिस भाषा का उपयोग करते हैं, उसके आधार पर, हमें डेटा को फिर से जारी करने के लिए मजबूर किया जा सकता है अगर यह हमारे सूचकांक सम्मेलन को संरक्षित करने के लिए स्मृति में पढ़ा जाता है। उदाहरण के लिए यदि हम री-ऑर्डर किए बिना मेमोरी में रो-ऑर्डर किए गए डेटा को पढ़ते हैं, तो यह सी के लिए मैट्रिक्स इंडेक्सिंग कन्वेंशन से मेल खाएगा, लेकिन फोरट्रान के लिए नहीं। इसके विपरीत, यह फोरट्रान के लिए इमेज इंडेक्सिंग कन्वेंशन से मेल खाएगा, लेकिन सी के लिए सी के लिए नहीं, यदि कोई पंक्ति क्रम में संग्रहीत डेटा का उपयोग कर रहा है, और कोई छवि इंडेक्स कन्वेंशन को संरक्षित करना चाहता है, तो मेमोरी में पढ़ने पर डेटा को फिर से व्यवस्थित करना होगा।

अंत में, जो आप फोरट्रान या सी के लिए करते हैं, यह इस बात पर निर्भर करता है कि कौन सा अधिक महत्वपूर्ण है, डेटा को फिर से व्यवस्थित करना या अनुक्रमण सम्मेलन को संरक्षित करना नहीं। बड़ी छवियों के लिए, डेटा को पुन: क्रमबद्ध करना महंगा है, और अक्सर इससे बचने के लिए अनुक्रमण सम्मेलन उलटा होता है।

सुन्न के साथ स्थिति इस मुद्दे को और अधिक जटिल बना देती है। सूचक के किसी भी आदेश को स्वीकार करने के लिए सुन्न सरणियों की आंतरिक मशीनरी पर्याप्त लचीली है। कोई भी डेटा को पुन: व्यवस्थित किए बिना सरणियों के लिए आंतरिक स्ट्राइड जानकारी में हेरफेर करके केवल सूचकांकों को पुनः व्यवस्थित कर सकता है। NumPy को पता चलेगा कि डेटा को स्थानांतरित किए बिना डेटा को नए इंडेक्स ऑर्डर को कैसे मैप किया जाए।

इसलिए यदि यह सत्य है, तो उस अनुक्रमणिका क्रम को क्यों न चुनें, जो आपकी अपेक्षा से मेल खाता है? विशेष रूप से, छवि सम्मेलन का उपयोग करने के लिए पंक्ति-क्रम वाली छवियों को परिभाषित क्यों नहीं किया जाता है? (इसे कभी-कभी फोर्ट्रान सम्मेलन बनाम सी कन्वेंशन के रूप में संदर्भित किया जाता है, इस प्रकार 'सी' और 'फोरट्रान' क्रम में अरेंज ऑर्डर के लिए विकल्प विकल्प।) ऐसा करने का दोष संभावित प्रदर्शन दंड है। यह क्रमिक रूप से डेटा तक पहुँचने के लिए आम है, या तो सरणी संचालन में या स्पष्ट रूप से किसी छवि की पंक्तियों पर लूप करके। जब ऐसा किया जाता है, तो डेटा गैर-इष्टतम क्रम में एक्सेस किया जाएगा। जैसा कि पहले सूचकांक में वृद्धि हुई है, वास्तव में क्या हो रहा है कि स्मृति में दूर तक फैले तत्वों को क्रमिक रूप से एक्सेस किया जा रहा है, आमतौर पर खराब मेमोरी एक्सेस गति के साथ। उदाहरण के लिए, दो आयामी छवि 'im' के लिए परिभाषित किया गया है ताकि im [0, 10] x = 0, y = 10 पर मान का प्रतिनिधित्व करे। सामान्य पायथन व्यवहार के अनुरूप होना तो im [0] x = 0 पर एक कॉलम का प्रतिनिधित्व करेगा। फिर भी वह डेटा पूरे क्रम में फैला होगा क्योंकि डेटा को पंक्ति क्रम में संग्रहीत किया जाता है। संख्यात्मक खराबी के लचीलेपन के बावजूद, यह वास्तव में इस तथ्य पर कागज नहीं दे सकता है कि बुनियादी आदेश डेटा आदेश के कारण अक्षम हैं या कि सन्निहित सबरेज़ मिलना अभी भी अजीब है (जैसे, im [: 0], पहली पंक्ति के लिए, बनाम im] 0]), इस प्रकार एक मुहावरे का उपयोग नहीं कर सकते जैसे कि im में पंक्ति के लिए; के लिए में im काम करता है, लेकिन सन्निहित स्तंभ डेटा उपज नहीं है।

जैसा कि यह पता चला है, सूफी काफी स्मार्ट है जब यह निर्धारित करने के लिए कि किस सूचकांक में मेमोरी में सबसे तेजी से बदलती है और अंतरतम लूप के लिए इसका उपयोग किया जाता है। इस प्रकार ufuncs के लिए ज्यादातर मामलों में या तो दृष्टिकोण के लिए कोई बड़ा आंतरिक लाभ नहीं है। दूसरी ओर, एक फोरट्रान ऑर्डर किए गए सरणी के साथ .flat का उपयोग गैर-इष्टतम मेमोरी एक्सेस को बढ़ावा देगा क्योंकि समतल सरणी (इट्रेटर,) में आसन्न तत्व वास्तव में मेमोरी में सन्निहित नहीं हैं।

वास्तव में, तथ्य यह है कि सूचियों और अन्य अनुक्रमों पर पायथन अनुक्रमण स्वाभाविक रूप से एक बाहरी-अंदर के आदेश की ओर जाता है (पहला सूचकांक सबसे बड़ा समूहन प्राप्त करता है, अगला सबसे बड़ा, और अंतिम सबसे छोटा तत्व प्राप्त करता है)। चूंकि छवि डेटा आम तौर पर पंक्तियों द्वारा संग्रहीत किया जाता है, यह पंक्तियों के भीतर स्थिति से मेल खाता है अंतिम आइटम अनुक्रमित किया जा रहा है।

यदि आप फोरट्रान ऑर्डरिंग का उपयोग करना चाहते हैं, तो महसूस करें कि विचार करने के लिए दो दृष्टिकोण हैं: 1) स्वीकार करें कि पहला इंडेक्स सिर्फ मेमोरी में सबसे तेजी से बदलने वाला नहीं है और मेमोरी से डिस्क पर जाते समय आपके सभी आई / ओ रूटीन आपके डेटा को फिर से व्यवस्थित करते हैं। या वीज़ा वर्सा, या पहले इंडेक्स की मैपिंग के लिए सबसे तेज़ी से बदलती डेटा के लिए numpy के तंत्र का उपयोग करें। यदि संभव हो तो हम पूर्व की सलाह देते हैं। उत्तरार्द्ध का नुकसान यह है कि जब तक आप 'ऑर्डर' कीवर्ड का उपयोग करने के लिए सावधान नहीं रहते, तब तक सुन्न के कई कार्य फोरट्रान ऑर्डर के बिना सरणियों का उत्पादन करेंगे। ऐसा करना अत्यधिक असुविधाजनक होगा।

अन्यथा हम किसी ऐरे के तत्वों को एक्सेस करते समय सूचकांकों के सामान्य क्रम को उल्टा करने के लिए सीखने की सलाह देते हैं। दी, यह अनाज के खिलाफ जाता है, लेकिन यह पायथन शब्दार्थ और डेटा के प्राकृतिक क्रम के अनुरूप है।