Solving the Linear Regression Model using QR Decomposition (MATLAB) - matlab

Background : I want to implement a MATLAB algorithm that takes as input vectors x and y, solves the linear regression problem
associated with the data stored in x and y using a modified QR version and then to plot the graph of the linear function.
So first I wrote the modified QR algorithm :
function x=QRQ(A,b,n)
[Q1,R1]=qr(A);
c1=Q1'*b;
n=length(c1);
x=backward(R1,c1,n);
end
function x=backward(U,y,n)
x=zeros(n,1);
x(n)=y(n)/U(n,n);
for i=n -1 : -1 : 1
x(i)=(y(i)-U(i,i+1 : n)*x(i+1 : n))/U(i,i);
end
end
Then I wrote the algorithm for the linear regression :
function ysol = LinearReg(x,y)
A=[x ones(21,1)];
z=QRQ(A,y,2);
ysol=z(1)*x+z(2);
plot(x,y,'bo',x,ysol,'g-');
end
I tried to run this algorithm on the following data :
x=[0;0.25;0.5;0.75;1;1.25;1.5;1.75;2;2.25;2.5;2.75;3;3.25;3.5;3.75;4;4.25;4.5;4.75;5];
y=[4;3;7;7;1;4;4;6;7;7;2;6;6;1;1;4;9;3;5;2;7];
The full error message that I received is :
Index in position 2 exceeds array bounds (must not exceed 2).
Error in untitled>backward (line 12)
x(n)=y(n)/U(n,n);
Error in untitled>QRQ (line 8)
x=backward(R1,c1,n);
Error in untitled>LinearReg (line 20)
z=QRQ(A,y,2);
The line causing the error is x(n)=y(n)/U(n,n);
the only variable with an index in position 2 is U. Apparently U only has 2 columns, and n is a value >2, hence the error.
Using the debugger, I see that U is a 21x2 array, and n has a value of 21.
How can this MATLAB algorithm be fixed?

The U in your case is R1. Since the matrix A has rank two, R1 will only have two columns since A already only has two columns.
You then try to solve the system R1 * x = y using backward substitution with the index starting at n, but here you clearly have to start at 2.
(Keep in mind that R1 is an upper triangular matrix.)

Related

Having errors with userdefined functions

Doing homework and there's a question that's giving me trouble. The questions is:
a)create a function M-file called nmoles that requires two vector inputs—
the mass and molecular weight—and returns the corresponding number
of moles. Because you are providing vector input, it will be necessary
to use the meshgrid function in your calculations.
b) Test your function for the compounds shown in the following table, for
masses from 1 to 10 g:
In my function file, i've got:
function [ n ] = nmoles(m, MW)
%% Finds number of moles
m = (1:10); %% mass range
MW = [78.115 46.07 102.3]; %% Values from the table
n=m/MW; %%formula provided by the textbook
My main file only has:
nmoles(m,MW)
I'm getting an error: "Error using / Matrix dimensions must agree"
Also: Error in nmoles (line 10) n=m/MW;
I'm inexperienced with MATLAB and still learning syntax but I assume that my formula is incorrect and i'm using the wrong symbol to divide, though i'm not sure how to correct this. Also, how would i incorporate the meshgrid function into my anwser?
Here is how your function should probably look like:
function [ n ] = nmoles(m, MW)
% Finds number of moles
[mv,MWv] = meshgrid(m, MW); % extends m and MW to match all combinations.
n = mv./MWv; %formula provided by the textbook
end
And then your main script should be:
m = 1:10; % mass range
MW = [78.115 46.07 102.3]; % Values from the table
nmoles(m, MW)
You had 3 mistakes:
If you get m and MW as input to the function, your not suppose to define them within it.
Because you want the number of moles for each combination of mass and molar weight, you use meshgrid.
When you want to perform an elementwise division or multiplication on 2 arrays, put a . before the / or *. In MATLAB everything is a matrix by default, and so this operations are interpreted as matrix multiplication and division by default. If you want to do a regular division or multiplication you use .* and ./. This is true also for power (^ and .^).

Using Hindmarsh’s ODE solver LSODE in OCTAVE

