MATLAB loop refactoring - matlab

I'm curious to know if there is a better way to express the following loop:
To = 1;
fileName = "fourier/signal.txt";
spectrum_left(abs(spectrum_left) < 1e-3) = 0+0i;
Ts = 1 / Fs;
t = 0:Ts:To-Ts;
signal = load(fileName, "-ascii");
Ns = numel(signal);
Fs = Ns / To;
fr = f(abs(spectrum_left) > 0)
a = abs(spectrum_left(abs(spectrum_left) > 0))
p = angle(spectrum_left(abs(spectrum_left) > 0))
signal_synth = 0;
len = length(a);
for i=1:len
a_i = a(i);
p_i = p(i);
f_i = fr(i);
s_i = a_i * cos(2*pi*f_i*t + p_i)
signal_synth = signal_synth + s_i;
end
Any suggestions are greatly appreciated. And Happy New Year!

In MATLAB, element-wise operators, that preceded by the period character (.), can be applied on arrays. I used (:) operator to convert the vectors to column vectors. Note that t is a row vector, when it is combined with column vectors the result will be a matrix that is formed by implicit expansion. In order to sum up the values the function sum is used that by default sums along the first dimension of the matrix and the result will be a row vector with the same size as t.
signal_synth = sum(a(:) .* cos(2 * pi * f(:) .* t + p(:)));
A more compact form using matrix multiplication:
signal_synth = a(:).' * cos(2 * pi * f(:) .* t + p(:));

Related

expectation maximization algorithm matlab out of memory error

I am implementing Expectation Maximization algorithm in matlab. Algorithm is operating on 214096 x 2 data matrix and While computing probabilities, there is multiplication of ( 214096 x 2 ) * (2 x 2) * ( 2 x 214096 ) matrices, which is resulting in error of out of memory in matlab. Is there a way to fix this problem?
Equation
Matlab Code:
enter image description here D = size(X,2); % dimension
N = size(X,1); % number of samples
K = 4; % number of Gaussian Mixture components ( Also number of clusters )
% Initialization
p = [0.2, 0.3, 0.2, 0.3]; % arbitrary pi, probabilities of clusters, apriori probability of cluster
[idx,mu] = kmeans(X,K); % initial means of the components, theta is mu and variance
% compute the covariance of the components
sigma = zeros(D,D,K);
for k = 1:K
tempmat = X(idx==k,:);
sigma(:,:,k) = cov(tempmat); % Sigma j
sigma_det(k) = det(sigma(:,:,k));
end
% calculate x-mu
for k=1: K
check=length( X(idx == k,1))
for lidx = 1: length( X(idx == k,1))
cidx = find( idx == k) ;
Xmu(cidx(lidx),:) = X(cidx(lidx),:) - mu(k,:); %( x-mu ) calculation on cluster level
end
end
% compute P(Cj|x; theta(t)), and take log to simplified calculation
%Eq 14.14 denominator
denom = 0;
for k=1:K
calc_sigma_1_2 = sigma_det(k)^(-1/2);
calc_x_mu = Xmu(idx == k,:);
calc_sigma_inv = inv(sigma(:,:,k));
calc_x_mu_tran = calc_x_mu.';
factor = calc_sigma_1_2 * exp (-1/2 * calc_x_mu * calc_sigma_inv * calc_x_mu_tran ) * p(k);
denom = denom + factor;
end
for k =1:K
calc_sigma_1_2 = sigma_det(k)^(-1/2);
calc_x_mu = Xmu(idx == k,:);
calc_sigma_inv = inv(sigma(:,:,k));
calc_x_mu_tran = calc_x_mu.';
factor = calc_sigma_1_2 * exp (-1/2 * calc_x_mu_tran * calc_sigma_inv * calc_x_mu ) * p(k);
pdf(k) = factor/denom;
end
%%%% Equation 14.14 ends
It seems that you tried to apply vector based equation by simply substituting vector for matrix, this is not how it works
(x - mu).' * Inv(sigma) * (x-mu)
is supposed to be mahalanobis norm of (x-mu), and you want to obtain this value per each row of matrix X, thus
(X - mu).' * Inv(sigma) =: A <- this is ok, this results in N x d matrix
and now you have to do point-wise multiplication of A with (X - mu), not a dot product, and finally sum over second axis (columns), this way you end up with N element vector, each containing a mahalanobis norm of corresponding row from X.

