FastICA Implementation.. Matlab - matlab

I have been working on a FastICA algorithm implementation using MatLab. Currently the code does not separate the signals as good as id like. I was wondering if anyone here could give me some advice on what I could do to fix this problem?
disp('*****Importing Signals*****');
s = [1,30000];
[m1,Fs1] = audioread('OSR_us_000_0034_8k.wav', s);
[f1,Fs2] = audioread('OSR_us_000_0017_8k.wav', s);
ss = size(f1,1);
n = 2;
disp('*****Mixing Signals*****');
A = randn(n,n); %developing mixing matrix
x = A*[m1';f1']; %A*x
m_x = sum(x, n)/ss; %mean of x
xx = x - repmat(m_x, 1, ss); %centering the matrix
c = cov(x');
sq = inv(sqrtm(c)); %whitening the data
x = c*xx;
D = diff(tanh(x)); %setting up newtons method
SD = diff(D);
disp('*****Generating Weighted Matrix*****');
w = randn(n,1); %Random weight vector
w = w/norm(w,2); %unit vector
w0 = randn(n,1);
w0 = w0/norm(w0,2); %unit vector
disp('*****Unmixing Signals*****');
while abs(abs(w0'*w)-1) > size(w,1)
w0 = w;
w = x*D(w'*x) - sum(SD'*(w'*x))*w; %perform ICA
w = w/norm(w, 2);
end
disp('*****Output After ICA*****');
sound(w'*x); % Supposed to be one of the original signals
subplot(4,1,1);plot(m1); title('Original Male Voice');
subplot(4,1,2);plot(f1); title('Original Female Voice');
subplot(4,1,4);plot(w'*x); title('Post ICA: Estimated Signal');
%figure;
%plot(z); title('Random Mixed Signal');
%figure;
%plot(100*(w'*x)); title('Post ICA: Estimated Signal');

Your covariance matrix c is 2 by 2, you cannot work with that. You have to mix your signal multiple times with random numbers to get anywhere, because you must have some signal (m1) common to different channels. I was unable to follow through your code for fast-ICA but here is a PCA example:
url = {'https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0034_8k.wav';...
'https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0017_8k.wav'};
%fs = 8000;
m1 = webread(url{1});
m1 = m1(1:30000);
f1 = webread(url{2});
f1 = f1(1:30000);
ss = size(f1,1);
n = 2;
disp('*****Mixing Signals*****');
A = randn(50,n); %developing mixing matrix
x = A*[m1';f1']; %A*x
[www,comp] = pca(x');
sound(comp(:,1)',8000)

Related

Triangle Pulse with fourier transformation

I have a basic exercise for telecommunications with matlab, and i must plot a triangle pulse with (-c,0) to (c,0) with c = 6 and Amplitude = 1 in a for loop for M pulses and approach the periodic pulse using N Fourier series terms. I can't find something on the internet that can help me so far.
A similar code for rect pulse that I made and works is this:
a = 1;
b = 3;
N = 1000;
t = linspace(a-2*a,b+2*b,N);
A = 1;
y = rect_pulse(A,a,b,t);
plot(t,y);
grid on
axis([a-2*a b+2*b 0 2*A]);
M = 5;
T=7;
t_new = linspace(a-2*a,b+(M-1)*T+2*b,N);
y_new = zeros(1,N);
for index = 1:1:M
temp_y = rect_pulse(A,a+(index-1)*T,b+(index-1)*T,t_new);
y_new = y_new + temp_y;
end
figure;
plot(t_new,y_new);
grid on;
axis([a-2*a b+(M-1)*T+2*b 0 2*A]);
Where rect_pulse is this:
function y = rect_pulse (A,a,b,t)
N=length(t);
y = zeros(1,N);
for index = 1:1:N
if(t(1,index)>=a) && (t(1,index)<=b)
y(1,index) = A;
end
end
And fourier series is this:
function y_fourier = fourier_series_rect_pulse(a,b,To,N,t)
y_fourier = 0;
wo = (2*pi)/To;
for n = -N:1:N
f_real = #(x) cos(n*wo*x);
f_imag = #(x) sin(n*wo*x);
cn = (1/To)*(quad(f_real,a,b)) - j*quad(f_imag,a,b));
y_fourier = y_fourier + cn*exp(j*n*wo*t);
end
y_fourier = real(y_fourier);
Any ideas how to make this in to triangle pulse?
This probably deviates significantly from your approach but if you're curious here is a script I came up with to generate a triangular pulse train that can be adjusted. This method, unfortunately, uses the fft() function which may or may not be off-limits in your case. Most of the script uses indexing and manipulating vectors. Additional spectral components may be seen due to the DC offset of the alternating triangular wave and the limited number of cycles available in the vector representation of the triangular wave.
Triangular Pulses and Fourier Transforms:
Triangular Pulse with Duty-Off Period:
Higher frequency spectral components present due to the abrupt corners that occur at the transition states of the triangle pulse and duty-off period.
%******************************************************%
%PROPERTIES THAT CAN BE CHANGED%
%******************************************************%
Plotting_Interval = 0.01; %0.01 seconds%
Pulse_Width = 1/20; %6 seconds%
Period = 1/20; %10 seconds (should be at least the pulse width)%
Start_Time = 0;
End_Time = Pulse_Width*1000; %(1000 pulses)%
%******************************************************%
if(Period < Pulse_Width)
Period = Pulse_Width;
end
Time_Vector = (Start_Time: Plotting_Interval: End_Time);
Points_Per_Unit_Time = 1/Plotting_Interval;
Half_Pulse = Pulse_Width/2;
Number_Of_Points = Pulse_Width/Plotting_Interval;
Rising_Slope = linspace(0,1,floor(Number_Of_Points/2) + 1);
Falling_Slope = 1 - Rising_Slope;
Triangular_Pulse = [Rising_Slope Falling_Slope(2:end)];
t = (0: Plotting_Interval: Pulse_Width);
Periodic_Triangular_Pulse = zeros(1,length(Time_Vector));
for Cycle = 1: +Period/Plotting_Interval: End_Time/Plotting_Interval
Periodic_Triangular_Pulse(1,Cycle:Cycle+length(Triangular_Pulse)-1) = Triangular_Pulse(1,1:end);
end
Periodic_Triangular_Pulse = Periodic_Triangular_Pulse(1,1:length(Time_Vector));
subplot(1,2,1); plot(Time_Vector,Periodic_Triangular_Pulse);
Triangle_Frequency = 1/Period;
title("Triangular Pulse Train " + num2str(Triangle_Frequency) + "Hz (first 10 cycles)");
axis([0 Period*10 0 1]);
xlabel("Time (s)"); ylabel("Amplitude");
Signal_Length = length(Periodic_Triangular_Pulse);
Fourier_Transform = fft(Periodic_Triangular_Pulse);
Fs = 1/Plotting_Interval;
P2 = abs(Fourier_Transform/Signal_Length);
P1 = P2(1:floor(Signal_Length/2)+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(Signal_Length/2))/Signal_Length;
subplot(1,2,2); plot(f,P1)
title("Single-Sided Fourier Transform");
xlabel("Frequency (Hz)"); ylabel("Magnitude");
Ran using MATLAB R2019b

Is there a correlation ratio in MATLAB?

Is there any function in Matlab which calculates the correlation ratio?
Here is an implementation I tried to do, but the results are not right.
function cr = correlation_ratio(X, Y, L)
ni = zeros(1, L);
sigmai = ni;
for i = 0:(L-1)
Yn = Y(X == i);
ni(1, i+1) = numel(Yn);
m = (1/ni(1, i+1))*sum(Yn);
sigmai(1, i+1) = (1/ni(1, i+1))*sum((Yn - m).^2);
end
n = sum(ni);
prod = ni.*sigmai;
cr = (1-(1/n)*sum(prod))^0.5;
This is the equation on the Wikipedia page:
where:
η is the correlation ratio,
yx,i are the sample values (x is the class label, i the sample index),
yx (with the bar on top) is the mean of sample values for class x,
y (with the bar on top) is the mean for all samples across all classes, and
nx is the number of samples in class x.
This is how I interpreted it into code:
function eta = correlation_ratio(X, Y)
X = X(:); % make sure we've got column vectors, simplifies things below a bit
Y = Y(:);
L = max(X);
mYx = zeros(1, L+1); % we'll write mean per class here
nx = zeros(1, L+1); % we'll write number of samples per class here
for i = unique(X).'
Yn = Y(X == i);
if numel(Yn)>1
mYx(i+1) = mean(Yn);
nx(i+1) = numel(Yn);
end
end
mY = mean(Y); % mean across all samples
eta = sqrt(sum(nx .* (mYx - mY).^2) / sum((Y-mY).^2));
The loop could be replaced with accumarray.

Interpolation using polyfit (Matlab)

My script is supposed to run Runge-Kutta and then interpolate around the tops using polyfit to calculate the max values of the tops. I seem to get the x-values of the max points correct but the y-values are off for some reason. Have sat with it for 3 days now. The problem should be In the last for-loop when I calculate py?
Function:
function funk = FU(t,u)
L0 = 1;
C = 1*10^-6;
funk = [u(2); 2.*u(1).*u(2).^2./(1+u(1).^2) - u(1).*(1+u(1).^2)./(L0.*C)];
Program:
%Runge kutta
clear all
close all
clc
clf
%Given values
U0 = [240 1200 2400];
L0 = 1;
C = 1*10^-6;
T = 0.003;
h = 0.000001;
W = [];
% Runge-Kutta 4
for i = 1:3
u0 = [0;U0(i)];
u = u0;
U = u;
tt = 0:h:T;
for t=tt(1:end-1)
k1 = FU(t,u);
k2 = FU(t+0.5*h,u+0.5*h*k1);
k3 = FU((t+0.5*h),(u+0.5*h*k2));
k4 = FU((t+h),(u+k3*h));
u = u + (1/6)*(k1+2*k2+2*k3+k4)*h;
U = [U u];
end
W = [W;U];
end
I1 = W(1,:); I2 = W(3,:); I3 = W(5,:);
dI1 = W(2,:); dI2 = W(4,:); dI3 = W(6,:);
I = [I1; I2; I3];
dI = [dI1; dI2; dI3];
%Plot of the currents
figure (1)
plot(tt,I1,'r',tt,I2,'b',tt,I3,'g')
hold on
legend('U0 = 240','U0 = 1200','U0 = 2400')
BB = [];
d = 2;
px = [];
py = [];
format short
for l = 1:3
[H,Index(l)]=max(I(l,:));
Area=[(Index(l)-2:Index(l)+2)*h];
p = polyfit(Area,I(Index(l)-2:Index(l)+2),4);
rotp(1,:) = roots([4*p(1),3*p(2),2*p(3),p(4)]);
B = rotp(1,2);
BB = [BB B];
Imax(l,:)=p(1).*B.^4+p(2).*B.^3+p(3).*B.^2+p(4).*B+p(5);
Tsv(i)=4*rotp(1,l);
%px1 = linspace(h*(Index(l)-d-1),h*(Index(l)+d-2));
px1 = BB;
py1 = polyval(p,px1(1,l));
px = [px px1];
py = [py py1];
end
% Plots the max points
figure(1)
plot(px1(1),py(1),'b*-',px1(2),py(2),'b*-',px1(3),py(3),'b*-')
hold on
disp(Imax)
Your polyfit line should read:
p = polyfit(Area,I(l, Index(l)-2:Index(l)+2),4);
More interestingly, take note of the warnings you get about poor conditioning of that polynomial (I presume you're seeing these). Why? Partly because of numerical precision (your numbers are very small, scaled around 10^-6) and partly because you're asking for a 4th-order fit to five points (which is singular). To do this "better", use more input points (more than 5), or a lower-order polynomial fit (quadratic is usually plenty), and (probably) rescale before you use the polyfit tool.
Having said that, in practice this problem is often solved using three points and a quadratic fit, because it's computationally cheap and gives very nearly the same answers as more complex approaches, but you didn't get that from me (with noiseless data like this, it doesn't much matter anyway).

Matrix dimensions must agree of jexact

I tried to code the jexact of Mie Series, but it says "Matrix dimensions must agree.
how should it be fixed?
%wave_length
lamda = 2*pi/3.5;
%speed of light
c = 299792458;
%frequency
freq = c/lamda;
%Raduis
R = 1;
%Permeability
mu = 4.0e-7*pi;
%permittivity
epsilon = 1.0/c/mu/c;
% radian frequency (w)
w = 2.0*pi*freq;
% wavenumber
K = w*sqrt(mu*epsilon);
omega=2*pi*(0:N-1)/N;
x=cos(omega)*R;
y=sin(omega)*R;
phi = atan2(y,x);
Jexact = zeros(size(x));
for nu = -10:10;
Jexact= Jexact + (1j.^(-nu).*exp(1j*nu*phi)./besselh(nu,2,K*R))*(-2/(w.*mu.*pi.*R));
end

Working on Separable Gabor filters in matlab

A filter g is called separable if it can be expressed as the multiplication of two vectors grow and gcol . Employing one dimensional filters decreases the two dimensional filter's computational complexity from O(M^2 N^2) to O(2M N^2) where M and N are the width (and height) of the filter mask and the image respectively.
In this stackoverflow link, I wrote the equation of a Gabor filter in the spatial domain, then I wrote a matlab code which serves to create 64 gabor features.
According to the definition of separable filters, the Gabor filters are parallel to the image axes - theta = k*pi/2 where k=0,1,2,etc.. So if theta=pi/2 ==> the equation in this stackoverflow link can be rewritten as:
The equation above is extracted from this article.
Note: theta can be extented to be equal k*pi/4. By comparing to the equation in this stackoverflow link, we can consider that f= 1 / lambda.
By changing my previous code in this stackoverflow link, I wrote a matlab code to make the Gabor filters separable by using the equation above, but I am sure that my code below is not correct especially when I initialized the gbp and glp equations. That is why I need your help. I will appreciate your help very much.
Let's show now my code:
function [fSiz,filters1,filters2,c1OL,numSimpleFilters] = init_gabor(rot, RF_siz)
image=imread('xxx.jpg');
image_gray=rgb2gray(image);
image_gray=imresize(image_gray, [100 100]);
image_double=double(image_gray);
rot = [0 45 90 135]; % we have four orientations
RF_siz = [7:2:37]; %we get 16 scales (7x7 to 37x37 in steps of two pixels)
minFS = 7; % the minimum receptive field
maxFS = 37; % the maximum receptive field
sigma = 0.0036*RF_siz.^2 + 0.35*RF_siz + 0.18; %define the equation of effective width
lambda = sigma/0.8; % it the equation of wavelength (lambda)
G = 0.3; % spatial aspect ratio: 0.23 < gamma < 0.92
numFilterSizes = length(RF_siz); % we get 16
numSimpleFilters = length(rot); % we get 4
numFilters = numFilterSizes*numSimpleFilters; % we get 16x4 = 64 filters
fSiz = zeros(numFilters,1); % It is a vector of size numFilters where each cell contains the size of the filter (7,7,7,7,9,9,9,9,11,11,11,11,......,37,37,37,37)
filters1 = zeros(max(RF_siz),numFilters);
filters2 = zeros(numFilters,max(RF_siz));
for k = 1:numFilterSizes
for r = 1:numSimpleFilters
theta = rot(r)*pi/180;
filtSize = RF_siz(k);
center = ceil(filtSize/2);
filtSizeL = center-1;
filtSizeR = filtSize-filtSizeL-1;
sigmaq = sigma(k)^2;
for x = -filtSizeL:filtSizeR
fx = exp(-(x^2)/(2*sigmaq))*cos(2*pi*x/lambda(k));
f1(x+center,1) = fx;
end
for y = -filtSizeL:filtSizeR
gy = exp(-(y^2)/(2*sigmaq));
f2(1,y+center) = gy;
end
f1 = f1 - mean(mean(f1));
f1 = f1 ./ sqrt(sum(sum(f1.^2)));
f2 = f2 - mean(mean(f2));
f2 = f2 ./ sqrt(sum(sum(f2.^2)));
p = numSimpleFilters*(k-1) + r;
filters1(1:filtSize,p)=f1;
filters2(p,1:filtSize)=f2;
convv1=imfilter(image_double, filters1(1:filtSize,p),'conv');
convv2=imfilter(double(convv1), filters2(p,1:filtSize),'conv');
figure
imagesc(convv2);
colormap(gray);
end
end
I think the code is correct provided your previous version of Gabor filter code is correct too. The only thing is that if theta = k * pi/4;, your formula here should be separated to:
fx = exp(-(x^2)/(2*sigmaq))*cos(2*pi*x/lambda(k));
gy = exp(-(G^2 * y^2)/(2*sigmaq));
To be consistent, you may use
f1(1,x+center) = fx;
f2(y+center,1) = gy;
or keep f1 and f2 as it is but transpose your filters1 and filters2 thereafter.
Everything else looks good to me.
EDIT
My answer above works for theta = k * pi/4;, with other angles, based on your paper,
x = i*cos(theta) - j*sin(theta);
y = i*sin(theta) + j*cos(theta);
fx = exp(-(x^2)/(2*sigmaq))*exp(sqrt(-1)*x*cos(theta));
gy = exp(-(G^2 * y^2)/(2*sigmaq))*exp(sqrt(-1)*y*sin(theta));
The final code will be:
function [fSiz,filters1,filters2,c1OL,numSimpleFilters] = init_gabor(rot, RF_siz)
image=imread('xxx.jpg');
image_gray=rgb2gray(image);
image_gray=imresize(image_gray, [100 100]);
image_double=double(image_gray);
rot = [0 45 90 135];
RF_siz = [7:2:37];
minFS = 7;
maxFS = 37;
sigma = 0.0036*RF_siz.^2 + 0.35*RF_siz + 0.18;
lambda = sigma/0.8;
G = 0.3;
numFilterSizes = length(RF_siz);
numSimpleFilters = length(rot);
numFilters = numFilterSizes*numSimpleFilters;
fSiz = zeros(numFilters,1);
filters1 = zeros(max(RF_siz),numFilters);
filters2 = zeros(numFilters,max(RF_siz));
for k = 1:numFilterSizes
for r = 1:numSimpleFilters
theta = rot(r)*pi/180;
filtSize = RF_siz(k);
center = ceil(filtSize/2);
filtSizeL = center-1;
filtSizeR = filtSize-filtSizeL-1;
sigmaq = sigma(k)^2;
for x = -filtSizeL:filtSizeR
fx = exp(-(x^2)/(2*sigmaq))*exp(sqrt(-1)*x*cos(theta));
f1(1, x+center) = fx;
end
for y = -filtSizeL:filtSizeR
gy=exp(-(y^2)/(2*sigmaq))*exp(sqrt(-1)*y*sin(theta));
f2(y+center,1) = gy;
end
f1 = f1 - mean(mean(f1));
f1 = f1 ./ sqrt(sum(sum(f1.^2)));
f2 = f2 - mean(mean(f2));
f2 = f2 ./ sqrt(sum(sum(f2.^2)));
p = numSimpleFilters*(k-1) + r;
filters1(1:filtSize,p)=f1;
filters2(p,1:filtSize)=f2;
convv1=imfilter(image_double, filters1(1:filtSize,p),'conv');
convv2=imfilter(double(convv1), filters2(p,1:filtSize),'conv');
figure
imagesc(imag(convv2));
colormap(gray);
end
end