Error executing harmonic product spectrum - matlab

I've been trying to find the fundamental notes using Harmonic Product Spectrum in MATLAB. I came across an algorithm and tried using it. I tested it with C Major scale (piano) with the notes
C4 D4 E4 F4 G4 A4 B4 C5 B4 A4 G4 F4 E4 D4 C4
I get the correct (almost close) frequency values for all the notes except the last C4 note because at that point i get the error
Matrix dimensions must agree.
This is the line that shows the error
f_ym = (1*seg_fft) .* (1.0*seg_fft2) .* (1*seg_fft3) .* (1*seg_fft4);
I'm not quite sure what's wrong here..
I found the note onsets and performed FFT on each onset and used that for the harmonic product spectrum. This is the part that does the HPS
h = 1;
for i = 2:No_of_peaks
song_seg = song(max_col(i-1):max_col(i)-1);
L = length(song_seg);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
seg_fft = fft(song_seg,NFFT);%/L;
%HPS
seg_fft = seg_fft(1 : size(seg_fft,1) / 2);
seg_fft = abs(seg_fft);
%HPS: downsampling
for i = 1:length(seg_fft)
seg_fft2(i,1) = 1;
seg_fft3(i,1) = 1;
seg_fft4(i,1) = 1;
% f_x5(i,1) = 1;
end
for i = 1:floor((length(seg_fft)-1)/2)
seg_fft2(i,1) = (seg_fft(2*i,1) + seg_fft((2*i)+1,1))/2;
end
for i = 1:floor((length(seg_fft)-2)/3)
seg_fft3(i,1) = (seg_fft(3*i,1) + seg_fft((3*i)+1,1) + seg_fft((3*i)+2,1))/3;
end
for i = 1:floor((length(seg_fft)-3)/4)
seg_fft4(i,1) = (seg_fft(4*i,1) + seg_fft((4*i)+1,1) + seg_fft((4*i)+2,1) + seg_fft((4*i)+3,1))/4;
end
%HPS, PartII: calculate product
f_ym = (1*seg_fft) .* (1.0*seg_fft2) .* (1*seg_fft3) .* (1*seg_fft4);
%HPS, PartIII: find max
f_y1 = max(f_ym);
for c = 1 : size(f_ym)
if(f_ym(c, 1) == f_y1)
index = c;
end
end
% Convert that to a frequency
f_y(h) = (index / NFFT) * FS
h=h+1;
f_y = abs(f_y)';
end
Well I'm trying to find the fundamental frequency in the presence of harmonics. Harmonic product spectrum is one way of doing it and that is what is being implemented in the above code. When I do the multiplication the size of seg_fft seems to be half the size of seg_fft2, seg_fft3, seg_fft4.
I don't know how I can make the dimensions to be of the same size.. That is where I need some help..
Would really appreciate some quick help. Thanx in advance :)

It is hard to understand exactly what you are trying to do without more explanation. But you get an error while trying to do element-wise multiplication of several matrices. This error message means that not all matrices have the same size, which is required for element-wise operations. To debug this kind of errors, the easiest is usually to check the sizes of the various matrices. So add these lines just before the line that gives the error:
disp(size(seg_fft))
disp(size(seg_fft2))
disp(size(1*seg_fft3))
disp(size(seg_fft4))
This should probably show you that one of them has a size that is different from what you expect. After this, try to fix your for-loops so that they all have the same size.

Related

How to plot π›½βˆ’π‘€ diagram in MATLAB?