Implement those functions using matlab

I have an array of samples of ECG signals 1250x1 double let us called it "a".
I need to implement 4 functions which represent features are used to characterize the signals. Energy, 4th Power,Nonlinear Energy and Curve Length
I manged to implement Energy and 4th Power
for i=1:1250
energy = sum(a.^2,i);
power4th = sum(a.^4,i);
end
Which produce 2 array (energy and power4th)
How I can produce the other 2 array? let us called them NonLE and CL.
Use vectorization instead of for loops to solve all 4 of the formulas you need
% generate some random numbers
a = rand(1000,1);
Energy = sum(a.^2);
Power4 = sum(a.^4);
NLEnergy = sum(-a(3:end).*a(1:end-2) + a(2:end).^2);
CurveLength = sum(a(2:end) - a(1:end-1));
The . operator allows element by element operations in a vector.
Actually I think you can implement your formulas without using for loop. You can use matrix multiplication characteristic. Try the code below:
len = 1250;
a = randi(10, len, 1); % // You didn' t give your vector so I generated random a..
Energy = ones(1, len) * (a.^2);
power4th = ones(1, len) * (a.^4);
NonLE = ones(1, len - 2) * ( -a(3:end) .* a(1:end-2) ) + ones(1, len - 1) * ( a(2:end).^2 );
CL = ones(1, len - 1) * ( a(2:end) - a(1:end-1) );
You don't really need a for loop for 3 of them:
energy = sum(a.^2);
power_4th = sum(a.^4);
curve_length = sum(diff(a));
For the last one, you can do something like:
nonLE = 0;
for k = 3 : length(a)
nonLE = nonLE + a(k - 1)^2 - a(k) * a(k - 2);
end

I am trying to understand why the dimensions of this calculation are wrong?