I am learning OCTAVE, and I am trying to use LSODE ODE solver to integrate a version of FitzHugh–Nagumo model. My attempt looks like this:
time = linspace(0,200,1000);
u0 = rand(32,32);
v0 = rand(32,32);
vec_u0 = reshape(u0,[1,size(u0)(1)*size(u0)(2)]);
vec_v0 = reshape(v0,[1,size(v0)(1)*size(v0)(2)]);
vec_FHN0 = horzcat(vec_u0,vec_v0);
FHN = lsode("FHN_eq_vec", vec_FHN0, time);
FHN(end)
where all of the functions I have defined are in the repository I have set in GitHub - link. I have created a function that transform the two 2D fields of the FHN model into a row vector (as I understand from the examples here the LSODE integrator use row vector as input). I got this error message:
>> fhn_integrate_lsode
warning: non-integer range used as index
warning: called from
FHN_eq_vec at line 3 column 7
fhn_integrate_lsode at line 9 column 5
error: reshape: can't reshape 0x1 array to 1x1 array
error: called from
FHN_eq_vec at line 4 column 3
fhn_integrate_lsode at line 9 column 5
error: lsode: evaluation of user-supplied function failed
error: called from
fhn_integrate_lsode at line 9 column 5
error: lsode: inconsistent sizes for state and derivative vectors
error: called from
fhn_integrate_lsode at line 9 column 5
>>
Someone knows what could be the problem?
This has been answered at http://octave.1599824.n4.nabble.com/Using-Hindmarsh-s-ODE-solver-LSODE-in-OCTAVE-td4674210.html
However, looking quickly at your code, the system that you want to
solve is probably an ordinary differential equation stemming from a
pde space discretization, i.e.,
$dx(t)/dt = f(x,t) := -K x(t) + r(t)$
with K being a square matrix (Laplacian?!) and f a time-dependent
function of matching dimension. I expect that your system is stiff
(due to the negative Laplacian on the right-hand side) and that you
are happy with errors in the order of 10^(-4). Thus you should adapt
the options of lsode:
lsode_options("integration method","stiff");
lsode_options("absolute tolerance",1e-4);
lsode_options("relative tolerance",1e-4);
Then
T = 0:1e-2:1; % time vector
K = sprandsym(32,1)+eye(32); % symmetric stiffness matrix
x0 = rand(32,1); % initial values
r = #(t) rand(32,1)*sin(t); % excitation vector
f = #(x,t) (-K*x+r(t)); % right-hand-side function
x=lsode (f, x0, T); % get solution from lsode
You should exploit any knowledge on the Jacobian df/dx since this will
speed up computations. It's trivial in the case of linear ODE:
f = {#(x,t) -K*x+r(t), #(x,t) -K}; % right-hand-side function.
On the other hand, if the system has an additional mass matrix
$M dx(t)/dt = -K x(t) + r(t)$
things might become more complicated. You probably want to use another
time stepper. Only if M has full rank then you could do
f = #(x,t) ( M\(-K*x+r(t)) ); % right-hand-side function
which is typically not very efficient.
Bye Sebastian

how can i obtain polynomial form of a .wav(audio) file in matlab

My teacher has given me a task of expressing a sound file(.wav) in polynomial form in MATLAB(curve fitting),.
I tried using polyfit() like this:-
a=wavread('filename');
x=linspace(0,1,239915);
p=polyfit(x,a,4);
display(p);
but I am getting error as
X and Y vectors must be the same size
Please help me.
Size of a is not 239915, it is for x we have taken these many samples, for line space, by the way, why do we need x for polyfit().
Thank you in advanced
Try this
a = wavread('filename')
x = linspace(0, 1, numel(a))';
p = polyfit(x,a,4);
display(p)
Note that I transpose linspace output as it returns a row vector where wavread returns a column vector, which is why you get the error message.

how to solve a very large overdetermined system of linear equations?

I am doing a project about image processing, and I need to solve the following set of equations:
Nx+Nz*( z(x+1,y)-z(x,y) )=0
Ny+Nz*( z(x+1,y)-z(x,y) )=0
and equations of the boundary (bottom and right side of the image):
Nx+Nz*( z(x,y)-z(x-1,y) )=0
Ny+Nz*( z(x,y)-z(x,y-1) )=0
where Nx,Ny,Nz are the surface normal vectors at the corresponding coordinates and are already determined. Now the problem is that since (x,y) are the coordinates on an image, which typically has a size of say x=300 and y=200. So there are 300x200=60000 unknowns. I rewrite the equations in the form of Mz=b, where M has a size of 120,000x60000, and both z and b are vectors of length 60000. When I solve it using the function in python scipy.linalg.lstsq, I run into memory errors.
I notice that M is very sparse as it only has two non-zero entries of either 1 or -1 in each row. However, I don't know how I can utilize it to solve the problem. Any ideas how I can solve it more efficiently in matlab or python?
In python I find a library that has the lsmr method (as mentioned by someone in the comment). Other than using this algorithm to solve the equation Mx=b, I want to know if I need to store M and B in sparse format as well. Now I just create a very large array with all entries zero in the beginning, then I use a for loop to loop over each pixel and change the corresponding entries to 1 or -1. Then I apply lsmr to solve Mx=b directly. Does it help if I construct the matrix M and b in any one of the sparse format? Right now most of the time spent is in solving Mx=b. Construct the array M,b and doing all previous tasks take negligible time compared to solving Mx=b.
thanks
edit: this is the python code I use to generate matrix M and b. They should be 'correct', but not sure if there are other better ways of rewriting the system of linear equations.
eq_no = 0
for pix in range(total_pix):
row, col = y[pix], x[pix]
if index_array[row,col] >= 0: # confirm (x,y) is inside boundary
# check x-direction
if index_array[row,col+1] >= 0: # (x+1,y) is inside boundary
M[eq_no,pix] = -1
M[eq_no,pix+1] = 1
b[eq_no,0] = -normal_array[row,col,0]/normal_array[row,col,2]
eq_no += 1
# check y-direction
next_pix = index_array[row+1,col]
if next_pix >= 0:
M[eq_no , pix] = -1
M[eq_no , next_pix] = 1
b[eq_no,0] = -normal_array[row,col,1]/normal_array[row,col,2]
eq_no += 1

matlab ARX parameter

I want to use ARX. X is a 1000X13 matrix (1000 sample with 13 features). I want to see the relationship of for example 1st and 2nd column of X. I don't know how to make input parameters right. What should be the size of [na nb nk] for my regression problem. Matlab documentation doesn't have much detail.
Here is my code:
data = iddata(X(:,1),[],1); %I have to make iddata object first.
Y = arx(data,[ [ones(size(X(:,1),2),size(X(:,1),2))] [ones(size(X(:,2),1),size(X(:,1),1))] [ones(size(X(:,1),2),size(X(:,1),1))] ])
Error is:
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
I tried to change the dimensions of [na nb nk], but every time, I got an error like:
Y = arx(data,[ [ones(size(X(:,1),2),size(X(:,1),2))] 1 [ones(size(X(:,1),2),size(X(:,1),1))] ])
Invalid ARX orders. Note that continuous-time ARX models are not supported.
Y = arx(data,[ 1 1 1])
Error using arx (line 77)
The model orders must be compatible with the input and output dimensions of the estimation data.