2012-09-23 23 views
5

enter image description hereMatlab में विभाजित लाइनों की एक श्रृंखला द्वारा वक्र फिट करने के लिए कैसे?

मेरे पास ऊपर के रूप में एक साधारण लॉगलॉग वक्र है। क्या मैटलैब में कुछ फ़ंक्शन है जो सेगमेंट लाइनों द्वारा इस वक्र को फिट कर सकता है और इन लाइन सेगमेंट के शुरुआती और अंतिम बिंदु दिखा सकता है? मैंने matlab में वक्र फिटिंग टूलबॉक्स की जांच की है। ऐसा लगता है कि वे एक पंक्ति या कुछ कार्यों से वक्र फिट बैठते हैं। मैं केवल एक पंक्ति से फिटिंग वक्र नहीं करना चाहता हूं।

यदि कोई प्रत्यक्ष कार्य नहीं है, तो एक ही लक्ष्य प्राप्त करने का कोई भी विकल्प मेरे साथ ठीक है। मेरा लक्ष्य खंडित लाइनों द्वारा वक्र फिट करना है और इन खंडों के अंतिम बिंदुओं के स्थान प्राप्त करना है।

उत्तर

7

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

  1. स्प्लिट मैन्युअल:

    मैं निम्नलिखित रणनीति सुझाव देते हैं। खंड आकार व्युत्पन्न, बड़े व्युत्पन्न पर निर्भर होना चाहिए -> छोटा सा भाग

  2. नमूना वर्गों
  3. के बीच नोड्स पर समारोह एक रैखिक प्रक्षेप कि अंक ऊपर उल्लेख किया है के माध्यम से गुजरता का पता लगाएं।

यहां एक कोड का एक उदाहरण है जो ऐसा करता है। आप देख सकते हैं कि खंडों की छोटी मात्रा के बावजूद लाल रेखा (इंटरपोलेशन) मूल कार्य के बहुत करीब है। यह अनुकूलक अनुभाग आकार के कारण होता है।

enter image description here

function fitLogLog() 
    x = 2:1000; 
    y = log(log(x)); 

    %# Find section sizes, by using an inverse of the approximation of the derivative 
    numOfSections = 20; 
    indexes = round(linspace(1,numel(y),numOfSections)); 
    derivativeApprox = diff(y(indexes)); 
    inverseDerivative = 1./derivativeApprox; 
    weightOfSection = inverseDerivative/sum(inverseDerivative); 
    totalRange = max(x(:))-min(x(:)); 
    sectionSize = weightOfSection.* totalRange; 

    %# The relevant nodes 
    xNodes = x(1) + [ 0 cumsum(sectionSize)]; 
    yNodes = log(log(xNodes)); 

    figure;plot(x,y); 
    hold on; 
    plot (xNodes,yNodes,'r'); 
    scatter (xNodes,yNodes,'r'); 
    legend('log(log(x))','adaptive linear interpolation'); 
end 
+0

आप स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। रैखिक इंटरपोलेशन और मैटलैब के लिए मेरी उथली पृष्ठभूमि के लिए खेद है। मुझे लगता है कि आपने जो किया है वह बहुत अच्छा है। हालांकि, मेरे अनुसार मेरे कोड को संशोधित करने में मुझे कठिन समय है। मेरा मूल डेटा, वाई, 1 * 73 पंक्ति वेक्टर है जिसका वितरण सीजेएच के समाधान में सामान्य साजिश की तरह दिखता है। क्या आप लॉग-लॉग अक्ष प्लॉट (अंतिम लॉग (लॉग (x)) गणना में अंतिम परिणाम दिखाने के लिए अपने कोड को संशोधित कैसे कर सकते हैं)? बहुत बहुत धन्यवाद, – Cassie

5

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

Nsamp = 1000;  %number of data samples on x-axis 
x = [1:Nsamp]; %this is your x-axis 
Nlines = 5;  %number of lines to fit 

fx = exp(-10*x/Nsamp); %generate something like your current data, f(x) 
gx = NaN(size(fx));  %this will hold your fitted lines, g(x) 

joins = round(linspace(1, Nsamp, Nlines+1)); %define equally spaced breaks along the x-axis 

dx = diff(x(joins)); %x-change 
df = diff(fx(joins)); %f(x)-change 

m = df./dx; %gradient for each section 

for i = 1:Nlines 
    x1 = joins(i); %start point 
    x2 = joins(i+1); %end point 
    gx(x1:x2) = fx(x1) + m(i)*(0:dx(i)); %compute line segment 
end 

