सुविधा और प्रदर्शन आम तौर पर विपरीत रूप से सहसंबद्ध होते हैं। यदि कोड का उपयोग करना आसान है, तो यह कम अनुकूलित है। यदि इसे अनुकूलित किया गया है, तो यह कम सुविधाजनक है। कुशल कोड को वास्तव में क्या चल रहा है, कैसे चल रहा है, इसकी विस्तृत जानकारी के करीब पहुंचने की आवश्यकता है।
कैंसर अनुसंधान के लिए डीपसेल सेलुलर सेगमेंटेशन को चलाने और अनुकूलित करने के हमारे चल रहे काम में मुझे एक उदाहरण मिला। डीपसेल एआई मॉडल भविष्यवाणी करता है कि सेल में कौन से पिक्सल के होने की सबसे अधिक संभावना है। वहां से, हम सेल बॉर्डर (कुछ सीमा से नीचे) तक पहुंचने तक, सबसे संभावित पिक्सेल से "बाढ़ भरते" हैं।
इस प्रक्रिया के एक भाग में अनुमानित कोशिकाओं के अंदर छोटे-छोटे अंतरालों को ठीक करना शामिल है, जो विभिन्न कारणों से हो सकता है लेकिन जैविक रूप से संभव नहीं है। (डोनट छेद के बारे में सोचें, कोशिका की छिद्रपूर्ण झिल्ली के बारे में नहीं।)
छेद भरने का एल्गोरिदम इस प्रकार है:
यहां विकिपीडिया लेख से यूलर संख्याओं का एक उदाहरण दिया गया है; एक वृत्त (सिर्फ रेखा भाग) में शून्य की यूलर विशेषता होती है जबकि एक डिस्क ("भरा हुआ" वृत्त) का मान 1 होता है।
हालांकि हम यहां यूलर संख्याओं को परिभाषित करने या गणना करने के बारे में बात करने के लिए नहीं हैं। हम इस बारे में बात करेंगे कि कैसे यूलर संख्याओं की गणना करने के लिए लाइब्रेरी का आसान रास्ता काफी अक्षम है।
सबसे पहली बात। स्पीडस्कोप का उपयोग करके इस प्रोफ़ाइल को देखकर हमने समस्या देखी:
यह रीजनप्रॉप्स में खर्च किए गए ~32 एमएस (~15%) दिखाता है। यह दृश्य बाएँ-भारी है, यदि हम टाइमलाइन दृश्य पर जाते हैं और ज़ूम इन करते हैं, तो हमें यह मिलता है:
(ध्यान दें कि हम ऐसा दो बार करते हैं, इसलिए यहां ~16 एमएस और अन्यत्र ~16 एमएस, नहीं दिखाया गया है।)
यह तुरंत संदेहास्पद है: find_objects के साथ वस्तुओं को खोजने का "दिलचस्प" हिस्सा वह पहला स्लिवर, 0.5ms है। यह टुपल्स की सूची लौटाता है, जनरेटर नहीं, इसलिए जब यह पूरा हो जाता है तो यह हो जाता है। तो बाकी सभी चीज़ों का क्या हाल है? हम रीजनप्रॉपर्टीज़ ऑब्जेक्ट का निर्माण कर रहे हैं। आइए उनमें से एक पर ज़ूम इन करें।
छोटे स्लिवर्स (जिन्हें हम ज़ूम नहीं करेंगे) कस्टम __setattr__ कॉल हैं: रीजनप्रॉपर्टीज़ ऑब्जेक्ट एलियासिंग का समर्थन करते हैं, उदाहरण के लिए यदि आप विशेषता ConvexArea सेट करते हैं तो यह एक मानक विशेषता एरिया_कॉनवेक्स पर रीडायरेक्ट करता है। भले ही हम उसका उपयोग नहीं कर रहे हैं फिर भी हम विशेषता कनवर्टर के माध्यम से ही चलते हैं।
इसके अलावा: हम क्षेत्र की संपत्तियों में गणना की गई अधिकांश संपत्तियों का उपयोग भी नहीं कर रहे हैं। हमें केवल यूलर संख्या की परवाह है:
props = regionprops(np.squeeze(label_img.astype('int')), cache=False) for prop in props: if prop.euler_numberबदले में, यह केवल क्षेत्र गुणों के सबसे बुनियादी पहलू का उपयोग करता है: find_objects (मूल छवि के स्लाइस) द्वारा पता लगाए गए छवि क्षेत्र।
इसलिए, हमने रीजनप्रॉप्स सामान्य प्रयोजन फ़ंक्शन को बायपास करने के लिए कोड को fill_holes कोड में बदल दिया। इसके बजाय, हम find_objects को कॉल करते हैं और परिणामी छवि उप-क्षेत्रों को euler_number फ़ंक्शन में पास करते हैं (RegionProperties ऑब्जेक्ट पर विधि नहीं)।
यहां पुल अनुरोध है: डीपसेल-इमेजिंग#358 रीजनप्रॉप्स निर्माण छोड़ें
मध्यवर्ती ऑब्जेक्ट को छोड़ कर, हमें fill_holes ऑपरेशन के लिए एक अच्छा प्रदर्शन सुधार मिला:
छवि का आकार पहले बाद में गति बढ़ाना 260k पिक्सेल 48 एमएस 40 एमएस 8 एमएस (17%) 140M पिक्सेल 15.6s 11.7s 3.9 सेकंड (25%) बड़ी छवि के लिए, 4एस कुल रनटाइम का ~3% है - इसका बड़ा हिस्सा नहीं, लेकिन बहुत जर्जर भी नहीं।
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3