Need help to code the power Low fit using least square regression
Show older comments
I have the following data:
X = [0.17,0.17,0.5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3.5,3.5,4,4,4.5,6,6,10,10,10,12,15,18,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,37,49,72,72,72,96,96,120,192];
Y = [30,30,60,50,15,40,40,30,100,30,17,29,44,40,125,52,102,64,52,85,34,12.7,62.3,12.8,50,169,33.3,40,15,20,25,10.4,12.7,17.8,6.25,7.5,12.5,6.25,6.33,5.29,7.42,17.7,16.7,19.4,28.6,6.25,10.21,4.46,5.5,30,8.42,13.96,6.53,6.56,6.94,6.72,2.65,2.94,4.17,4.18];
I need a code to deriv the power law as Y= 14.82 X^(-0.39) (which is of the form y=b. x.^m) using constrained least squares. Could you please help me with the code how to get the b and m as 14.82 and -.39 respectively? I think we need to apply some optimization for getting the exact values.
Any help will be much appreciated.
Accepted Answer
More Answers (2)
Michael Madelaire
on 2 Jan 2019
Here is my attempt. But it does not use a non linear fit as the suggestion above.
Instead I fit the log.
%% Init
clear all; close all; clc;
%% Data
X = [0.17,0.17,0.5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3.5,3.5,4,4,4.5,6,6,10,10,10,12,15,18,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,37,49,72,72,72,96,96,120,192];
Y = [30,30,60,50,15,40,40,30,100,30,17,29,44,40,125,52,102,64,52,85,34,12.7,62.3,12.8,50,169,33.3,40,15,20,25,10.4,12.7,17.8,6.25,7.5,12.5,6.25,6.33,5.29,7.42,17.7,16.7,19.4,28.6,6.25,10.21,4.46,5.5,30,8.42,13.96,6.53,6.56,6.94,6.72,2.65,2.94,4.17,4.18];
y_log = log(Y);
x_log = log(X);
%% Plot data
figure;
subplot(2,1,1);
plot(X, Y, '.', 'MarkerSize', 10);
grid on;
title('True data');
subplot(2,1,2);
plot(x_log, y_log, '.', 'MarkerSize', 10);
grid on;
title('Log of data');
%% build data kernel
G = ones(length(X),2);
G(:,2) = x_log;
%% Solve LSQ
model = G\y_log';
%% Extract model coefficients
b = exp(model(1));
m = exp(model(2));
fprintf('\nThe fit to your function is Y=%.3f*X^{%.3f}\n',b,m)
%% Predict
x_pred = -2:0.01:6;
G_pred = ones(length(x_pred), 2);
G_pred(:, 2) = x_pred;
y_pred = G_pred*model;
%% Plot fit
figure;
subplot(2,1,1);
plot(X, Y, '.', 'MarkerSize', 10);
hold on;
plot(exp(x_pred), exp(y_pred));
grid on;
title('True data - x truncated at 200');
legend('Data', 'Fit');
xlim([0,200]);
subplot(2,1,2);
plot(x_log, y_log, '.', 'MarkerSize', 10);
hold on;
plot(x_pred, y_pred);
grid on;
title('Log of data');
legend('Data', 'Fit');
%% Residuals
G = ones(length(X),2);
G(:,2) = x_log;
r_my_model = exp(y_log-G*model);
your_model = [14.82; -.39];
r_your_model = Y-your_model(1)*X.^your_model(2);
figure;
subplot(2,1,1);
histogram(r_my_model, 'binWidth', 0.5);
grid on;
title('My model - residuals');
subplot(2,1,2);
histogram(r_your_model, 'binWidth', 0.5);
grid on;
title('Your model - residuals');


