2012-04-03 15 views
14

मैं थोड़ी-बहुत माफी चाहता हूं अगर इस प्रश्न का उत्तर पहले से ही दिया जा चुका है, तो मैंने देखा है और विशेष रूप से जो मैं ढूंढ रहा था उसे नहीं मिला।रैखिक प्रतिगमन में शून्य अवरोध को कैसे बल दिया जाए?

मैं रूप से कुछ कम या ज्यादा रेखीय डेटा है

x = [0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 20.0, 40.0, 60.0, 80.0] 
y = [0.50505332505407008, 1.1207373784533172, 2.1981844719020001, 3.1746209003398689, 4.2905482471260044, 6.2816226678076958, 11.073788414382639, 23.248479770546009, 32.120462301367183, 44.036117671229206, 54.009003143831116, 102.7077685684846, 185.72880217806673, 256.12183145545811, 301.97120103079675] 

मैं scipy.optimize.leastsq उपयोग कर रहा हूँ यह करने के लिए एक रेखीय प्रतिगमन फिट करने के लिए:

def lin_fit(x, y): 
    '''Fits a linear fit of the form mx+b to the data''' 
    fitfunc = lambda params, x: params[0] * x + params[1] #create fitting function of form mx+b 
    errfunc = lambda p, x, y: fitfunc(p, x) - y    #create error function for least squares fit 

    init_a = 0.5       #find initial value for a (gradient) 
    init_b = min(y)       #find initial value for b (y axis intersection) 
    init_p = numpy.array((init_a, init_b)) #bundle initial values in initial parameters 

    #calculate best fitting parameters (i.e. m and b) using the error function 
    p1, success = scipy.optimize.leastsq(errfunc, init_p.copy(), args = (x, y)) 
    f = fitfunc(p1, x)   #create a fit with those parameters 
    return p1, f  

और यह खूबसूरती से काम करता है (हालांकि मैं नहीं कर रहा हूँ सुनिश्चित करें कि scipy.optimize यहां उपयोग करने के लिए सही बात है, यह शीर्ष पर थोड़ा सा हो सकता है?)।

हालांकि, डेटा बिंदुओं के झूठ के कारण यह मुझे 0 पर वाई-अक्ष इंटरसेप्शन नहीं देता है। मुझे पता है कि इस मामले में यह शून्य होना चाहिए, if x = 0 than y = 0

क्या कोई तरीका है जिससे मैं इसे मजबूर कर सकता हूं?

+0

क्या आप जानते हैं अपने अवरोधन 0 है, तो क्यों आप अपने समारोह में एक नि: शुल्क पैरामीटर फिट करने के लिए के रूप में यह क्या है? क्या आप बस एक मुक्त पैरामीटर के रूप में 'बी' को हटा सकते हैं? – Jdog

+0

आह। हाँ। बेशक! मैं क्षमा चाहता हूं, यह वास्तव में एक स्पष्ट जवाब है। कभी-कभी मुझे पेड़ों के लिए लकड़ी नहीं दिखाई देती: -/यह ठीक काम करता है। मुझे यह इंगित करने के लिए बहुत बहुत धन्यवाद! –

+0

मैं सिर्फ एक जवाब में डेटा की साजिश देखता हूं। प्रश्न से असंबंधित, आपको फिट करने के लिए एक दूसरे क्रम बहुपद का प्रयास करना चाहिए। आम तौर पर कोई यह कह सकता है कि इसकी त्रुटि के क्रम में अवरोध शून्य है, और मुझे लगता है कि एक पैराबोला फिट में आपको यह मिल जाएगा। – chuse

उत्तर

9

मैं इन मॉड्यूल में सक्षम नहीं हूं, लेकिन मुझे आंकड़ों में कुछ अनुभव है, इसलिए मैं जो देखता हूं वह यहां है। इसके अलावा लाइन हटाने

fitfunc = lambda params, x: params[0] * x 

:

init_b = min(y) 

और करने के लिए अगली पंक्ति को बदलने:

init_p = numpy.array((init_a)) 

आप से

