Weird results in approximation of a function with neural networks - matlab

I am trying to approximate a function (the right hand side of a differential equation) of the form ddx=F(x,dx,u) (where x,dx,u are scalars and u is constant) with an RBF neural network. I have the function F as a black box (I can feed it with initial x,dx and u and take x and dx for a timespan I want) and during training (using sigma-modification) I am getting the following response plotting the real dx vs the approximated dx.
Then I save the parameters of the NN (the centers and the stds of the gaussians, and the final weights) and perform a simulation using the same initial x,dx and u as before and keeping, of course, the weights stable this time. But I get the following plot.
Is that logical? Am I missing something?
The training code is as follows:
%load the results I got from the real function
load sim_data t p pd dp %p is x,dp is dx and pd is u
real_states = [p,dp];
%down and upper limits of the variables
p_dl = 0;
p_ul = 2;
v_dl = -1;
v_ul = 4;
pd_dl = 0;%pd is constant each time,but the function should work for different pds
pd_ul = 2;
%number of gaussians
nc = 15;
x = p_dl:(p_ul-p_dl)/(nc-1):p_ul;
dx = v_dl:(v_ul-v_dl)/(nc-1):v_ul;
pdx = pd_dl:(pd_ul-pd_dl)/(nc-1):pd_ul;
%centers of gaussians
Cx = combvec(x,dx,pdx);
%stds of the gaussians
B = ones(1,3)./[2.5*(p_ul-p_dl)/(nc-1),2.5*(v_ul-v_dl)/(nc-1),2.5*(pd_ul-pd_dl)/(nc-1)];
nw = size(Cx,2);
wdx = zeros(nw,1);
state = real_states(1,[1,4]);%there are also y,dy,dz and z in real_states (ignored here)
states = zeros(length(t),2);
timestep = 0.005;
for step=1:length(t)
states(step,:) = state;
%compute the values of the sigmoids
Sx = exp(-1/2 * sum(((([real_states(step,1);real_states(step,4);pd(1)]*ones(1,nw))'-Cx').*(ones(nw,1)*B)).^2,2));
ddx = -530*state(2) + wdx'*Sx;
edx = state(2) - real_states(step,4);
dwdx = -1200*edx * Sx - 4 * wdx;
wdx = wdx + dwdx*timestep;
state = [state(1)+state(2)*timestep,state(2)+ddx*timestep];
end
save weights wdx Cx B
figure
plot(t,[dp(:,1),states(:,2)])
legend('x_d_o_t','x_d_o_t_h_a_t')
The code used to verify the approximation is the following:
load sim_data t p pd dp
real_states = [p,dp];
load weights wdx Cx B
nw = size(Cx,2);
state = real_states(1,[1,4]);
states = zeros(length(t),2);
timestep = 0.005;
for step=1:length(t)
states(step,:) = state;
Sx = exp(-1/2 * sum(((([real_states(step,1);real_states(step,4);pd(1)]*ones(1,nw))'-Cx').*(ones(nw,1)*B)).^2,2));
ddx = -530*state(2) + wdx'*Sx;
state = [state(1)+state(2)*timestep,state(2)+ddx*timestep];
end
figure
plot(t,[dp(:,1),states(:,2)])
legend('x_d_o_t','x_d_o_t_h_a_t')

Related

FastICA Implementation.. 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)

Code unable to reconcile vector assignment

