2017-01-28 10 views
5

मैं matplotlib के hist फ़ंक्शन का उपयोग करके वितरण के लिए फिटिंग सांख्यिकीय मॉडल पर काम कर रहा हूं। उदाहरण के लिए मेरे कोड निम्नलिखित कोड का उपयोग कर एक घातीय वितरण फिट बैठता है:scipy.optimize.curve_fit को फ़ंक्शन को चलाने के लिए पूरा करने की आवश्यकता क्या है?

try: 

     def expDist(x, a, x0): 
      return a*(exp(-(x/x0))/x0) 

     self.n, self.bins, patches = plt.hist(self.getDataSet(), self.getDatasetSize()/10, normed=1, facecolor='blue', alpha = 0.55) 
     popt,pcov = curve_fit(expDist,self.bins[:-1], self.n, p0=[1,mean]) 
     print "Fitted gaussian curve to data with params a %f, x0 %f" % (popt[0], popt[1]) 
     self.a = popt[0] 
     self.x0 = popt[1] 

     self.fitted = True 
    except RuntimeError: 
     print "Unable to fit data to exponential curve" 

कौन सा ठीक चलाता है, लेकिन जब मैं a & b के बीच एक समान वितरण के लिए एक ही बात करने के लिए, इसे संशोधित

def uniDist(x, a, b): 
     if((x >= a)and(x <= b)): 
      return float(1.0/float(b-a)) 
     else: 
      return 0.000 

    try: 



     self.n, self.bins, patches = plt.hist(self.getDataSet(), self.getDatasetSize()/10, normed=1, facecolor='blue', alpha = 0.55) 
     popt,pcov = curve_fit(uniDist,self.bins[:-1], self.n, p0=[a, b]) 
     print "Fitted uniform distribution curve to data with params a %f, b %f" % (popt[0], popt[1]) 
     self.a = popt[0] 
     self.b = popt[1] 

     self.fitted = True 
    except RuntimeError: 
     print "Unable to fit data to uniform distribution pdf curve" 

कोड क्रैश,

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

मुद्दे के साथ curve_fit में है कि कहीं न कहीं, वें प्रतीत हो रहा है ई फ़ंक्शन फ़ंक्शन को कॉल करने की कोशिश कर रहा है (expDist, और uniDist इस मामले में) मानों के एक पुनरावर्तक सेट के साथ, लेकिन मुझे यह पता नहीं लगा सकता कि expDist फ़ंक्शन क्रैश किए बिना कुछ भी करने में सक्षम है?

+1

https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html – user2357112

उत्तर

2

आपका संदेह आंशिक रूप से सही है। curve_fit वास्तव में फ़ंक्शन के लिए एक पुनरावर्तक पास करता है, लेकिन केवल किसी भी पुनरावर्तनीय नहीं: numpy.ndarray। ये अंकगणितीय ऑपरेटर vectorized के अधिकारी को भी हो, तो

a*(exp(-(x/x0))/x0) 

बस किसी भी त्रुटि के बिना काम करेंगे तत्व के लिहाज से इनपुट सरणियों से अधिक (और सही उत्पादन के साथ)। इसमें बहुत अधिक जादू शामिल नहीं है: फ़ंक्शन के प्रत्येक मूल्यांकन के लिए, पैरामीटर a और x0 स्केलर होंगे, केवल x एक सरणी है।

अब, uniDist के साथ समस्या यह है कि इसमें केवल अंकगणितीय ऑपरेटरों नहीं हैं: इसमें तुलना ऑपरेटर भी शामिल हैं। ये काम ठीक जब तक केवल एक ही सरणी एक अदिश की तुलना में है:

>>> import numpy as np 
>>> a = np.arange(5) 
>>> a 
array([0, 1, 2, 3, 4]) 
>>> a>2 
array([False, False, False, True, True], dtype=bool) 

ऊपर यह दर्शाता है कि एक सरणी पर तुलना ऑपरेटर्स का उपयोग और एक अदिश फिर से तत्व के लिहाज से परिणाम देगा। त्रुटि आप देख उठता है जब आप इन बूलियन सरणियों के दो के लिए एक तार्किक ऑपरेटर लागू करने का प्रयास:

>>> a>2 
array([False, False, False, True, True], dtype=bool) 
>>> a<4 
array([ True, True, True, True, False], dtype=bool) 
>>> (a>2) and (a<4) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

त्रुटि संदेश थोड़ा भ्रामक है। इसे इस तथ्य पर वापस देखा जा सकता है कि अजगर array1 and array2 के लिए एक परिणाम के साथ आने का प्रयास करेगा (जो देशी पायथन में अपनी खालीपन के आधार पर सरणी वापस कर देगा)। हालांकि, numpy संदिग्ध है कि यह वह नहीं है जो आप करना चाहते हैं, और अनुमान लगाने के लिए प्रलोभन का विरोध करता है।

जब से तुम तत्व के लिहाज से दो बूलियन सरणियों (जो तुलना आपरेशन से आते हैं) पर संचालित करने के लिए अपने समारोह चाहते हैं, आप & ऑपरेटर का उपयोग करना होगा। यह देशी अजगर में "द्विआधारी और" है, लेकिन numpy arrays के लिए यह आपको सरणी के तत्व "बुद्धिमान और" देता है। तुम भी numpy.logical_and इस्तेमाल कर सकते हैं (या अपने मामले scipy.logical_and में) अधिक स्पष्ट होने के लिए:

>>> (a>2) & (a<4) 
array([False, False, False, True, False], dtype=bool) 
>>> np.logical_and(a>2,a<4) 
array([False, False, False, True, False], dtype=bool) 

ध्यान दें कि & मामले तुम हमेशा (प्रोग्रामर करने के लिए) अपने तुलना बीच में लिखना है, क्योंकि फिर a>2&a<4 अस्पष्ट हो जाएगा के लिए और गलत (इस बात पर विचार करें कि आप करना चाहते हैं)।चूंकि "बाइनरी और" बूलियन वास्तव में व्यवहार करेंगे जैसा कि आप उम्मीद करेंगे, दो तुलनाओं की तुलना करने के लिए के बजाय & का उपयोग करने के लिए अपने फ़ंक्शन को फिर से लिखना सुरक्षित है।

हालांकि, अभी भी एक कदम है जिसे आपको बदलने की आवश्यकता होगी: ndarray इनपुट के मामले में, if भी अलग-अलग व्यवहार करेगा। पाइथन मदद नहीं कर सकता है लेकिन if में एक ही विकल्प बना सकता है, जो कि यदि आप इसमें सरणी डालते हैं तो यह भी सच है। लेकिन आप वास्तव में क्या करना चाहते हैं अपने आउटपुट तत्व-वार (फिर से) के तत्वों को बाधित करना है। तो आपको या तो अपनी सरणी (लेट नहीं) पर लूप करना होगा, या वेक्टरेटेड तरीके से फिर से यह विकल्प करना होगा।

import scipy as sp 
def uniDist(x, a, b): 
    return sp.where((a<=x) & (x<=b), 1.0/(b-a), 0.0) 

यह वही x के रूप में आकार (अर्थात् numpy.where) एक सरणी वापस आ जाएगी: उत्तरार्द्ध मुहावरेदार का उपयोग कर numpy/scipy है। उन तत्वों के लिए जहां स्थिति True है, आउटपुट का मान 1/(b-a) होगा। बाकी के लिए आउटपुट 0 है। स्केलर x के लिए, वापसी मूल्य एक numpy scalar है। ध्यान दें कि मैंने उपर्युक्त उदाहरण में float रूपांतरण को हटा दिया है, क्योंकि 1.0 संख्यात्मक में आपको निश्चित रूप से सही विभाजन प्रदान करेगा, आपके पाइथन 2 का उपयोग करने के बावजूद। हालांकि मैं अजगर 3, या कम से कम from __future__ import division का उपयोग करने का सुझाव दूंगा।


माइनर ध्यान दें: यहां तक ​​कि एक अदिश मामले के लिए मैं अजगर के ऑपरेटर तुलना, जो अपने आप को इस उद्देश्य के लिए उधार देता है के लिए चेनिंग का इस्तेमाल कर रही सुझाव है। मेरा मतलब यह है कि आप बस if a <= x <= b: ... कर सकते हैं, और अधिकांश भाषाओं के विपरीत, यह आपके द्वारा लिखे गए कार्यों के बराबर काम करेगा (लेकिन सुंदर)।

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

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