Linear regression (regress) discrepancy with polynomial fit (polyfit) - matlab

I have some data which comes from a linear function (y=mx+c) where m=4, c=1 (so: y=4x+1).
When I try to get back the coefficients using regress, I'm getting an R2<1 and a seemingly random m value:
x = [1 2 3 4]
y = [5 9 13 17]
[m,bint,r,rint,stats] = regress(y',x');
%{
>> R = stats(1) % Coefficient of determination
R =
1
>> m % Linear function coefficients
m =
4.333333333333333
%}
Whereas polyfit does this correctly:
P = polyfit(x,y,1);
%{
>> P(1)
ans =
4.000000000000000
>> P(2)
ans =
1.000000000000000
%}
Why is this happening?

The source of your problem is not following the documentation or regress which states that:
b = regress(y,X) returns a vector b of coefficient estimates for a multiple linear regression of the responses in vector y on the predictors in matrix X. The matrix X must include a column of ones.
If we include a column of ones in the 2nd input, we get the desired result:
x = [1 2 3 4].';
y = [5 9 13 17].';
[m,bint,r,rint,stats] = regress(y,[ones(size(x)) x]);
%{
Results:
m =
1.0000
4.0000
bint =
1.0000 1.0000
4.0000 4.0000
r =
1.0e-14 *
0.1776
0.1776
0.1776
0
rint =
1.0e-13 *
0.0178 0.0178
-0.2190 0.2545
-0.2190 0.2545
-0.2141 0.2141
stats =
1.0e+31 *
0.0000 1.6902 0.0000 0.0000
%}

Related

mvnrnd does not generates data with given average and correlation

let us suppose that we have following vector of averages
mu = [2,3]
and given correlation matrix
sigma = [1,1.5;1.5,3].
so we would have in matlab
>> mu = [2,3]
sigma = [1,1.5;1.5,3]
mu =
2 3
sigma =
1.0000 1.5000
1.5000 3.0000
now generate Multivariate normal random numbers with the given information
rng default % For reproducibility
r = mvnrnd(mu,sigma,100);
but mean of given matrix
>> mean(r)
ans =
2.1231 3.1217
and correlation matrix
>> corrcoef(r)
ans =
1.0000 0.9016
0.9016 1.0000
what is the reason of such difference? because of small sample size? thanks in advance

What is different between the implementation of deconvolution with fft and the deconv function in MATLAB?

I've got stuck in this code:
function [ y ] = mydeconv( c,x )
lx=length(x);
lc=length(c);
%lt=lx+lc;
c=[c zeros(1,lx)];
x=[x zeros(1,lc)];
y = ifft(real((fft(c)) ./(fft(x))));
end
and the result is:
mydeconv([1 2 3 3 2 1],[1 1 1])
ans =
Column 1
NaN + 0.000000000000000i
Column 2
NaN + NaNi
Column 3
NaN + NaNi
Column 4
NaN + 0.000000000000000i
Column 5
NaN + NaNi
Column 6
NaN + NaNi
Column 7
NaN + 0.000000000000000i
Column 8
NaN + NaNi
Column 9
NaN + NaNi
and the result of deconv function simply is:
deconv([1 2 3 3 2 1],[1 1 1])
ans =
1 1 1 1
In principle it should work, I can't understand what is wrong with it.
There are two problems in your code:
Firstly, you should take real part of the IFFT output, not of individual FFTs.
Secondly, you should protect against zero-divide-by-zero cases, which are resulting in NaN in your example.
You can implement both of the above, by modifying the line computing y as follows:
y = real(ifft((eps+fft(c)) ./ (eps+fft(x))));
Note that eps is a small positive number to protect against zero-divide-by-zero cases. With this, the output is:
disp(y)
% 1.0000 1.0000 1.0000 1.0000 0.0000 -0.0000 0.0000 0.0000 0.0000
Since the padded vector x has a length that is a multiple of the original, you end up with zeros in the frequency domain of fft(x). You can avoid this by choosing a different (longer) length when such zeros are observed:
function [ y ] = mydeconv( c,x )
lx=length(x);
lc=length(c);
if (lc >= lx)
lt = lc;
while (1)
xpadded = [x zeros(1,lt-length(x))];
Xf = fft(xpadded);
if (min(abs(Xf)) > 0)
break;
end
lt = lt + 1;
end
cpadded = [c zeros(1,lt-length(c))];
Cf = fft(cpadded);
y = real(ifft(Cf ./ Xf));
y = y(1:lc-lx+1);
else
y = [];
end
end

How to make the size(B,1) = size(A,1)?