I am trying to plot the π›½βˆ’π‘€ diagrams for the given phase constants using MATLAB, but although I have look at many web pages, there is not a similar example plotting π›½βˆ’π‘€ diagram in MATLAB. Could you please clarify me how to proceed by giving some examples regarding to this problem? Any help would really be appreciated.
Plot range: 𝑓=10π‘€β„Žπ‘§βˆ’10𝐺𝐻𝑧
w : Angular frequency
wc : A constant Angular frequency
Parameters for 1st: 𝑀𝑐1=0.2βˆ—π‘€, 𝑀𝑐2=0.4βˆ—π‘€, 𝑀𝑐3=0.6βˆ—π‘€, 𝑀𝑐4=0.8βˆ—π‘€ , Ι›1=1* Ι›0, ΞΌ= ΞΌ0
Parameters for 1st: a1=0.08636cm, a2=0.8636cm, a3=2.286cm, a4=29.21cm, Ι›1=1* Ι›0, ΞΌ= ΞΌ0
As the OP asked, this is a sort of Matlab code.
I assume to map the plot of B with w in range [1,100] (but values can be changed)
First case has wc has 3 different cases, 4 different plot of B (B1,B2, B3 and B4) will be mapped in four different colors
%constant inizialization
mu = 1.2566E-6;
e = 1;
start_f = 10000; %10 MHz start frequency range
end_f = 10000000; %10 GHz end frequency range
step = 10 %plot the function every "step" Hz (ONLY INTEGER NUMBERS ALLOWED)
k = 1;
% function of B example: B = w*sqrt(mu*e)*sqrt(1-((wc^2)/w));
%vectors initialization to avoid the "consider preallocation" Matlab not-critical warning
range_f = ceil((end_f - start_f)/step) + 1;
w = zeros(range_f);
B1 = zeros(range_f);
B2 = zeros(range_f);
B3 = zeros(range_f);
B4 = zeros(range_f);
for i=start_f:step:end_f %from 10 MHz to 10 GHz with steps of 1 Hz
%store i in the i-cell of vector w
w(k) = i;
%values that need to be updated every time
w1 = 0.2*w(i);
w2 = 0.4*w(i);
w3 = 0.6*w(i);
w4 = 0.8*w(i);
%four different results of B
B1(i) = w(i)*sqrt(mu*e)*sqrt(1-((w1^2)/w(i)));
B2(i) = w(i)*sqrt(mu*e)*sqrt(1-((w2^2)/w(i)));
B3(i) = w(i)*sqrt(mu*e)*sqrt(1-((w3^2)/w(i)));
B4(i) = w(i)*sqrt(mu*e)*sqrt(1-((w4^2)/w(i)));
k = k+1;
end
%plot the 4 lines
plot(w,B1,'r') %red line of B1 = f(w)
hold on
plot(w,B2,'g') %green line of B2 = f(w)
hold on
plot(w,B3,'b') %blue line of B3 = f(w)
hold on
plot(w,B4,'k') %black line of B4 = f(w)
4 different cases have to be represented with 4 plot (in this example they have been overlayed).
The last notation can be done in the same way (you have 4 constant parameters a1, a2 etc.) that does not depends from w this time. So
B1a(i) = sqrt((w(i)^2)*mu*e - ((pi^2)/a1)));
B2a(i) = sqrt((w(i)^2)*mu*e - ((pi^2)/a1)));
B3a(i) = sqrt((w(i)^2)*mu*e - ((pi^2)/a1)));
B4a(i) = sqrt((w(i)^2)*mu*e - ((pi^2)/a1)));
If some errors (due to "fast" writing) occurs to you, report them in comments and I will correct and update the code

Getting NaN values in neural network weight matrices

