MvNormal Error with Symmetric & Positive Semi-Definite Matrix - matlab

The summary of my problem is that I am trying to replicate the Matlab function:
mvnrnd(mu', sigma, 200)
into Julia using:
rand( MvNormal(mu, sigma), 200)'
and the result is a 200 x 7 matrix, essentially generating 200 random return time series data.
Matlab works, Julia doesn't.
My input matrices are:
mu = [0.15; 0.03; 0.06; 0.04; 0.1; 0.02; 0.12]
sigma = [0.0035 -0.0038 0.0020 0.0017 -0.0006 -0.0028 0.0009;
-0.0038 0.0046 -0.0011 0.0001 0.0003 0.0054 -0.0024;
0.0020 -0.0011 0.0041 0.0068 -0.0004 0.0047 -0.0036;
0.0017 0.0001 0.0068 0.0125 0.0002 0.0109 -0.0078;
-0.0006 0.0003 -0.0004 0.0002 0.0025 -0.0004 -0.0007;
-0.0028 0.0054 0.0047 0.0109 -0.0004 0.0159 -0.0093;
0.0009 -0.0024 -0.0036 -0.0078 -0.0007 -0.0093 0.0061]
Using Distributions.jl, running the line:
MvNormal(sigma)
Produces the error:
ERROR: LoadError: Base.LinAlg.PosDefException(4)
The matrix sigma is symmetrical but only positive semi-definite:
issym(sigma) #symmetrical
> true
isposdef(sigma) #positive definite
> false
using LinearOperators
check_positive_definite(sigma) #check for positive (semi-)definite
> true
Matlab produces the same results for these tests however Matlab is able to generate the 200x7 random return sample matrix.
Could someone advise as to what I could do to get it working in Julia? Or where the issue lies?
Thanks.

The issue is that the covariance matrix is indefinite. See
julia> eigvals(sigma)
7-element Array{Float64,1}:
-3.52259e-5
-2.42008e-5
2.35508e-7
7.08269e-5
0.00290538
0.0118957
0.0343873
so it is not a covariance matrix. This might have happened because of rounding so if you have access to unrounded data you can try that instead. I just tried and I also got an error in Matlab. However, in contrast to Julia, Matlab does allow the matrix to be positive semidefinite.
A way to make this work is to add a diagonal matrix to the original matrix and then input that to MvNormal. I.e.
julia> MvNormal(randn(7), sigma - minimum(eigvals(Symmetric(sigma)))*I)
Distributions.MvNormal{PDMats.PDMat{Float64,Array{Float64,2}},Array{Float64,1}}(
dim: 7
μ: [0.889004,-0.768551,1.78569,0.130445,0.589029,0.529418,-0.258474]
Σ: 7x7 Array{Float64,2}:
0.00353523 -0.0038 0.002 0.0017 -0.0006 -0.0028 0.0009
-0.0038 0.00463523 -0.0011 0.0001 0.0003 0.0054 -0.0024
0.002 -0.0011 0.00413523 0.0068 -0.0004 0.0047 -0.0036
0.0017 0.0001 0.0068 0.0125352 0.0002 0.0109 -0.0078
-0.0006 0.0003 -0.0004 0.0002 0.00253523 -0.0004 -0.0007
-0.0028 0.0054 0.0047 0.0109 -0.0004 0.0159352 -0.0093
0.0009 -0.0024 -0.0036 -0.0078 -0.0007 -0.0093 0.00613523
)
The "covariance" matrix is of course not the same anymore, but it is very close.

Related

compute inverse fft manually

I am trying to compute the inverse FFT of a fft-output manually. I am using the following script, which first uses fft to compute the FFT of a data set. I then try to find the inverse FFT manually, but it doesn't resemble the result I get from ifft.
Can you spot my error? I am merely using the standard inverse formula of the FFT presented here, https://en.wikipedia.org/wiki/Fast_Fourier_transform#Definition_and_speed
data = [
-0.0005
-0.0004
-0.0003
-0.0002
-0.0001
-0.0000
0.0001
0.0001
0.0001
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0003
0.0004
0.0005
0.0006
0.0007
0.0009
0.0010
0.0011
0.0011
0.0012
0.0011
0.0011
0.0011
0.0010
0.0011];
delta = 0.0125;
fs = 1/delta;
x = (0:1:length(data)-1)/fs;
X=fft(data);
%find fft
N=length(data);
ws = 2*pi/N;
wnorm = -pi:ws:pi;
wnorm = wnorm(1:length(x));
w = wnorm*fs;
figure(2)
plot(w/(2*pi),abs(fftshift(X)))
%find inverse fft manually
for m=1:length(X)
for k=1:length(data)
X_real(m) = X(k)*exp(i*k*ws*(m-1));
end
end
figure(3)
plot(1:length(data), abs(X_real), 1:length(data), ifft(X))
Please, change your for loop like below.
for m=1:length(X)
for k=1:length(data)
temp(k) = X(k)*exp(i*(m-1)*ws*(k-1));
end
X_real(m)=(1/N)*sum(temp);
end
figure(3)
plot(1:length(data), real(X_real))
You can find the equation of ifft in matlab, here.
You missed two things.
One thing is normalization, another is summing.

inverse fft with matlab not working

I am trying to do an inverse FFT in Matlab, but I can't seem to get the inverse working correctly. Here is my code:
data = [-0.0005
-0.0004
-0.0003
-0.0002
-0.0001
-0.0000
0.0001
0.0001
0.0001
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0002
0.0003
0.0004
0.0005
0.0006
0.0007
0.0009
0.0010
0.0011
0.0011
0.0012
0.0011
0.0011
0.0011
0.0010 ];
%plot data
figure(1)
plot(data)
%FFT
N = 100;
X = fft(data, N);
F = [-N/2:N/2-1]/N;
F = F/0.0125;
X = fftshift(X);
figure(2)
plot(F, abs( X ) )
%inverse FFT
y = ifft(X);
figure(3)
plot(F,y)
Figure 1 and 3 should be identical, but are not in any way. I made sure not to take ifft of the absolute value of fft, so it's not clear to me what is wrong.
Since you shifted the spectrum using fftshift, you have to "unshift" the spectrum prior to taking the inverse Fourier transform
y = ifft(fftshift(X));

polyfit/polyval with log scale through scatter points in matlab

I have a scatter plot with both x and y axes in log scale in Matlab. How do I add a line of best fit on the log scale?
Thanks!
x = [0.0090 0.0000 0.0001 0.0000 0.0001 0.0000 0.0097 0.0016 0.0006 0.0000 0.0016 0.0013 0.0023];
y = [0.0085 0.0001 0.0013 0.0006 0.0005 0.0006 0.0018 0.0076 0.0015 0.0001 0.0039 0.0015 0.0024];
scatter(x,y)
set(gca,'YScale','log');
set(gca,'XScale','log');
hold on
p = polyfit(log(x),log(y),1);
f = polyval(p,x);
plot(x,f,'Color',[0.7500 0.7500 0.7500],'linewidth',2)
When searching for the best fit, you need to use the original data x and y and not their logs. The log scale serves only for representation of the result.
Before use the polyval you need to sort the x. It does not matter when using normal axes, but can look strange with log-axes, because of the wrong sequence.
Here is the plot:
The code:
x = [0.0090 0.0000 0.0001 0.0000 0.0001 0.0000 0.0097 0.0016 0.0006 0.0000 0.0016 0.0013 0.0023];
y = [0.0085 0.0001 0.0013 0.0006 0.0005 0.0006 0.0018 0.0076 0.0015 0.0001 0.0039 0.0015 0.0024];
scatter(x,y);
set(gca,'YScale','log');
set(gca,'XScale','log');
hold on;
x_sort = sort(x);
p = polyfit(x,y,1);
f = polyval(p,x_sort);
plot(x_sort,f,'Color',[0.7500 0.7500 0.7500],'linewidth',2);
Is it what you wanted?

Dimension reduction using PCA in Matlab

I am trying to classify vehicles in matlab. I need to reduce the dimensionality of the features to eliminate redundancy. Am using pca for this. Unfortunately, the the pca function is not returning the expected results. The output seems truncated and i don't understand why.
summary of this is as follows:
Components_matrix = [Areas_vector MajorAxisLengths_vector MinorAxisLengths_vector Perimeters_vector...
EquivDiameters_vector Extents_vector Orientations_vector Soliditys_vector]
The output is:
Components_matrix =
1.0e+03 *
1.4000 0.1042 0.0220 0.3352 0.0422 0.0003 0.0222 0.0006
2.7690 0.0998 0.0437 0.3973 0.0594 0.0005 0.0234 0.0007
1.7560 0.0853 0.0317 0.2610 0.0473 0.0005 0.0236 0.0008
1.0870 0.0920 0.0258 0.3939 0.0372 0.0003 0.0157 0.0005
0.7270 0.0583 0.0233 0.2451 0.0304 0.0004 0.0093 0.0006
1.2380 0.0624 0.0317 0.2436 0.0397 0.0004 0.0106 0.0007
Then i used the pca function as follows:
[COEFF, SCORE, LATENT] = pca(Components_matrix)
The displayed results are:
COEFF =
0.9984 -0.0533 -0.0057 -0.0177 0.0045
0.0162 0.1810 0.8788 0.0695 -0.3537
0.0099 -0.0218 -0.2809 0.8034 -0.2036
0.0514 0.9817 -0.1739 -0.0016 0.0468
0.0138 -0.0018 0.0616 0.4276 -0.3585
0.0001 -0.0008 -0.0025 0.0215 0.0210
0.0069 0.0158 0.3388 0.4070 0.8380
0.0001 -0.0011 0.0022 0.0198 0.0016
SCORE =
1.0e+03 *
-0.0946 0.0312 0.0184 -0.0014 -0.0009
1.2758 0.0179 -0.0086 -0.0008 0.0001
0.2569 -0.0642 0.0107 0.0016 0.0012
-0.4043 0.1031 -0.0043 0.0015 0.0003
-0.7721 -0.0299 -0.0079 -0.0017 0.0012
-0.2617 -0.0580 -0.0083 0.0008 -0.0020
LATENT =
1.0e+05 *
5.0614
0.0406
0.0014
0.0000
0.0000
I expected for instance COEFF and LATENT to be 8x8 and 8x1 matrices respectively. But that is not what i get. Why is this so and how can the situation be rectified. Kindly help.
Your usage of pca() and Matlab's output are correct. The issue is that you have more dimensions than you have samples, i.e., you only have 6 vehicles but 8 variables. If you have N samples and N or greater variables, the number of principal components there are is only N-1, because further components would not be unique. So COEFF are the eigenvectors of the covariance matrix of the input, and SCORE(:,1) is the first principal component, SCORE(:,2) is the second, etc., of which there are only N-1=5 in total, and LATENT are the eigenvalues of the covariance matrix, or the amount of variance explained by each successive principal component, of which there are, again, only N-1=5.
There is a more detailed discussion of this here.

Finding local minima and local maxima [duplicate]

This question already has answers here:
Find local maximum value in the vector
(4 answers)
Closed 8 years ago.
I would like to find local minima and local maxima of a given vector. Let's assume that the given vector is as follow:
speed =
0.0002
0.0008
0.0014
0.0027
0.0037
0.0047
0.0054
0.0053
0.0053
0.0058
0.0060
0.0063
0.0062
0.0065
0.0062
0.0061
0.0060
0.0057
0.0062
0.0057
0.0053
0.0050
0.0047
0.0065
0.0049
0.0048
0.0033
0.0033
0.0041
0.0049
0.0063
0.0075
0.0085
0.0105
0.0108
0.0109
0.0105
0.0105
0.0099
0.0098
0.0099
0.0099
0.0105
0.0103
0.0112
0.0108
0.0088
0.0079
0.0066
0.0055
0.0058
0.0049
0.0049
0.0055
0.0060
0.0051
0.0055
0.0060
0.0053
0.0047
0.0058
0.0050
0.0044
0.0033
0.0022
0.0008
0.0015
0.0010
0.0011
0.0024
0.0028
0.0024
0.0016
0.0009
0.0009
0.0009
0.0015
0.0015
0.0025
0.0031
0.0030
0.0042
0.0051
0.0060
0.0065
0.0054
0.0012
0.0043
0.0059
0.0070
0.0078
0.0076
0.0082
0.0087
0.0088
0.0095
0.0101
0.0100
0.0110
0.0103
0.0111
0.0120
0.0118
0.0116
0.0115
0.0121
0.0120
0.0145
0.0107
0.0119
0.0110
0.0116
0.0102
0.0086
0.0076
0.0071
0.0055
0.0066
0.0063
0.0077
0.0052
0.0059
0.0061
0.0036
0.0047
0.0053
0.0027
0.0020
0.0011
0.0041
0.0034
0.0034
0.0019
0.0022
0.0008
0.0001
0.0007
0.0009
0.0010
0.0010
0.0001
0.0007
0.0014
0.0016
0.0016
0.0013
0.0008
0.0008
0.0005
0.0004
0.0002
0.0001
0.0004
0.0005
0.0006
0.0005
0.0006
0.0006
0.0004
0.0002
0.0000
0.0001
0.0001
0.0002
0.0003
0.0004
0.0004
0.0005
0.0007
0.0008
0.0007
0.0006
0.0005
0.0006
0.0006
0.0004
0.0002
0.0003
0.0006
0.0005
0.0005
0.0010
0.0012
0.0014
0.0020
0.0028
0.0039
0.0044
0.0061
0.0074
0.0082
0.0091
0.0102
0.0108
0.0110
0.0117
0.0128
0.0133
0.0148
0.0153
0.0155
0.0150
0.0146
0.0137
0.0130
0.0113
0.0110
0.0107
0.0112
0.0114
0.0113
0.0104
0.0101
0.0095
0.0088
0.0083
0.0076
0.0057
0.0047
0.0043
0.0046
0.0053
0.0063
0.0078
0.0070
0.0062
0.0053
0.0051
0.0055
0.0048
0.0053
0.0052
0.0055
0.0065
0.0075
0.0078
0.0081
0.0067
0.0044
0.0061
0.0047
0.0032
0.0033
0.0028
0.0019
0.0007
0.0017
0.0016
0.0025
0.0034
0.0037
0.0044
0.0039
0.0037
0.0029
0.0030
0.0025
0.0022
0.0025
0.0027
0.0028
0.0031
0.0029
0.0025
0.0025
0.0025
0.0024
0.0022
0.0021
0.0019
0.0020
0.0020
0.0016
0.0016
0.0015
0.0013
0.0011
0.0011
0.0010
0.0009
0.0008
0.0006
0.0005
0.0004
0.0002
0.0000
0.0002
0.0003
0.0004
0.0006
0.0005
0.0004
0.0003
0.0004
0.0003
0.0003
0.0004
0.0006
0.0004
0.0004
when I polt this vector in Matlab using command plot(speed) then I have the following figure:
How could I find the maxima and minima's of the given vector? For example, in this above picture my aim is to find the three minimums/maximums that are shown in the picture.
I have lots of such a vectors that I want to write a code for all to find local minimas and maximas as well.
First of all you need to define what you count as extremum (maximum or minimum), i.e. which scale is considered appropriate, as your curve in reality has much more local maxima and minima than 3 or 4. Therefore looking for zero-crossings of the first derivative with diff will give you a lots of spurious micro-peaks. One option is to smooth it before. However, it might be easier to resort to a standard tool.
Try findpeaks from Signal Processing Toolbox.
There you can specify the scale with various parameters, such as 'MinPeakDistance', 'MinPeakHeight', 'Threshold' etc.