I'm trying to Write a function that takes a matrix A as an input and returns the matrix B as the output. B has the same number of rows as A.
Each element of the first column of B contains the mean of the corresponding row of A.
The second column contains the median values.
While the third column has the minimums.
Each element of the fourth column of B is equal to the maximum value of given row of A.
function B = simple_stats (A)
n = size(A,1);
x = A(1,:);
y = median(A);
z = min(A);
r = max(A);
B = [x.',y.',z.',r.'];
B(1:n,:); % Here I have a problem and B has not the same number of rows as A.
end
You need to specify that you want to compute the median, mean, min and max across the second dimension of your matrix A. By default, all of these functions operate along the first dimension (down the columns). All of these functions take a dim parameter which is used to specify the dimension along which to apply the operation.
A = randi(10, 5, 3);
%// 8 3 3
%// 8 2 1
%// 6 3 5
%// 2 9 1
%// 6 1 9
B = [mean(A, 2), median(A, 2), min(A, [], 2), max(A, [], 2)];
%// 4.6667 3.0000 3.0000 8.0000
%// 3.6667 2.0000 1.0000 8.0000
%// 4.6667 5.0000 3.0000 6.0000
%// 4.0000 2.0000 1.0000 9.0000
%// 5.3333 6.0000 1.0000 9.0000

Checking which rows switched given an original and an altered matrix in Matlab

I've been trying to wrap my head around this for awhile and was hoping to get some insight.
Suppose you have matrix A, then you switched rows until you ended up with matrix B;
A = [1 3 1;
3 2 1;
2 3 1;];
B = [3 2 1;
1 3 1;
2 3 1;];
invA =
0.0000 -1.0000 1.0000
-1.0000 -1.0000 2.0000
3.0000 5.0000 -7.0000
invB =
-1.0000 0.0000 1.0000
-1.0000 -1.0000 2.0000
5.0000 3.0000 -7.0000
How would I document these row switches?. I'm ultimately trying to alter the inverse of B to match with the inverse of A. My conclusion was that given 2 rows switched (aka between rows 1 and 2), the end result of the inverse would be identical except for switching the columns of (1 and 2) of the inverse B.
This is quite a basic algebra question.
You can write your matrix B as a product of a permutation matrix P and A:
B = PA;
(in your example: P = [0 1 0;1 0 0;0 0 1];).
Now you can invert B:
inv( B ) = inv( PA )
The inverse of a product is
= inv(A) * inv(P)
Since matrix P is a permutation matrix: inv(P) = P.'. Thus
= inv(A) * P.'
That is, inv(B) = inv(A) * P.' which means that you apply the permutation P to the columns of inv(A).
Note that a permutation P can represent more than a single switch between rows, moreover, permutations can be multiplies to account for repeated switching of rows.
An important comment: I use inv in this answer to denote the inverse of a matrix. However, when running Matlab and numerically inverting matrices it is un-recommended to use inv function explicitly.

Create vectors associated with each entry of an array and save them in a new matrix

Say i have a matrix like A = [1 2; 3 4], and that i need to create 4, vectors each one associated to one entrance of the matrix, such that the first one goes from -1..1, and second from -2..2, and so forth. Wath i try was
for j=1:2
for k=1:2
W=linspace(-A(j,k),A(j,k),4)
end
end
the problem with that line is that it not save the data.
Also i need that to create a new matrix, such that every row be one of the vectors that i mentioned.
I know that on octave i can do
W=linspace(-A,A,4)
but in MATLAB it doesn't work
If you want 4 values evenly distributed between A(k) and A(k), then you can use an anonymous function in combination with linspace this way:
fun = #(x) linspace(-A(x), A(x), 4)
b = fun(1:numel(A))
b =
-1.00000 -0.33333 0.33333 1.00000
-3.00000 -1.00000 1.00000 3.00000
-2.00000 -0.66667 0.66667 2.00000
-4.00000 -1.33333 1.33333 4.00000
Assuming you want [-1 0 1], [-2 -1 0 1 2] etc, then I suggest using arrayfun like this:
A = [1 2;3 4];
b = arrayfun(#(n) -A(n):A(n), 1:numel(A), 'UniformOutput',0)
b =
{
[1,1] =
-1 0 1
[1,2] =
-3 -2 -1 0 1 2 3
[1,3] =
-2 -1 0 1 2
[1,4] =
-4 -3 -2 -1 0 1 2 3 4
Your approach didn't work because you're overwriting W everytime you loop. The following works:
V = zeros(numel(A),4);
for k=1:numel(A)
W(k,:) = linspace(-A(k),A(k),4);
end
The reason why I only use one index for A is because you may use linear indexing in MATLAB. Remember to allocate memory before you assign values to a matrix inside a loop. "Growing" matrices are very slow.
You can do it like that
W = zeros(4,4);
a = reshape(A, 1, 4);
for i=1:4
W(i,:) = linspace(-a(i), a(i), 4);
end
and you obtain
W =
-1.0000 -0.3333 0.3333 1.0000
-3.0000 -1.0000 1.0000 3.0000
-2.0000 -0.6667 0.6667 2.0000
-4.0000 -1.3333 1.3333 4.0000
If you want to generate a fixed number of values (say 4) for each entry of A, you can achieve it in one line:
>> bsxfun(#times, linspace(-1,1,4), A(:))
ans =
-1.0000 -0.3333 0.3333 1.0000
-3.0000 -1.0000 1.0000 3.0000
-2.0000 -0.6667 0.6667 2.0000
-4.0000 -1.3333 1.3333 4.0000