I am interested in modifying the code below to find the parameters I_1, I_2, I_3 and I_4, to be used in another code. Every time I run the code, it throws up
In an assignment A(:) = B, the number of elements in A and B must be the same
on this line " mult(mult == 0) = B;".
I have spent eternity figuring out what the problem could be. Here is the code:
%%% Some Parameters %%
delta = 0.6; % Blanked subframe ratio
B = [0 0.2 0.4 0.6 0.8 1]; %Power splitting factor
k = 2.3; %Macro BS density
f = k*5; %Small cell density
j = 300; %users density
P_m = 46; %Macro BS transmission power
P_s = 23; %SC transmit power
Zm = -15;
Zs = -15;
iter = 30; %Iteration run
h = 500; %Simulation area
hu = 0.8*h; %users simulation area
Vm = round(k*h); %Macro BS average no in h
Vs = round(f*h); %SC average no in h
Vu = round(j*hu); %%users average no in hu
Pm = 10^(P_m/10)/1000*10^(Zm/10);
Ps = 10^(P_s/10)/1000*10^(Zs/10);
for i = iter;
%% XY coodinates for Macrocell, small cells and users.
Xm = sqrt(h)*(rand(Vm,1)-0.5);
Ym = sqrt(h)*(rand(Vm,1)-0.5);
Xs = sqrt(h)*(rand(Vs,1)-0.5);
Ys = sqrt(h)*(rand(Vs,1)-0.5);
Xu = sqrt(hu)*(rand(Vu,1)-0.5);
Yu = sqrt(hu)*(rand(Vu,1)-0.5);
%Total coordinates for MBS and small cells
Total_Coord = [Xs Ys ones(size(Xs)) Xm Ym 2*ones(size(Xm))];
%Distance between BSs and users
[Xsm_mat, Xu_mat] = meshgrid(Total_Coord(:,1),Xu);
[Ysm_mat, Yu_mat] = meshgrid(Total_Coord(:,2),Yu);
Distance = sqrt((Xsm_mat-Xu_mat).^2 + (Ysm_mat-Yu_mat).^2);
%% To determine serving BS for each user
[D_m,idx_m] = min(Distance(:,(length(Xs)+1):end),[],2);
idx_m = idx_m + length(Xs);
[D_s,idx_s] = min(Distance(:,1:length(Xs)),[],2);
%% Power received by users from each BS
Psm_mat = [Ps*ones(length(Xu),length(Xs))
Pm*ones(length(Xu),length(Xm))]; % Transmit power of MBS and small cells
Pr_n = Psm_mat.*exprnd(1,size(Psm_mat))./(Distance*1e3).^4;
mult = binornd(1,delta,1,length(Xm)); % Full transmission power of each
interfering MBS for delta
mult(mult == 0) = B; % Reduced transmission power for (1-delta)
Pr = Pr_n.*[ones(length(Xu),length(Xs)) repmat(mult,length(Xu),1)];%
Interference from each BS
%% Power received by each user from serving BSs
Prm = Pr(sub2ind(size(Pr),(1:length(idx_m))',idx_m));
Prs = Pr(sub2ind(size(Pr),(1:length(idx_s))',idx_s));
P_m_n = Pr_n(sub2ind(size(Pr_n),(1:length(idx_m))',idx_m));
%% Total interference for each UE
I_T = sum(Pr,2) - Prm - Prs;
I_1 = P_m_n./(Prs + I_T);
I_2 = Prs./(P_m_n + I_T);
I_3 = B*I_1;
I_4 = Prs./(B*P_m_n + I_T);
end
The error appeared on this line "mult(mult == 0) = B;".
I know it to be assignment problem which requires equality in both the left and right dimensions. Suggestions for correction will be appreciated.
Your vector mult has length Vm (number of macro BS?). Assigning to mult(mult==0) will assign to a subset of this vector (those that have a value equal to zero). What you are assigning is your variable B which you define as B = [0 0.2 0.4 0.6 0.8 1], i.e., it is a length-6 vector. The assignment fails unless mult has exactly 6 zeros.
I highly doubt that this is what you want. It looks like you are trying to assign the same value ("Reduced transmission power"). Then your B should be scalar though.
Since we have no idea what you are trying to do (and your code is not exactly an MCVE), we can only guess.

Solving PDE with Matlab

`sol = pdepe(m,#ParticleDiffusionpde,#ParticleDiffusionic,#ParticleDiffusionbc,x,t);
% Extract the first solution component as u.
u = sol(:,:,:);
function [c,f,s] = ParticleDiffusionpde(x,t,u,DuDx)
global Ds
c = 1/Ds;
f = DuDx;
s = 0;
function u0 = ParticleDiffusionic(x)
global qo
u0 = qo;
function [pl,ql,pr,qr] = ParticleDiffusionbc(xl,ul,xr,ur,t,x)
global Ds K n
global Amo Gc kf rhop
global uavg
global dr R nr
sum = 0;
for i = 1:1:nr-1
r1 = (i-1)*dr; % radius at i
r2 = i * dr; % radius at i+1
r1 = double(r1); % convert to double precision
r2 = double(r2);
sum = sum + (dr / 2 * (r1*ul+ r2*ur));
end;
uavg = 3/R^3 * sum;
ql = 1;
pl = 0;
qr = 1;
pr = -((kf/(Ds.*rhop)).*(Amo - Gc.*uavg - ((double(ur/K)).^2).^(n/2) ));`
dq(r,t)/dt = Ds( d2q(r,t)/dr2 + (2/r)*dq(r,t)/dr )
q(r, t=0) = 0
dq(r=0, t)/dr = 0
dq(r=dp/2, t)/dr = (kf/Ds*rhop) [C(t) - Cp(at r = dp/2)]
q = solid phase concentration of trace compound in a particle with radius dp/2
C = bulk liquid concentration of trace compound
Cp = trace compound concentration at particle surface
I want to solve the above pde with initial and boundary conditions given. Tried Matlab's pdepe, but does not work satisfactorily. Maybe the boundary conditions is creating problem for me. I also used this isotherm equation for equilibrium: q = K*Cp^(1/n). This is convection-diffusion equation but i could not find any write ups that addresses solving this type of equation properly.
There are two problems with the current implementation.
Incorrect Source Term
The PDE you are attempting to solve has the form
which has the equivalent form
where the last term arises due to the factor of 2 in the original PDE.
The last term needs to be incorporated into pdepe via a source term.
Calculation of q average
The current implementation attempts to calculate the average value of q using the left and right values of q passed to the boundary condition function.
This is incorrect.
The average value of q needs to be calculated from a vector of up-to-date values of the quantity.
However, we have the complication that the only function to receive all mesh values is ParticleDiffusionpde; however, the mesh values passed to that function are not guaranteed to be from the mesh we provided.
Solution: use events (as described in the pdepe documentation).
This is a hack since the event function is meant to detect zero-crossings, but it has the advantage that the function is given all values of q on the mesh we provide.
So, the working example below (you'll notice I set all of the parameters to 1 since I didn't know better) uses the events function to update a variable qStore that can be accessed by the boundary condition function (see here for an explanation), and the boundary condition function performs a vectorized trapezoidal integration for the average calculation.
Working Example
function [] = ParticleDiffusion()
% Parameters
Ds = 1;
q0 = 0;
K = 1;
n = 1;
Amo = 1;
Gc = 1;
kf = 1;
rhop = 1;
% Space
rMesh = linspace(0,1,10);
rMesh = rMesh(:) ;
dr = rMesh(2) - rMesh(1) ;
% Time
tSpan = linspace(0,1,10);
% Vector to store current u-value
qStore = zeros(size(rMesh));
options.Events = #(m,t,x,y) events(m,t,x,y);
% Solve
[sol,~,~,~,~] = pdepe(1,#ParticleDiffusionpde,#ParticleDiffusionic,#ParticleDiffusionbc,rMesh,tSpan,options);
% Use the events function to update qStore
function [value,isterminal,direction] = events(m,~,~,y)
qStore = y; % Value of q on rMesh
value = m; % Since m is constant, it will never be zero (no event detection)
isterminal = 0; % Continue integration
direction = 0; % Detect all zero crossings (not important)
end
function [c,f,s] = ParticleDiffusionpde(r,~,~,DqDr)
% Define the capacity, flux, and source
c = 1/Ds;
f = DqDr;
s = DqDr./r;
end
function u0 = ParticleDiffusionic(~)
u0 = q0;
end
function [pl,ql,pr,qr] = ParticleDiffusionbc(~,~,R,ur,~)
% Calculate average value of current solution
qL = qStore(1:end-1);
qR = qStore(2: end );
total = sum((qL.*rMesh(1:end-1) + qR.*rMesh(2:end))) * dr/2;
qavg = 3/R^3 * total;
% Left boundary
pl = 0;
ql = 1;
% Right boundary
qr = 1;
pr = -(kf/(Ds.*rhop)).*(Amo - Gc.*qavg - (ur/K).^n);
end
end

integral2Calc>integral2t/tensor & Warning: Reached the maximum number of function evaluations (10000)

I am trying to do a set of integrations for a particular value of psi and theta. These integrations are then combined into a formula to give P. The idea is then to do this for a set of psi and theta from 0 to pi/2 and then plot the results of P against a function of theta and psi.
I get two errors, firstly
integral2Calc>integral2t/tensor
not sure how to change the integral to make it the right dimensions to psi no longer being a scalar.
I also get Warning: Reached the maximum number of function evaluations (10000) for i3, is this a serious error, (as in has the integration not been computed) I tried changing the type of integration or changing the error tolerance and this seemed to have no effect on removing the actual error..
eta = input('Enter Dielectric Constant 1.5-4: ');
sdev = input('Enter STD DEV (roughness) maybe 0.1: ');
psi = [0:0.01:pi/2];
theta = [0:0.01:pi/2];
r = sqrt((sin(psi)).^2+(sin(theta).*(cos(psi))).^2);
calpha = (cos(theta+dtheta)).*(cos(psi+dpsi));
rp01 = calpha-sqrt(eta-1+((calpha).^2));
rp02 = calpha+sqrt(eta-1+((calpha).^2));
rperp = (rp01./rp02).^2;
rp11 = ((eta.*calpha)-sqrt(eta-1+((calpha).^2)));
rp12 = ((eta.*calpha)+sqrt(eta-1+((calpha).^2)));
rpar = (rp11./rp12).^2;
qthingy1 = ((sin(psi+dpsi)).^2)-((sin(theta+dtheta)).^2).*((cos(psi+dpsi)).^2);
qthingy2 = ((sin(psi+dpsi)).^2)+((sin(theta+dtheta)).^2).*((cos(psi+dpsi)).^2);
qthingy = qthingy1./qthingy2;
wthingy1 = (sin(2*(psi+dpsi))).*(sin(theta+dtheta));
wthingy2 = ((sin(psi+dpsi)).^2)+(sin((theta+dtheta)).^2).*((sin(psi+dpsi)).^2);
wthingy = wthingy1./wthingy2;
roughness = (cos(psi)./(2*pi*(sdev.^2))).*exp(-((cos(psi).*dtheta).^2+(dpsi).^2)/(2*sdev.^2));
fun = matlabFunction((rpar+rperp).*roughness,'vars',{dtheta,dpsi});
fun2 = matlabFunction(roughness,'vars',{dtheta,dpsi});
fun3 = matlabFunction((rpar+rperp).*roughness.*qthingy,'vars',{dtheta,dpsi});
fun4 = matlabFunction((rpar+rperp).*roughness.*wthingy,'vars',{dtheta,dpsi});
thetamax = (pi/2) - theta;
psimax = (pi/2) - psi;
A = integral2(fun2,-pi/2,pi/2,-pi/2,pi/2);
i1 = (integral2(fun,-pi/2,thetamax,-pi/2,psimax))./A;
q = 2 - i1;
i2 = (integral2(fun3,-pi/2,thetamax,-pi/2,psimax))./A;
i3 = (integral2(fun4,-pi/2,thetamax,-pi/2,psimax))./A;
P = sqrt(i2.^2+i3.^2)./i1
plot(P, r);

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