Creating a MATLAB system with tunable parameters for system identification - system-identification

Im trying to get MATLAB to create a state space model with initial values, which i later have to fine tune using the system identification toolbox.
The problem is that i am doing this with "white-box" models, which means that the A-matrix in my model isn't just a matrix of numeric values, but consists of several other parameters.
Since each of the parameters that makes up the matrix has a physical meaning, i'd like to estimate that seperately instead of just the value of the A-matrix.
Is this possible in any way? Have looked at both genss, idss and several other tools, but haven't been able to make any of them work as of yet.
A version of the system i'll be working with is as follows (C and D matrices are not relevant, since this is just testing really):
A = [-H_infil/Ca+Hsa_i^2/(Ca*(Hms_i+Hsa_i))-Hsa_i/Ca-H_win/Ca+Hsa_e^2/(Ca*(Hsa_e+Hms_e))-Hsa_e/Ca-H_vent/Ca Hsa_i*Hms_i/((Hms_i+Hsa_i)*Ca) Hsa_e*Hms_e/((Hsa_e+Hms_e)*Ca);
Hms_i*Hsa_i/((Hms_i+Hsa_i)*Ci) Hms_i^2/((Hms_i+Hsa_i)*Ci)-Hms_i/Ci 0;
Hms_e*Hsa_e/((Hsa_e+Hms_e)*Ce) 0 Hms_e^2/((Hsa_e+Hms_e)*Ce)-Hms_e/Ce-Hem/Ce];
Bc = [Hsa_i*S*wi/(Ca*(Hms_i+Hsa_i))+S*wa/Ca Hsa_i*fi/(Ca*(Hms_i+Hsa_i))+fa/Ca+Hsa_e*fe/(Ca*(Hsa_e+Hms_e)) H_infil/Ca+H_win/Ca H_vent/Ca;
Hms_i*S*wi/((Hms_i+Hsa_i)*Ci) Hms_i*fi/((Hms_i+Hsa_i)*Ci) 0 0;
0 Hms_e*fe/((Hsa_e+Hms_e)*Ce) Hem/Ce 0];
Cc = [0 0 0];
Dc = [0 0 0 0]
I realize that i may run into a problem with several solutions, but then i figured that the system identification would just choose one.
Any ideas?
Thanks in advance!
oh, and initial values goes as follows:
%% Q_Heating ratio factors are defined
% Factors
ki = 0.6;
ke = 0;
ka = 1 - ki - ke;
%% Internal heat gain factors are defined
fe = 0; % Internal heat gain ratio to external constructions
fi = 0; % Internal heat gain ratio to internal constructions
fa = 1 - fe - fi; % Internal heat gain ratio to room air
%% Solar heat gain factors are defined
S = 0.558; % Shading factor
wi = 0.6; % Solar heat gain ratio to internal constructions
wa = 1 - wi; % Solar heat gain ratio to room air
%% Capacities
% Air node
Ca = 60708.707;
% Internal node
Ci = 6.160*10^6*1.3;
% External node
Ce = 5.489*10^5*1.3;
%% Heat transfer coefficients
% Air to surface heat transfer coefficients
Hsa_i = 581.286;
Hsa_e = 52.094;
% Surface to mass heat transfer coefficients
Hms_i = 3235.007;
Hms_e = 284.432;
% Mass to external air/ground heat transfer coefficient
Hem = 0.986*1.3;
% Room air to external air heat transfer coefficients
H_infil = 0;
H_win = 1.627;
% Ventilation heat transfer coefficient
H_vent = 0;

Related

How can I evaluate and take the derivative of a neural net in Julia