**I am trying to develop a feedforward NN in MATLAB. I have a dataset of 12 inputs and 1 output with 46998 samples. I have some NaN values in last rows of Matrix, because some inputs are accelerations & velocities which are 1 & 2 steps less respectively than displacements.
With this current data set I am getting w1_grad & w2_grad as NaN matrices. I tried to remove them using `Heave_dataset(isnan(Heave_dataset))=[];, but my dataset is getting converted into a column matrix of (1*610964).
can anyone help me with this ?
%
%% Clear Variables, Close Current Figures, and Create Results Directory
clc;
clear all;
close all;
mkdir('Results//'); %Directory for Storing Results
%% Configurations/Parameters
load 'Heave_dataset'
% Heave_dataset(isnan(Heave_dataset))=[];
nbrOfNeuronsInEachHiddenLayer = 24;
nbrOfOutUnits = 1;
unipolarBipolarSelector = -1; %0 for Unipolar, -1 for Bipolar
learningRate = 0.08;
nbrOfEpochs_max = 50000;
%% Read Data
Input = Heave_dataset(:, 1:length(Heave_dataset(1,:))-1);
TargetClasses = Heave_dataset(:, length(Heave_dataset(1,:)));
%% Calculate Number of Input and Output NodesActivations
nbrOfInputNodes = length(Input(1,:)); %=Dimention of Any Input Samples
nbrOfLayers = 2 + length(nbrOfNeuronsInEachHiddenLayer);
nbrOfNodesPerLayer = [nbrOfInputNodes nbrOfNeuronsInEachHiddenLayer nbrOfOutUnits];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Forward Pass %%%%%%%%%%%
%% Adding the Bias to Input layer
Input = [ones(length(Input(:,1)),1) Input];
%% Weights leading from input layer to hidden layer is w1
w1 = rand(nbrOfNeuronsInEachHiddenLayer,(nbrOfInputNodes+1));
%% Input & output of hidde layer
hiddenlayer_input = Input*w1';
hiddenlayer_output = -1 + 2./(1 + exp(-(hiddenlayer_input)));
%% Adding the Bias to hidden layer
hiddenlayer_output = [ones(length(hiddenlayer_output(:,1)),1) hiddenlayer_output];
%% Weights leading from input layer to hidden layer is w1
w2 = rand(nbrOfOutUnits,(nbrOfNeuronsInEachHiddenLayer+1));
%% Input & output of hidde layer
outerlayer_input = hiddenlayer_output*w2';
outerlayer_output = outerlayer_input;
%% Error Calculation
TotalError = 0.5*(TargetClasses-outerlayer_output).^2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Backward Pass %%%%%%%%%%%
d3 = outerlayer_output - TargetClasses;
d2 = (d3*w2).*hiddenlayer_output.*(1-hiddenlayer_output);
d2 = d2(:,2:end);
D1 = d2' * Input;
D2 = d3' * hiddenlayer_output;
w1_grad = D1/46998 + learningRate*[zeros(size(w1,1),1) w1(:,2:end)]/46998;
w2_grad = D2/46998 + learningRate*[zeros(size(w2,1),1) w2(:,2:end)]/46998;
You should try vectorize your algorithm. First arrange your data in a 46998x12 matrix X.Add bias to X like X=[ones(46998,1 X]. Then the weights leading from input layer to first hidden layer must be arranged in a matrix W1 with dimensions numberofneuronsinfirsthiddenlayer(24)x(input + 1). Then XW1' is what you feed in your neuron function (either is it sigmoid or whatever it is). The result (like sigmoid(XW') is the output of neurons at hidden level 1. You add bias like before and multiply by weight matrix W2 (the weights that lead from hidden layer 1 to hidden layer 2) and so on. Hope this helps to get you started vectorizing your code at least for the feedforward part. The back-propagation part is a little trickier but luckily involves the same matrices.
I will shortly recite the feedforward process so that we use same language talking about backpropagation.
There is the data called X.(dimensions 46998x12)
A1 = [ones(46998,1 X] is the input including bias. (46998x13)
Z2 = A1*W1' (W1 is the weight matrix that leads from input to hidden layer 1)
A2 = sigmoid(Z2);
A2 = [ones(m,1) A2]; adding bias again
Z3 = A2 * W2';
A3 = sigmoid(Z3);
Supposing you only have one hidden layer feedforward stops here. I'll start backwards now and you can generalize as appropriate.
d3 = A3 - Y; (Y must is part of your data, the actual values of the data with which you train your nn)
d2 = (d3 * W2).* A2 .* (1-A2); ( Sigmod function has a nice property that d(sigmoid(z))/dz = sigmoid(z)*(1-sigmoid(z)).)
d2 = d2(:,2:end);(You dont need the first column that corresponds in the bias)
D1 = d2' * A1;
D2 = d3' * A2;
W1_grad = D1/m + lambda*[zeros(size(W1,1),1) W1(:,2:end)]/m; (lamda is the earning rate, m is 46998)
W2_grad = D2/m + lambda*[zeros(size(W2,1),1) W2(:,2:end)]/m;
Everything must be in place now except for the vectorized cost function which have to be minimized. Hope this helps a bit...

How do I integrate a differential equation in MATLAB?

I want to integrate a differential equation dc/dt. Below is the code and the values of the variables.
clear all;
c1=.185;c0=2*10^-6;k3=.1*10^-6;
v1=6;v2=.11;v3=.09*10^-6;
Ca_ER=10*10^-6;Ca_cyto=1.7*10^-6;
p_open3=0.15;c=15*10^-6;
dcdt= (c1*(v1*(p_open3)+v2)*(Ca_ER)-c)-v3*((c)^2)/(c^2+(k3)^2);
I know there is an integral function but I am not sure how to apply for this equation. How do I proceed from here? Please help. The value of initial c, if needed, can be taken as 0.15*10^-6. Also, I need to plot the obtained result versus time. So will get an array of values or just a single value?
the link to the article. the equation i have used comes under Calcium Oscillations section
You could use Euler method to solve this problem to get a rough idea regarding the solution yet not accurate.
clear all
clc
t = 0;
dt = 0.0001;
c1 = 0.185;
c0 = 2*10^-6;
k3 = 0.1*10^-6;
v1 =6;
v2 =.11;
v3 =.09*10^-6;
Ca_ER =10*10^-6;
Ca_cyto =1.7*10^-6;
p_open3 =0.15;
c = 15*10^-6;
%store initial values
C(1) = c;
T(1) = t;
for i = 1:40000
dc = ( (c1*(v1*(p_open3)+v2)*(Ca_ER)-c)- v3*( c^2 /( c^2+(k3)^2) ) );
c = c + dt*dc;
t = t + dt;
%store data
C(i+1) = c;
T(i+1) = t;
end
plot(T,C, 'LineWidth',2)
xlabel('time (sec)')
ylabel('c(t)')
grid on
The result is
You can also use Wolfram which gives same result.

Harmonic Product Spectrum using MATLAB

Im tying to find the fundamental frequency of a note using harmonic product spectrum. This is the part that implements the HPS algorithm
seg_fft = seg_fft(1 : size(seg_fft,1)/2 ); % FFT data
seg_fft = abs(seg_fft);
seg_fft2 = ones(size(seg_fft));
seg_fft3 = ones(size(seg_fft));
seg_fft4 = ones(size(seg_fft));
seg_fft5 = ones(size(seg_fft));
for i = 1:floor((length(seg_fft)-1)/2)
seg_fft2(i,1) = (seg_fft(2*i,1) + seg_fft((2*i)+1,1))/2;
end
for i = 1:floor((length(seg_fft)-2)/3)
seg_fft3(i,1) = (seg_fft(3*i,1) + seg_fft((3*i)+1,1) + seg_fft((3*i)+2,1))/3;
end
for i = 1:floor((length(seg_fft)-3)/4)
seg_fft4(i,1) = (seg_fft(4*i,1) + seg_fft((4*i)+1,1) + seg_fft((4*i)+2,1) + seg_fft((4*i)+3,1))/4;
end
for i = 1:floor((length(seg_fft)-4)/5)
seg_fft5(i,1) = (seg_fft(5*i,1) + seg_fft((5*i)+1,1) + seg_fft((5*i)+2,1) + seg_fft((5*i)+3,1) + seg_fft((5*i)+4,1))/5;
end
f_ym = (seg_fft) .* (seg_fft2) .* (seg_fft3) .* (seg_fft4) .*(seg_fft5);
Now when i play F4, the 2nd harmonic(698 -F5) has a higher amplitude. So HPS is supposed to help me detect the fundamental which is F4 and NOT F5.
When i do the HPS these are the graphs I get:
The figures above show the plots of seg_fft2, seg_fft3, seg_fft4 and seg_fft5 respectively.
But what I dont understand is how come the frequency points obtained in these graphs are not factors of the original spectrum?? Isn't that how HPS is supposed to work??
This is the plot I obtained when I took the product of all 5.
the peak is at 698Hz.. But shouldn't it be at 349Hz instead??
But after the whole code is run, I do get the fundamental as F4.. Its all very confusing.... Can someone tell me why my graphs are different from what is expected yet I get the correct fundamental please????
This is the rest of the code
%HPS, PartIII: find max
f_y1 = max(f_ym)
for c = 1 : length(f_ym)
if(f_ym(c,1) == f_y1)
index = c;
end
end
% Convert that to a frequency
f_y(h) = (index / NFFT) * FS;
h=h+1;
%end
V = abs(f_y);
Please do help...... Thanx in advance....

Evolution strategy with individual stepsizes

I'm trying to find a good solution with an evolution strategy for a 30 dimensional minimization problem. Now I have developed with success a simple (1,1) ES and also a self-adaptive (1,lambda) ES with one step size.
The next step is to create a (1,lambda) ES with individual stepsizes per dimension. The problem is that my MATLAB code doesn't work yet. I'm testing on the sphere objective function:
function f = sphere(x)
f = sum(x.^2);
end
The plotted results of the ES with one step size vs. the one with individual stepsizes:
The blue line is the performance of the ES with individual step sizes and the red one is for the ES with one step size.
The code for the (1,lambda) ES with multiple stepsizes:
% Strategy parameters
tau = 1 / sqrt(2 * sqrt(N));
tau_prime = 1 / sqrt(2 * N);
lambda = 10;
% Initialize
xp = (ub - lb) .* rand(N, 1) + lb;
sigmap = (ub - lb) / (3 * sqrt(N));
fp = feval(fitnessfct, xp');
evalcount = 1;
% Evolution cycle
while evalcount <= stopeval
% Generate offsprings and evaluate
for i = 1 : lambda
rand_scalar = randn();
for j = 1 : N
Osigma(j,i) = sigmap(j) .* exp(tau_prime * rand_scalar + tau * randn());
end
O(:,i) = xp + Osigma(:,i) .* rand(N,1);
fo(i) = feval(fitnessfct, O(:,i)');
end
evalcount = evalcount + lambda;
% Select best
[~, sortindex] = sort(fo);
xp = O(:,sortindex(1));
fp = fo(sortindex(1));
sigmap = Osigma(:,sortindex(1));
end
Does anybody see the problem?
Your mutations have a bias: they can only ever increase the parameters, never decrease them. sigmap is a vector of (scaled) upper minus lower bounds: all positive. exp(...) is always positive. Therefore the elements of Osigma are always positive. Then your change is Osigma .* rand(N,1), and rand(N,1) is also always positive.
Did you perhaps mean to use randn(N,1) instead of rand(N,1)? With that single-character change, I find that your code optimizes rather than pessimizing :-).