fitfunc = lambda params, x: params[0] * x + params[1] 

करने के लिए अपने फिट समारोह को बदलने की जरूरत यह दूसरे पैरामीटर से छुटकारा पाना चाहिए वह y-intercept का उत्पादन कर रहा है और मूल के माध्यम से फिट लाइन पास कर रहा है। आपके शेष कोड में इसके लिए कुछ और मामूली बदलाव हो सकते हैं।

लेकिन हाँ, मुझे यकीन नहीं है कि यह मॉड्यूल काम करेगा यदि आप इस तरह दूसरे पैरामीटर को दूर करते हैं। यह मॉड्यूल के आंतरिक कार्यों पर निर्भर करता है कि क्या यह इस संशोधन को स्वीकार कर सकता है या नहीं। उदाहरण के लिए, मुझे नहीं पता कि params, पैरामीटर की सूची शुरू की जा रही है, इसलिए मुझे नहीं पता कि यह करने से इसकी लंबाई बदल जाएगी या नहीं।

और एक तरफ के रूप में, जैसा कि आपने उल्लेख किया है, यह वास्तव में लगता है कि यह सिर्फ एक ढलान को अनुकूलित करने के लिए एक शीर्ष-शीर्ष तरीका है। आप रैखिक प्रतिगमन को थोड़ा और लिफाफा कैलकुस के बाद इसे स्वयं करने के लिए छोटे कोड लिख सकते हैं। यह वास्तव में बहुत सरल और सीधा है। असल में, मैंने अभी कुछ गणना की है, और मुझे लगता है कि अनुकूलित ढलान सिर्फ <xy>/<x^2> होगा, यानी एक्स * वाई उत्पादों का मतलब x^2 के माध्यम से विभाजित है।

+0

धन्यवाद, यह वही है जो मुझे करने की ज़रूरत है। :) –

+0

वास्तव में 'y = a * x' के कम-वर्ग फिट के लिए उचित समाधान केवल एक = x.dot (y) /x.dot (x)' है क्योंकि अभरिल ने अंत में लिखा था। – divenex

26

@AbhranilDas के रूप में उल्लेख किया गया है, बस एक रैखिक विधि का उपयोग करें। scipy.optimize.lstsq जैसे गैर-रैखिक सॉल्वर की कोई आवश्यकता नहीं है।

आमतौर पर, आप अपने डेटा के लिए एक पंक्ति फिट करने के लिए numpy.polyfit का उपयोग करेंगे, लेकिन इस मामले में आपको सीधे numpy.linalg.lstsq का उपयोग करने की आवश्यकता होगी, क्योंकि आप शून्य पर अवरोध सेट करना चाहते हैं।

एक त्वरित उदाहरण के रूप में:

import numpy as np 
import matplotlib.pyplot as plt 

x = np.array([0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 
       20.0, 40.0, 60.0, 80.0]) 

y = np.array([0.50505332505407008, 1.1207373784533172, 2.1981844719020001, 
       3.1746209003398689, 4.2905482471260044, 6.2816226678076958, 
       11.073788414382639, 23.248479770546009, 32.120462301367183, 
       44.036117671229206, 54.009003143831116, 102.7077685684846, 
       185.72880217806673, 256.12183145545811, 301.97120103079675]) 

# Our model is y = a * x, so things are quite simple, in this case... 
# x needs to be a column vector instead of a 1D vector for this, however. 
x = x[:,np.newaxis] 
a, _, _, _ = np.linalg.lstsq(x, y) 

plt.plot(x, y, 'bo') 
plt.plot(x, a*x, 'r-') 
plt.show() 

enter image description here

+0

धन्यवाद। यह वह जवाब था जिसे मैं ढूंढ रहा था। मुझे अपनी समग्र समझ में मदद मिली एक अवरोध के साथ 'linalg.lstsq' का उपयोग करने के लिए एक और उदाहरण मिला। ऐसा करने के लिए, 'x = x [:, np.newaxis]' 'x = np.vstack ([x, np.ones (len (x))] के साथ बदलें। टी ' – Snorfalorpagus

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