I have solved a differential equation with a neural net. I leave code below with an example. I want to be able to compute the first derivative of this neural net with respect to its input "x" and evaluate this derivative for any "x".
1- Notice that I compute der = discretize.derivative . Is that the derivative of the neural net with respect to "x"? With this expression, if I type [first(der(phi, u, [x], 0.00001, 1, res.minimizer)) for x in xs] I get something that I wonder if it is the derivative but I cannot find a way to extract this in an array, let alone plot this. How can I evaluate this derivative at any point, lets say for all points in the array defined below as "xs"? Below in Update I give a more straightforward approach I took to try to compute the derivative (but still did not succeed).
2- Is there any other way that I could take the derivative with respect to x of the neural net?
I am new to Julia, so I am struggling a bit with how to manipulate the data types. Thanks for any suggestions!
Update: I found a way to see the symbolic expression for the neural net doing the following:
predict(x) = first(phi(x,res.minimizer))
df(x) = gradient(predict, x)[1]
After running the two lines of code type predict(x) or df(x) in the REPL and it will spit out the full neural net with the weights and biases of the solution. However I cannot evaluate the gradient, it spits an error. How can I evaluate the gradient with respect to x of my function predict(x)??
The original code creating the neural net and solving the equation
using NeuralPDE, Flux, ModelingToolkit, GalacticOptim, Optim, DiffEqFlux
import ModelingToolkit: Interval, infimum, supremum
#parameters x
#variables u(..)
Dx = Differential(x)
a = 0.5
eq = Dx(u(x)) ~ -log(x*a)
# Initial and boundary conditions
bcs = [u(0.) ~ 0.01]
# Space and time domains
domains = [x ∈ Interval(0.01,1.0)]
# Neural network
n = 15
chain = FastChain(FastDense(1,n,tanh),FastDense(n,1))
discretization = PhysicsInformedNN(chain, QuasiRandomTraining(100))
#named pde_system = PDESystem(eq,bcs,domains,[x],[u(x)])
prob = discretize(pde_system,discretization)
const losses = []
cb = function (p,l)
push!(losses, l)
if length(losses)%100==0
println("Current loss after $(length(losses)) iterations: $(losses[end])")
end
return false
end
res = GalacticOptim.solve(prob, ADAM(0.01); cb = cb, maxiters=300)
prob = remake(prob,u0=res.minimizer)
res = GalacticOptim.solve(prob,BFGS(); cb = cb, maxiters=1000)
phi = discretization.phi
der = discretization.derivative
using Plots
analytic_sol_func(x) = (1.0+log(1/a))*x-x*log(x)
dx = 0.05
xs = LinRange(0.01,1.0,50)
u_real = [analytic_sol_func(x) for x in xs]
u_predict = [first(phi(x,res.minimizer)) for x in xs]
x_plot = collect(xs)
xconst = analytic_sol_func(1)*ones(size(xs))
plot(x_plot ,u_real,title = "Solution",linewidth=3)
plot!(x_plot ,u_predict,line =:dashdot,linewidth=2)
The solution I found consists in differentiating the approximation with the help of ForwardDiff.
So if the neural network approximation to the unkown function is called "funcres" then we take its derivative with respect to x as shown below.
using ForwardDiff
funcres(x) = first(phi(x,res.minimizer))
dxu = ForwardDiff.derivative.(funcres, Array(x_plot))
display(plot(x_plot,dxu,title = "Derivative",linewidth=3))

Solve a linear system of equation using ODE45 in MATLAB