subplot(2,1,1) 
h(1,:) = plot(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro'); 
title('Normal Plot') 

subplot(2,1,2) 
h(2,:) = loglog(x, fx, 'b', x, gx, 'k', joins, gx(joins), 'ro'); 
title('Log Log Plot') 

for ip = 1:2 
    subplot(2,1,ip) 
    set(h(ip,:), 'LineWidth', 2) 
    legend('Data', 'Piecewise Linear', 'Location', 'NorthEastOutside') 
    legend boxoff 
end 

MATLAB plotted output

+0

+1 - कुल मिलाकर अच्छा जवाब। वैसे, मैंने सोचा कि फ़ंक्शन का नमूना लेने के बजाय, हमारी सभी विधियों को सभी त्रुटियों के योग को कम करके कम किया जा सकता है। उदाहरण के लिए, आपकी पहली साजिश में, कुल फिट बढ़ाने के लिए दूसरा नोड फ़ंक्शन वैल्यू के नीचे ले जाया जा सकता है। –

+0

+1 - हाँ, मैं बस वही बात सोच रहा था :) खासकर उत्तल या अवतल कार्यों के लिए, इस तरह की विधि हमेशा रैखिक इंटरपोलेशन से बेहतर प्रदर्शन करेगी। – cjh

+0

@cjh, आपकी मदद के लिए भी धन्यवाद। आपका मतलब "निश्चित लंबाई का खंड" क्या है? क्या आपका मतलब है कि आपका समाधान एक्स को एक ही लंबाई में फैलता है? – Cassie

0

यह इस सवाल का सटीक उत्तर नहीं है, लेकिन जब से मैं यहाँ किसी खोज के आधार पहुंचे, मैं कैसे बनाने के लिए से संबंधित सवाल का जवाब देने (फिट नहीं) करना चाहते हैं एक टुकड़ावर्त रैखिक फ़ंक्शन जिसका उद्देश्य स्कैटर प्लॉट में अंतराल डेटा के माध्य (या औसत, या कुछ अन्य फ़ंक्शन) का प्रतिनिधित्व करना है।

सबसे पहले, एक संबंधित लेकिन अधिक परिष्कृत विकल्प प्रतिगमन का उपयोग कर, जो स्पष्ट रूप से some MATLAB code listed on the wikipedia page है, Multivariate adaptive regression splines है।

समाधान यहाँ सिर्फ कुछ बनती एक्स और वाई डेटा मैं लंबाई 0 के अंतराल के साथ काम किया था से अधिक मतलब की गणना करने के

function [x, y] = intervalAggregate(Xdata, Ydata, aggFun, intStep, intOverlap) 
% intOverlap in [0, 1); 0 for no overlap of intervals, etc. 
% intStep this is the size of the interval being aggregated. 

minX = min(Xdata); 
maxX = max(Xdata); 

minY = min(Ydata); 
maxY = max(Ydata); 

intInc = intOverlap*intStep; %How far we advance each iteraction. 
if intOverlap <= 0 
    intInc = intStep; 
end 
nInt = ceil((maxX-minX)/intInc); %Number of aggregations 

parfor i = 1:nInt 
    xStart = minX + (i-1)*intInc; 
    xEnd = xStart + intStep; 
    intervalIndices = find((Xdata >= xStart) & (Xdata <= xEnd)); 
    x(i) = aggFun(Xdata(intervalIndices)); 
    y(i) = aggFun(Ydata(intervalIndices)); 
end 

उदाहरण के लिए, अंक प्राप्त करने के लिए ओवरलैपिंग अंतराल पर मतलब की गणना करने के लिए है।1 होने एक दूसरे को (देखें बिखराव छवि) के साथ लगभग 1/3 ओवरलैप:

Scatter plot example for Xdat and Ydat

[एक्स, वाई] = intervalAggregate (Xdat, Ydat, @mean, 0.1, 0.333)

एक्स =

कॉलम 1 के माध्यम से 8

0.0552 0.0868 0.1170 0.1475 0.1844 0.2173 0.2498 0.2834 

कॉलम 9 15

0.3182 0.3561 0.3875 0.4178 0.4494 0.4671 0.4822 

y =

कॉलम के माध्यम से 1 के माध्यम से 8

0.9992 0.9983 0.9971 0.9955 0.9927 0.9905 0.9876 0.9846 

कॉलम 9 के माध्यम से 15

0.9803 0.9750 0.9707 0.9653 0.9598 0.9560 0.9537 

हम देखते हैं कि एक्स बढ़ जाती है के रूप में, y मामूली कमी कम करता है y। वहां से, रेखा खंडों को आकर्षित करने और/या किसी अन्य प्रकार की चिकनाई करने के लिए पर्याप्त आसान है।

(ध्यान दें कि मैं इस समाधान vectorize का प्रयास नहीं किया,। यदि Xdata क्रमबद्ध हो जाता है एक बहुत तेजी से संस्करण माना जा सकता है)