Torsten
on 2 Jan 2019
0 votes
function main
X = [0.17,0.17,0.5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3.5,3.5,4,4,4.5,6,6,10,10,10,12,15,18,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,37,49,72,72,72,96,96,120,192];
Y = [30,30,60,50,15,40,40,30,100,30,17,29,44,40,125,52,102,64,52,85,34,12.7,62.3,12.8,50,169,33.3,40,15,20,25,10.4,12.7,17.8,6.25,7.5,12.5,6.25,6.33,5.29,7.42,17.7,16.7,19.4,28.6,6.25,10.21,4.46,5.5,30,8.42,13.96,6.53,6.56,6.94,6.72,2.65,2.94,4.17,4.18];
% Fit data
p0 = [14.82,-0.39];
p = fmincon(@(p)fun(p,X,Y),[],[],[],[],[],[],@(p)nonlcon(p,X,Y))
end
function obj = fun(p,X,Y)
obj = sum((p(1)*X.^p(2) - Y).^2);
end
function [c,ceq] = nonlcon(p,X,Y)
c = p(1)*X.^p(2) - Y;
ceq = [];
end
12 Comments
Geethu T H
on 2 Jan 2019
Thanks Torsten.
But, I think you are didnt understand the problem. And dont use b=14.82, m=-.39 directly as you used in the program(ie. p0 = [14.82,-0.39]). Because our aim is to code for getting b=14.82 and m=-.39.
Let me make it more clear.
I have some X and Y values as:
X=[0.17,0.17,0.5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3.5,3.5,4,4,4.5,6,6,10,10,10,12,15,18,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,37,49,72,72,72,96,96,120,192];
Y = [30,30,60,50,15,40,40,30,100,30,17,29,44,40,125,52,102,64,52,85,34,12.7,62.3,12.8,50,169,33.3,40,15,20,25,10.4,12.7,17.8,6.25,7.5,12.5,6.25,6.33,5.29,7.42,17.7,16.7,19.4,28.6,6.25,10.21,4.46,5.5,30,8.42,13.96,6.53,6.56,6.94,6.72,2.65,2.94,4.17,4.18];
I want to fit the data in the form of
.
And I know that, b=14.82, m=-.39. But I dont know how to get b=14.82, m=-.39 from the above X and Y. So I need a code to get this b and m.
Image Analyst
on 2 Jan 2019
'fmincon' requires Optimization Toolbox.
Since I don't have that toolbox, what is the p you got?
p(1) = his "b" variable.
p(2) = his "m" variable.
Geethu T H
on 2 Jan 2019
Actually I dont know how to get optimised solution of b and m. I need help in that only. I know X-Y value and will get Y = 14.82 X^(-0.39). But I dont know how can I get it and need a code for the same. ie, after running the code(which may contain the concept of regression and optimization), I need to get b=14.82 and m= -.39 as output.
Torsten
on 2 Jan 2019
What do you get for p if you run my code ? Isn't it p(1) = 14.82 and p(2) = -0.39 approximately ?
Geethu T H
on 2 Jan 2019
It is p(1) = 14.82 and p(2) = -0.39. But you are using p0 = [14.82,-0.39] in your code. This is the required solution which we need to find by applying some regression and optimization(iterate for n times for getting optimised solution. I have only this much idea). so we cannot use p0 = [14.82,-0.39].
Image Analyst
on 2 Jan 2019
It looks like you're doing a fit through ALL the data. Geethu doesn't want that. He wants a fit through only two points. The two bottom most ones. And those two points are the ones such that a line drawn through them is below all other points.
So first you need to draw lines between every pair of points to determine which pair is on a line below all other points. Then, and only then, get the b and m from only that one pair of points.
Torsten
on 2 Jan 2019
No. As clearly stated, Geethu wants to impose the constraint that
Yi > k1*Xi^k2
for all data points (Xi,Yi).
I define this constraint in the c-vector (c <= 0) , not in the ceq-vector (ceq = 0).
Image Analyst
on 2 Jan 2019
Geethu, can you run his code (I can't) and tell us what you get for p?
geethu th
on 4 Jan 2019
Torsten
on 4 Jan 2019
Use
p = fmincon(@(p)fun(p,X,Y),p0,[],[],[],[],[],[],@(p)nonlcon(p,X,Y));
Categories
Find more on Linear Predictive Coding in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