I have written a function plus a script to determine the variables. My variables name are "S E I1 I2 R Q H" which I named them in my function as x(1) to x(7). The total number of population equals to N which also equals to x(1)+x(2)+x(3)+x(4)+x(5). The problem is that when I try to run the script MATLAB gives me error and can not solve the linear system of ordinary differential equations. The worse problem is that MATLAB does not tell me where I'm wrong. It just tell me that the error comes from the eight line of my function. Can anyone help me with it ?
function Variables_rate = COVID_FUN(t,x) %#ok
NV = 7; % Number of Variables
global beta1 beta2 kessi ro1 ro2 alpha theta1 theta2 gamma1 gamma2 say phi lambda delta
% The Whole Number of community (N) equals to : N = S + E + I + R
N = x(1) + x(2) + x(3) + x(4) + x(5); % Total Number of people
%% This function will Model the COVID-19 Dynamical System Based on input Variables which are as follows :
% S: Suceptible Class corrosponds to {x1}
% E : Exposed Corrosponds to {x2}
% I1 : Infectious without intervention Corrosponds to {x3}
% I2 : Infectious with intervention corrosponds to {x4}
% R : Recovered corrosponds to {x5}
% Q : Quarantined corrosponds to {x6}
% H : Hospitalized corrosponds to {x7}
%% Model The Dynamic of the System with Differential Equations
Variables_rate = zeros(NV,1);
Variables_rate(1) = (-x(1)./N)*(beta1*x(3)+beta2*x(4)+kessi*x(2))+ro1*x(6)-ro2*x(1)+alpha*x(5); % Sdot
Variables_rate(2) = (x(1)./N)*(beta1*x(3)+beta2*x(4)+kessi*x(2))-theta1*x(2)-theta2*x(2); % Edot
Variables_rate(3) = theta1*x(2)-gamma1*x(3); % I1dot
Variables_rate(4) = theta2*x(2)-gamma2*x(4)-say*x(4)+lambda*(delta+x(6)); % I2dot
Variables_rate(5) = gamma1*x(3)+gamma2*x(4)+phi*x(7)-alpha*x(5); % Rdot
Variables_rate(6) = say*x(4)-phi*x(7); % Qdot
Variables_rate(7) = delta+ro2*x(1)-lambda*(delta+x(6))-ro1*x(6); % Hdot
end
Also the following is my main script :
clc;clear;close all;
% { COVID-19 Main Script Based on the written function }
global beta1 beta2 kessi ro1 ro2 alpha theta1 theta2 gamma1 gamma2 phi lambda delta say
%% According to TABLE 5 the Values of the Global Parameters are as follows :
beta1 = 1.0538*1e-1; % Contact rate of transmission per contact with infected class
beta2 = beta1; % Infection rate of transmission per contact with infected class
kessi = 1.6221*1e-1; % Probability of transmission per contact from exposed individuals
ro1 = 2.8133*1e-3; % Transition rate of quarantined exposed between the quarantined infected class and wider community
ro2 = 1.2668*1e-1; % Transition rate of quarantined exposed between the quarantined infected class and wider community
alpha = 1.2048*1e-4; % Temporary Immunity Rate
theta1 = 9.5*1e-4; % Transition rate of exposed individuals to the infected class
theta2 = 3.5412*1e-2; % Transition rate of exposed individuals to the infected class
gamma1 = 8.5*1e-3; % Recovery rate of symptomatic Infected Individuals to recovered
gamma2 =1.0037*1e-3; % Recovery rate of symptomatic Infected Individuals to recovered
say = 0.291; % Rate of Infectious with symptoms Hospitalized
phi = 0.0107; % Recovered rate of Quarantined infected individuals
lambda = 9.4522*1e-2; % Recovered rate of Quarantined Class to the recovered class
delta = 10; % External Input from the foreign countries
%% Time Vector and Initial Conditions
t = linspace(0,5,5);
Ics = [59717.71 5077 7.29 729 32 4711 658]';
%% Solve the Linear System Using ODE45 function
[~,States] = ode45(#(t,x)COVID_FUN,t,Ics)

GNU Octave: 1/N Octave Smoothing of actual FFT Data (not the representation of it)

I would like to smooth an Impulse Response audio file. The FFT of the file shows that it is very spikey. I would like to smooth out the audio file, not just its plot, so that I have a smoother IR file.
I have found a function that shows the FFT plot smoothed out. How could this smoothing be applied to the actual FFT data and not just to the plot of it?
[y,Fs] = audioread('test\test IR.wav');
function x_oct = smoothSpectrum(X,f,Noct)
%SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spectrum
%% Input checking
assert(isvector(X), 'smoothSpectrum:invalidX', 'X must be a vector.');
assert(isvector(f), 'smoothSpectrum:invalidF', 'F must be a vector.');
assert(isscalar(Noct), 'smoothSpectrum:invalidNoct', 'NOCT must be a scalar.');
assert(isreal(X), 'smoothSpectrum:invalidX', 'X must be real.');
assert(all(f>=0), 'smoothSpectrum:invalidF', 'F must contain positive values.');
assert(Noct>=0, 'smoothSpectrum:invalidNoct', 'NOCT must be greater than or equal to 0.');
assert(isequal(size(X),size(f)), 'smoothSpectrum:invalidInput', 'X and F must be the same size.');
%% Smoothing
% calculates a Gaussian function for each frequency, deriving a
% bandwidth for that frequency
x_oct = X; % initial spectrum
if Noct > 0 % don't bother if no smoothing
for i = find(f>0,1,'first'):length(f)
g = gauss_f(f,f(i),Noct);
x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
end
% remove undershoot when X is positive
if all(X>=0)
x_oct(x_oct<0) = 0;
end
end
endfunction
function g = gauss_f(f_x,F,Noct)
% GAUSS_F calculate frequency-domain Gaussian with unity gain
%
% G = GAUSS_F(F_X,F,NOCT) calculates a frequency-domain Gaussian function
% for frequencies F_X, with centre frequency F and bandwidth F/NOCT.
sigma = (F/Noct)/pi; % standard deviation
g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
g = g./sum(g); % normalise magnitude
endfunction
% take fft
Y = fft(y);
% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
Nout = (NFFT/2)+1;
else
Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;
% put into dB
Y = 20*log10(abs(Y)./NFFT);
% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);
% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on
PS. I have Octave GNU, so I don't have the functions that are available with Matlab Toolboxes.
Here is the test IR audio file.
I think I found it. Since the FFT of the audio file (which is real numbers) is symmetric, with the same real part on both sides but opposite imaginary part, I thought of doing this:
take the FFT, keep the half of it, and apply the smoothing function without converting the magnitudes to dB
then make a copy of that smoothed FFT, and invert just the imaginary part
combine the two parts so that I have the same symmetric FFT as I had in the beginning, but now it is smoothed
apply inverse FFT to this and take the real part and write it to file.
Here is the code:
[y,Fs] = audioread('test IR.wav');
function x_oct = smoothSpectrum(X,f,Noct)
x_oct = X; % initial spectrum
if Noct > 0 % don't bother if no smoothing
for i = find(f>0,1,'first'):length(f)
g = gauss_f(f,f(i),Noct);
x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient
end
% remove undershoot when X is positive
if all(X>=0)
x_oct(x_oct<0) = 0;
end
end
endfunction
function g = gauss_f(f_x,F,Noct)
sigma = (F/Noct)/pi; % standard deviation
g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian
g = g./sum(g); % normalise magnitude
endfunction
% take fft
Y = fft(y);
% keep only meaningful frequencies
NFFT = length(y);
if mod(NFFT,2)==0
Nout = (NFFT/2)+1;
else
Nout = (NFFT+1)/2;
end
Y = Y(1:Nout);
f = ((0:Nout-1)'./NFFT).*Fs;
% smooth
Noct = 12;
Z = smoothSpectrum(Y,f,Noct);
% plot
semilogx(f,Y,'LineWidth',0.7,f,Z,'LineWidth',2.2);
xlim([20,20000])
grid on
#Apply the smoothing to the actual data
Zreal = real(Z); # real part
Zimag_neg = Zreal - Z; # opposite of imaginary part
Zneg = Zreal + Zimag_neg; # will be used for the symmetric Z
# Z + its symmetry with same real part but opposite imaginary part
reconstructed = [Z ; Zneg(end-1:-1:2)];
# Take the real part of the inverse FFT
reconstructed = real(ifft(reconstructed));
#Write to file
audiowrite ('smoothIR.wav', reconstructed, Fs, 'BitsPerSample', 24);
Seems to work! :) It would be nice if someone more knowledgeable could confirm that the thinking and code are good :)