I am solving the poisson equation and want to plot the error of the exact solution vs. number of grid points. my code is:
function [Ntot,err] = poisson(N)
nx = N; % Number of steps in space(x)
ny = N; % Number of steps in space(y)
Ntot = nx*ny;
niter = 1000; % Number of iterations
dx = 2/(nx-1); % Width of space step(x)
dy = 2/(ny-1); % Width of space step(y)
x = -1:dx:1; % Range of x(-1,1)
y = -1:dy:1; % Range of y(-1,1)
b = zeros(nx,ny);
dn = zeros(nx,ny);
% Initial Conditions
d = zeros(nx,ny);
u = zeros(nx,ny);
% Boundary conditions
d(:,1) = 0;
d(:,ny) = 0;
d(1,:) = 0;
d(nx,:) = 0;
% Source term
b(round(ny/4),round(nx/4)) = 3000;
b(round(ny*3/4),round(nx*3/4)) = -3000;
i = 2:nx-1;
j = 2:ny-1;
% 5-point difference (Explicit)
for it = 1:niter
dn = d;
d(i,j) = ((dy^2*(dn(i + 1,j) + dn(i - 1,j))) + (dx^2*(dn(i,j + 1) + dn(i,j - 1))) - (b(i,j)*dx^2*dy*2))/(2*(dx^2 + dy^2));
u(i,j) = 2*pi*pi*sin(pi*i).*sin(pi*j);
% Boundary conditions
d(:,1) = 0;
d(:,ny) = 0;
d(1,:) = 0;
d(nx,:) = 0;
end
%
%
% err = abs(u - d);
the error I get is:
Subscripted assignment dimension mismatch.
Error in poisson (line 39)
u(i,j) = 2*pi*pi*sin(pi*i).*sin(pi*j);
I am not sure why it is not calculating u at every grid point. I tried taking it out of the for loop but that did not help. Any ideas would be appreciated.
This is because i and j are both 1-by-(N-2) vectors, so u(i, j) is an (N-2)-by-(N-2) matrix. However, the expression 2*pi*pi*sin(pi*i).*sin(pi*j) is a 1-by-(N-2) vector.
The dimensions obviously don't match, hence the error.
I'm not sure, but I'm guessing that you meant to do the following:
u(i,j) = 2 * pi * pi * bsxfun(#times, sin(pi * i), sin(pi * j)');
Alternatively, you can use basic matrix multiplication to produce an (N-2)-by-(N-2) like so:
u(i, j) = 2 * pi * pi * sin(pi * i') * sin(pi * j); %// Note the transpose
P.S: it is recommended not to use "i" and "j" as names for variables.

Recomposing vector input to algorithm from matrix output

I've written some code to implement an algorithm that takes as input a vector q of real numbers, and returns as an output a complex matrix R. The Matlab code below produces a plot showing the input vector q and the output matrix R.
Given only the complex matrix output R, I would like to obtain the input vector q. Can I do this using least-squares optimization? Since there is a recursive running sum in the code (rs_r and rs_i), the calculation for a column of the output matrix is dependent on the calculation of the previous column.
Perhaps a non-linear optimization can be set up to recompose the input vector q from the output matrix R?
Looking at this in another way, I've used an algorithm to compute a matrix R. I want to run the algorithm "in reverse," to get the input vector q from the output matrix R.
If there is no way to recompose the starting values from the output, thereby treating the problem as a "black box," then perhaps the mathematics of the model itself can be used in the optimization? The program evaluates the following equation:
The Utilde(tau, omega) is the output matrix R. The tau (time) variable comprises the columns of the response matrix R, whereas the omega (frequency) variable comprises the rows of the response matrix R. The integration is performed as a recursive running sum from tau = 0 up to the current tau timestep.
Here are the plots created by the program posted below:
Here is the full program code:
N = 1001;
q = zeros(N, 1); % here is the input
q(1:200) = 55;
q(201:300) = 120;
q(301:400) = 70;
q(401:600) = 40;
q(601:800) = 100;
q(801:1001) = 70;
dt = 0.0042;
fs = 1 / dt;
wSize = 101;
Glim = 20;
ginv = 0;
R = get_response(N, q, dt, wSize, Glim, ginv); % R is output matrix
rows = wSize;
cols = N;
figure; plot(q); title('q value input as vector');
ylim([0 200]); xlim([0 1001])
figure; imagesc(abs(R)); title('Matrix output of algorithm')
colorbar
Here is the function that performs the calculation:
function response = get_response(N, Q, dt, wSize, Glim, ginv)
fs = 1 / dt;
Npad = wSize - 1;
N1 = wSize + Npad;
N2 = floor(N1 / 2 + 1);
f = (fs/2)*linspace(0,1,N2);
omega = 2 * pi .* f';
omegah = 2 * pi * f(end);
sigma2 = exp(-(0.23*Glim + 1.63));
sign = 1;
if(ginv == 1)
sign = -1;
end
ratio = omega ./ omegah;
rs_r = zeros(N2, 1);
rs_i = zeros(N2, 1);
termr = zeros(N2, 1);
termi = zeros(N2, 1);
termr_sub1 = zeros(N2, 1);
termi_sub1 = zeros(N2, 1);
response = zeros(N2, N);
% cycle over cols of matrix
for ti = 1:N
term0 = omega ./ (2 .* Q(ti));
gamma = 1 / (pi * Q(ti));
% calculate for the real part
if(ti == 1)
Lambda = ones(N2, 1);
termr_sub1(1) = 0;
termr_sub1(2:end) = term0(2:end) .* (ratio(2:end).^-gamma);
else
termr(1) = 0;
termr(2:end) = term0(2:end) .* (ratio(2:end).^-gamma);
rs_r = rs_r - dt.*(termr + termr_sub1);
termr_sub1 = termr;
Beta = exp( -1 .* -0.5 .* rs_r );
Lambda = (Beta + sigma2) ./ (Beta.^2 + sigma2); % vector
end
% calculate for the complex part
if(ginv == 1)
termi(1) = 0;
termi(2:end) = (ratio(2:end).^(sign .* gamma) - 1) .* omega(2:end);
else
termi = (ratio.^(sign .* gamma) - 1) .* omega;
end
rs_i = rs_i - dt.*(termi + termi_sub1);
termi_sub1 = termi;
integrand = exp( 1i .* -0.5 .* rs_i );
if(ginv == 1)
response(:,ti) = Lambda .* integrand;
else
response(:,ti) = (1 ./ Lambda) .* integrand;
end
end % ti loop
No, you cannot do so unless you know the "model" itself for this process. If you intend to treat the process as a complete black box, then it is impossible in general, although in any specific instance, anything can happen.
Even if you DO know the underlying process, then it may still not work, as any least squares estimator is dependent on the starting values, so if you do not have a good guess there, it may converge to the wrong set of parameters.
It turns out that by using the mathematics of the model, the input can be estimated. This is not true in general, but for my problem it seems to work. The cumulative integral is eliminated by a partial derivative.
N = 1001;
q = zeros(N, 1);
q(1:200) = 55;
q(201:300) = 120;
q(301:400) = 70;
q(401:600) = 40;
q(601:800) = 100;
q(801:1001) = 70;
dt = 0.0042;
fs = 1 / dt;
wSize = 101;
Glim = 20;
ginv = 0;
R = get_response(N, q, dt, wSize, Glim, ginv);
rows = wSize;
cols = N;
cut_val = 200;
imagLogR = imag(log(R));
Mderiv = zeros(rows, cols-2);
for k = 1:rows
val = deriv_3pt(imagLogR(k,:), dt);
val(val > cut_val) = 0;
Mderiv(k,:) = val(1:end-1);
end
disp('Running iteration');
q0 = 10;
q1 = 500;
NN = cols - 2;
qout = zeros(NN, 1);
for k = 1:NN
data = Mderiv(:,k);
qout(k) = fminbnd(#(q) curve_fit_to_get_q(q, dt, rows, data),q0,q1);
end
figure; plot(q); title('q value input as vector');
ylim([0 200]); xlim([0 1001])
figure;
plot(qout); title('Reconstructed q')
ylim([0 200]); xlim([0 1001])
Here are the supporting functions:
function output = deriv_3pt(x, dt)
% Function to compute dx/dt using the 3pt symmetrical rule
% dt is the timestep
N = length(x);
N0 = N - 1;
output = zeros(N0, 1);
denom = 2 * dt;
for k = 2:N0
output(k - 1) = (x(k+1) - x(k-1)) / denom;
end
function sse = curve_fit_to_get_q(q, dt, rows, data)
fs = 1 / dt;
N2 = rows;
f = (fs/2)*linspace(0,1,N2); % vector for frequency along cols
omega = 2 * pi .* f';
omegah = 2 * pi * f(end);
ratio = omega ./ omegah;
gamma = 1 / (pi * q);
termi = ((ratio.^(gamma)) - 1) .* omega;
Error_Vector = termi - data;
sse = sum(Error_Vector.^2);

Matlab remove loop to calculate PT1

I am calculating PT1 behavior in Matlab using the input vector u:
u(20:50,1) = 2;
k = 0.8;
x=zeros(50,1);
for i=2:size(u,1)
x(i) = k*x(i-1) + (1-k)*u(i);
end
How can I remove the for loop to get the same result?
This is actually a first-order IIR filter, so you can use filter for that:
u(20:50, 1) = 2;
k = 0.8;
x = filter(1 - k, [1, -k], u);
If you write x(i) out for a couple of values, you'll see a pattern in it:
x(1) = 0; % since the loop starts at i=2
x(2) = k*x(1) + (1-k)*u(2)
= 0 + (1-k)*u(2)
x(3) = k*x(2) + (1-k)*u(3)
= k*(1-k)*u(2) + (1-k)*u(3)
x(4) = k*x(3) + (1-k)*u(4)
= k^2*(1-k)*u(2) + k*(1-k)*u(3) + (1-k)*u(4)
...
So you'll easily spot the pattern being:
x(i) = (1-k) * sum(k^(i-j)*u(j), j=2..i)
which is now an explicit function.
You could apply this to remove your loop, but in reality this explicit function itself must calculate a large sum. Doing this for every index of x takes probably more time than looping and re-using prior results.