Skip to main content

Registration is now open for this year's LibreFest! Join us virtually the week of July 13.

Register here
Engineering LibreTexts

12.5: Curve Fitting

  • Page ID
    135908
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\dsum}{\displaystyle\sum\limits} \)

    \( \newcommand{\dint}{\displaystyle\int\limits} \)

    \( \newcommand{\dlim}{\displaystyle\lim\limits} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \(\newcommand{\longvect}{\overrightarrow}\)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)

    In the previous section, we discussed interpolation, where the goal is to estimate values between known data points and the curve usually passes through the given points. Curve fitting is a little different.

    In curve fitting, we use data points to find a mathematical model that describes the overall trend of the data. The fitted curve does not necessarily pass through every data point. Instead, it tries to represent the general relationship between the independent variable and the dependent variable.

    This is especially useful when working with experimental data. Real measurements often include noise, small errors, or natural variation. If we force a curve to pass through every data point, we may accidentally model the noise instead of the real trend. Curve fitting helps us find a smoother model that describes the behavior of the data.

    For example, suppose we measure temperature during the day. The measured data may not follow a perfectly smooth curve because of sensor noise, small environmental changes, or measurement error. A fitted curve can help us describe the overall temperature trend without treating every small fluctuation as important.

    Method

    Main Question

    Does the curve pass through every data point?

    Interpolation

    What value should we estimate between known points?

    Usually yes

    Curve fitting

    What overall relationship best describes the data?

    Not necessarily

     

    In experiments, measurements often contain noise or uncertainty. A best-fit curve helps us model the trend without being forced to follow every small measurement variation.

     

    Least Squares Idea

    Many curve fitting methods use least squares regression. The fitted curve is chosen to minimize the sum of the squared residual errors. A residual error is the difference between a measured value and the value predicted by the model.

     

    Fitting a Polynomial with polyfit

    MATLAB uses the polyfit function to find coefficients for a polynomial model that fits data. The general form is:

     

    coefficients = polyfit(xData, yData, degree);

     

    • xData: contains the known x values
    • yData: contains the known y values
    • degree: is the degree of the polynomial
    • coefficents: is a vector containing the polynomial coefficients

    The degree of the polynomial controls the shape of the fitted curve. For example:

    Polynomial degree Type of fit
    1 Linear fit
    2 Quadratic fit
    3 Cubic fit

    A first-degree polynomial creates a straight line. A second-degree polynomial creates a parabola. Higher-degree polynomials can create curves with more bends.

     

    4.2 Evaluating a Polynomial with polyval

    After we find the coefficients of the polynomial, we use polyval to evaluate the polynomial at selected x-values.

     

    yFit = polyval(coefficients, xValues);

     

    Example: Room Temperature Curve Fit

    Suppose we recorded the temperature in a room every hour from 2 PM to 6 PM. We want to fit a second-order polynomial to the data.

     

    Example \(\PageIndex{1}\)

    Fitting a polynomial of a second order to a data set.

    clc; clear; clf;
    
    % x is the time and y is the temperature in F
    x = 2:6;
    y = [65 67 72 71 63];
    
    
    % Fit a quadratic polynomial
    coefs = polyfit(x, y, 2);
    
    
    % Evaluate the polynomial at the original x values
    curve = polyval(coefs, x);
    
    
    % Plot both the data and fitted curve
    plot(x, y, 'ro', x, curve)
    xlabel('Time')
    ylabel('Temperature (F)')
    title('Temperature vs. Time')
    axis([1 7 60 75])
    grid on
    
    

     

    Solution

    clipboard_ec177d1e771646d54056eb763ca6fe757.png

     

     

     

    The example 1 works, but the curve looks jagged because we only evaluate it at a few x-values. To draw a smoother curve, we can create many x-values using linspace. 

     

    Example \(\PageIndex{2}\)

    Fitting a polynomial of a second order to a data set.

    clc; clear; clf;
     
    x = 2:6;
    y = [65 67 72 71 63];
     
    % Create more x-values for a smoother plot
    moreX = linspace(min(x), max(x), 100);
     
    % Fit a quadratic model
    coefs = polyfit(x, y, 2);
     
    % Evaluate the model at many x-values
    curve = polyval(coefs, moreX);
     
    plot(x, y, 'ro', moreX, curve)
    xlabel('Time')
    ylabel('Temperature (F)')
    title('Temperature vs. Time')
    axis([1 7 60 75])
    grid on
    

     

    Solution

    clipboard_e006f9d9e50f3ffcf933655657288a8e3.png

     

     

     

    Why linspace Helps

    polyfit finds the model. polyval evaluates the model. If you want a smooth-looking plotted curve, evaluate the model at many points, not just the original data points.

     

     

    Choosing the Polynomial Degree

    Choosing the degree of the polynomial is important. A polynomial degree that is too low may not capture the trend in the data. A polynomial degree that is too high may bend too much and follow the random noise in the data instead of the overall pattern.

    This problem is called overfitting. Overfitting happens when a model matches the given data very closely but does not describe the real relationship well.

     

    As a beginner rule:

    • Use a first-degree polynomial if the trend looks approximately linear.
    • Use a second-degree polynomial if the trend looks curved like a parabola.
    • Be careful with high-degree polynomials unless you have a good reason to use them.

     

    Example \(\PageIndex{3}\)

    Comparing different polynomial degrees.

    
    clc; clear; clf;
    
    
    time = 2:6;
    
    temp = [65 67 72 71 63];
    
    moreX = linspace(min(time), max(time), 100);
    
    
    
    for degree = 1:3
    
        coefs = polyfit(time, temp, degree);
        
        curve = polyval(coefs, moreX);
        
        subplot(1, 3, degree)
        
        plot(time, temp, 'ro', moreX, curve)
        
        xlabel('Time')
        
        ylabel('Temperature (F)')
        
        title(sprintf('Degree %d', degree))
        
        axis([1 7 60 75])
        
        grid on
    
    end
    
    

     

    Solution

    clipboard_ea43e56a379ca026edc7dccaca8b25ffa.png

     

     

     

    Caution

    Common Mistake

    Do not choose the highest degree just because it looks like it fits the points better. A useful model should make sense for the situation and should not behave wildly between data points.

     


    12.5: Curve Fitting is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by LibreTexts.

    • Was this article helpful?