My octave function returns "ans = 0" -Coursera Machine Learning Week 2 problem

I am currently taking Andrew Nguyen's coursera machine learning course and I am on week 2. For a cost function assignment, my function keeps on returning "ans = 0" when it should be returning "ans= 32.07:
My code is below (The variables have been defined in the command window):
%COMPUTECOST Compute cost for linear regression
% J = COMPUTECOST(X, y, theta) computes the cost of using theta as the
% parameter for linear regression to fit the data points in X and y
% Initialize some useful values
% number of training examples
m = length(y);
% You need to return the following variables correctly
J =0;
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta
% You should set J to the cos
h = X * theta;
J = (1/(2m)*(sum(h-y).^2));
% =========================================================================
end

Variationnal auto-encoder: implementing warm-up in Keras

I recently read this paper which introduces a process called "Warm-Up" (WU), which consists in multiplying the loss in the KL-divergence by a variable whose value depends on the number of epoch (it evolves linearly from 0 to 1)
I was wondering if this is the good way to do that:
beta = K.variable(value=0.0)
def vae_loss(x, x_decoded_mean):
# cross entropy
xent_loss = K.mean(objectives.categorical_crossentropy(x, x_decoded_mean))
# kl divergence
for k in range(n_sample):
epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.,
std=1.0) # used for every z_i sampling
# Sample several layers of latent variables
for mean, var in zip(means, variances):
z_ = mean + K.exp(K.log(var) / 2) * epsilon
# build z
try:
z = tf.concat([z, z_], -1)
except NameError:
z = z_
except TypeError:
z = z_
# sum loss (using a MC approximation)
try:
loss += K.sum(log_normal2(z_, mean, K.log(var)), -1)
except NameError:
loss = K.sum(log_normal2(z_, mean, K.log(var)), -1)
print("z", z)
loss -= K.sum(log_stdnormal(z) , -1)
z = None
kl_loss = loss / n_sample
print('kl loss:', kl_loss)
# result
result = beta*kl_loss + xent_loss
return result
# define callback to change the value of beta at each epoch
def warmup(epoch):
value = (epoch/10.0) * (epoch <= 10.0) + 1.0 * (epoch > 10.0)
print("beta:", value)
beta = K.variable(value=value)
from keras.callbacks import LambdaCallback
wu_cb = LambdaCallback(on_epoch_end=lambda epoch, log: warmup(epoch))
# train model
vae.fit(
padded_X_train[:last_train,:,:],
padded_X_train[:last_train,:,:],
batch_size=batch_size,
nb_epoch=nb_epoch,
verbose=0,
callbacks=[tb, wu_cb],
validation_data=(padded_X_test[:last_test,:,:], padded_X_test[:last_test,:,:])
)
This will not work. I tested it to figure out exactly why it was not working. The key thing to remember is that Keras creates a static graph once at the beginning of training.
Therefore, the vae_loss function is called only once to create the loss tensor, which means that the reference to the beta variable will remain the same every time the loss is calculated. However, your warmup function reassigns beta to a new K.variable. Thus, the beta that is used for calculating loss is a different beta than the one that gets updated, and the value will always be 0.
It is an easy fix. Just change this line in your warmup callback:
beta = K.variable(value=value)
to:
K.set_value(beta, value)
This way the actual value in beta gets updated "in place" rather than creating a new variable, and the loss will be properly re-calculated.