loss defined on repeated evaluation of the same model - neural-network

I have a model denoted by f(),
Suppose the target is t, f(x1) = y1 and f(x2) = y2 and my loss is defined as
loss = mse(y1,y2) + mse(y2,t)
Since both y1 and y2 reguires grad, I have received error such as
one of the variables needed for gradient computation has been modified by an inplace operation
My understanding is that, suppose I evaluate y1 first, the graph has been changed upon my evaluation of y2. Should I fix some tensor such as ,e.g., y1_no_grad = y1.detach().numpy() and then use
loss = mse(y1_no_grad,y2) + mse(y2,t)?
However, I still receive error Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy(), which I am not sure if it is because y1_no_grad is a numpy array while y2 is a tensor.
Update:
I realized my problem afterwards. It was due to that I created multiple loss tensors and that I backwarded one loss tensor first which changed the parameters in-place. This caused error when I wanted to backward another loss tensor.
E.g.
f(x1) = y1
f(x2) = y2
f(x3) = y3
...
f(xn) = yn
f(x) = y
for i in range(n):
optimizer.zero_grad()
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()
To me the solutions are either:
1.accumulate the loss tensors before doing backward , i.e.
for i in range(n):
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()
2.Evaluate again before each backward, i.e.:
for i in range(n):
optimizer.zero_grad()
y = f(x)
yi = f(xi)
loss = mse(y,yi) + mse(yi,t)
loss.backward()
optimizer.step()

Suppose the target is t, f(x1) = y1 and f(x2) = y2 and my loss is defined as
loss = mse(y1,y2) + mse(y2,t)
Since both y1 and y2 reguires grad, I have received error such as
This statement is incorrect. What you've described does not necessiate in-place assignment errors. For example
import torch
from torch.nn.functional import mse_loss
def f(x):
return x**2
t = torch.ones(1)
x1 = torch.randn(1, requires_grad=True)
x2 = torch.randn(1, requires_grad=True)
y1 = f(x1)
y2 = f(x2)
loss = mse_loss(y1, y2) + mse_loss(y2, t)
loss.backward()
does not produce any errors. Likely your issue is somewhere else.
For the general case you described you should get a computation graph that could be visualized as
The only issue here could be that your function f is not differentiable or is somehow invalid (perhaps in in-place assignment is taking place in f).

Related

MATLAB Lsim initial value for RC filter doesnt work

I would simulate an RC (low-pass) filter that has some initial value.
R = 1e3; % 1kOm
C = 100e-6; % 100uF
es = tf('s');
LP1 = 1 / (R*C*es + 1);
Ts = 0.1; % 100ms
sysd = c2d(LP1, Ts);
Initial value means that capacitor is charged to some voltage (lets say 5V) and we apply some voltage to the input (lets say 10V). I would see output voltage / time plot:
x0 = 5; % 5V
input = 10; % 10V
N = 100;
lsim(sysd, ones(1, N)*input, [], x0);
Plot that is showed starts with zero (no initial condition). If i convert tf to ss:
lsim(ss(sysd), ones(1, N)*input, [], x0);
Than plot starts from non zero value but it is NOT 5V that I set as initial value.
What is wrong with it, How to simulate it?
The x0 input to lsim() is only used to define the initial conditions of a state-space system.
In the first example, sysd is a transfer function, so x0 has no effect and a zero initial condition is used.
In the second example, ss(sysd) is a state-space model, so x0 specifies the initial state and not the output as you intended. To understand what is going on, let's take a look at your state-space model:
>> ss(sysd)
ans =
A =
x1
x1 0.3679
B =
u1
x1 1
C =
x1
y1 0.6321
D =
u1
y1 0
Sample time: 0.1 seconds
Discrete-time state-space model.
Per the state-space output equation y = Cx + Du , the initial output is equal to C*x0 = 0.6321*5 = 3.16 which matches the result in your plot. Instead, you should set x0 = y0 / ss(sysd).C where y0 is the desired initial output. For y0 = 5, this means setting x0 = 7.91.

Optimize a definite integral

In the integral
I want to optimize the function Dt, as I know the end result of the integral. I have expressions for k1 and k0 in terms of k2 and N, and it is k2 and N that I would like to optimize. They have constraints, needing to be between certain values. I have it all setup in my code, but I am just unaware of how to tell the genetic alogrithm to optimize an integral function? Is there something I'm missing here? The integral is usually evaluated numerically but I am trying to go backwards, and assuming I know an answer find the input parameters
EDIT:
All right, so here's my code. I know the integral MUST add up to a known value, and I know the value, so I need to optimize the variables with that given parameter. I have created an objective function y= integral - DT. I kept theta as syms because it is the thing being integrated to give DT.
function y = objective(k)
% Define constants
AU = astroConstants(2);
mu = astroConstants(4);
% Define start and finish parameters for the exponential sinusoid.
r1 = AU; % Initial radius
psi = pi/2; % Final polar angle of Mars/finish transfer
phi = pi/2;
r2 = 1.5*AU;
global k1
k1 = sqrt( ( (log(r1/r2) + sin(k(1)*(psi + 2*pi*k(2)))*tan(0)/k(1)) / (1-
cos(k(1)*(psi+2*pi*k(2)))) )^2 + tan(0)^2/k(1)^2 );
k0 = r1/exp(k1*sin(phi));
syms theta
R = k0*exp(k1*sin(k(1)*theta + phi));
syms theta
theta_dot = sqrt((mu/(R^3))*1/((tan(0))^2 + k1*(k(1))^2*sin(k(1)*theta +
phi) + 1));
z = 1/theta_dot;
y = int(z, theta, 0,(psi+2*pi*k(2))) - 1.3069e08;
global x
x=y;
end
my k's are constrained, and the following is the constraint function. I'm hoping what I have done here is tell it that the function MUST = 0.
function [c,c_eq] = myconstraints(k)
global k1 x
c = [norm(k1*(k(1)^2))-1 -norm(k1*(k(1)^2))];
c_eq =[x];
end
And finally, my ga code looks like this. Honestly, I've been playing with it all night and getting error messages after error messages - ranging from "constraint function must return real value" to "error in fcnvectorizer" and "unable to convert expression into double array", with the last two coming after i've removed the constraints.
clc; clear;
ObjFcn = #objective;
nvars = 2
LB = [0 2];
UB = [1 7];
ConsFcn = #myconstraints;
[k,fval] = ga(ObjFcn,nvars,[],[],[],[],LB,UB,ConsFcn);
I've been stuck on this problem for weeks and have gotten nowhere, even with searching through literature.

MATLAB using rand to test for time invariance

So I am given a certain system: y(n) = 10x(n)cos(0.25pi*n + 0.1pi)
And I am to test if the system is time invariant by plotting two input signals x(n) and x(n-2), and their corresponding output signals. X(n) is supposed to be a causal signal with 10 elements using the rand function.
This is the code I've written thus far:
clear all; clc; close all;
n = 0:9; n2 = 0:11;
xN1 = [rand(1,10) 0 0]; %x(n)
xN2 = [0 0 rand(1,10)]; %x(n-2)
yN1 = 10.*xN1.*cos(0.25.*pi.*n2+0.1.*pi); %y(n)
yN2 = 10.*xN2.*cos(0.25.*pi.*n2+0.1.*pi); %y(n-2)
figure,
subplot(2,2,1)
stem(n2,xN1),title('x1')
subplot(2,2,2)
stem(n2,yN1),title('y1')
subplot(2,2,3)
stem(n2,xN2),title('x2')
subplot(2,2,4)
stem(n2,yN2),title('y2')
My question is what am I being asked to plot? x1 vs. x2, and then y1 vs. y2? Or x1 vs. n and x2 vs. n, and so on.
This is the result I obtain with my current code, http://imgur.com/iho2LDX. Does this mean the signal is time variant?
No, There is a very problem with your code. To prove that the system is time invariant we have to delay the input first and get the output and then delay the output for the same input and see whether both inputs are the same you are taking rand() which changes the input for y1 and y2 so you can never see if the system is time invariant
Here is an example for Time invariant system :
n0 = 1; %delay
n = 0:0.1:1;
x1 = [zeros(1,n0) cos(n)]%delaying the input
y1 = 2.5*x1;
x2 = [cos(n)]
y2 = [zeros(1,n0) 2.5*x2]%delaying the ouput
subplot(2,1,1)
stem(1:length(n) + 1,y1)
title('DELAYED INPUT')
subplot(2,1,2)
stem(1:length(n) + 1,y2)
title('DELAYED OUTPUT')
You can observe that the input remains the same just delayed in the input for the first time and the output is delayed for the second time but the output remains the same.
Plus one more thing your input is not time dependent xn1 and xn2 are not time dependent

Gradient descent in linear regression goes wrong

I actually want to use a linear model to fit a set of 'sin' data, but it turns out the loss function goes larger during each iteration. Is there any problem with my code below ? (gradient descent method)
Here is my code in Matlab
m=20;
rate = 0.1;
x = linspace(0,2*pi,20);
x = [ones(1,length(x));x]
y = sin(x);
w = rand(1,2);
for i=1:500
h = w*x;
loss = sum((h-y).^2)/m/2
total_loss = [total_loss loss];
**gradient = (h-y)*x'./m ;**
w = w - rate.*gradient;
end
Here is the data I want to fit
There isn't a problem with your code. With your current framework, if you can define data in the form of y = m*x + b, then this code is more than adequate. I actually ran it through a few tests where I define an equation of the line and add some Gaussian random noise to it (amplitude = 0.1, mean = 0, std. dev = 1).
However, one problem I will mention to you is that if you take a look at your sinusoidal data, you define a domain between [0,2*pi]. As you can see, you have multiple x values that get mapped to the same y value but of different magnitude. For example, at x = pi/2 we get 1 but at x = -3*pi/2 we get -1. This high variability will not bode well with linear regression, and so one suggestion I have is to restrict your domain... so something like [0, pi]. Another reason why it probably doesn't converge is the learning rate you chose is too high. I'd set it to something low like 0.01. As you mentioned in your comments, you already figured that out!
However, if you want to fit non-linear data using linear regression, you're going to have to include higher order terms to account for the variability. As such, try including second order and/or third order terms. This can simply be done by modifying your x matrix like so:
x = [ones(1,length(x)); x; x.^2; x.^3];
If you recall, the hypothesis function can be represented as a summation of linear terms:
h(x) = theta0 + theta1*x1 + theta2*x2 + ... + thetan*xn
In our case, each theta term would build a higher order term of our polynomial. x2 would be x^2 and x3 would be x^3. Therefore, we can still use the definition of gradient descent for linear regression here.
I'm also going to control the random generation seed (via rng) so that you can produce the same results I have gotten:
clear all;
close all;
rng(123123);
total_loss = [];
m = 20;
x = linspace(0,pi,m); %// Change
y = sin(x);
w = rand(1,4); %// Change
rate = 0.01; %// Change
x = [ones(1,length(x)); x; x.^2; x.^3]; %// Change - Second and third order terms
for i=1:500
h = w*x;
loss = sum((h-y).^2)/m/2;
total_loss = [total_loss loss];
% gradient is now in a different expression
gradient = (h-y)*x'./m ; % sum all in each iteration, it's a batch gradient
w = w - rate.*gradient;
end
If we try this, we get for w (your parameters):
>> format long g;
>> w
w =
Columns 1 through 3
0.128369521905694 0.819533906064327 -0.0944622478526915
Column 4
-0.0596638117151464
My final loss after this point is:
loss =
0.00154350916582836
This means that our equation of the line is:
y = 0.12 + 0.819x - 0.094x^2 - 0.059x^3
If we plot this equation of the line with your sinusoidal data, this is what we get:
xval = x(2,:);
plot(xval, y, xval, polyval(fliplr(w), xval))
legend('Original', 'Fitted');

MATLAB solve Ordinary Differential Equations

How can I use matlab to solve the following Ordinary Differential Equations?
x''/y = y''/x = -( x''y + 2x'y' + xy'')
with two known points, such as t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 ?
It doesn't need to be a complete formula if it is difficult. A numerical solution is ok, which means, given a specific t, I can get the value of x(t) and y(t).
If matlab is hard to do this, mathematica is also OK. But as I am not familiar with mathematica, so I would prefer matlab if possible.
Looking forward to help, thanks!
I asked the same question on stackexchange, but haven't get good answer yet.
https://math.stackexchange.com/questions/812985/matlab-or-mathematica-solve-ordinary-differential-equations
Hope I can get problem solved here!
What I have tried is:
---------MATLAB
syms t
>> [x, y] = dsolve('(D2x)/y = -(y*D2x + 2Dx*Dy + x*D2y)', '(D2y)/x = -(y*D2x + 2Dx*Dy + x*D2y)','t')
Error using sym>convertExpression (line 2246)
Conversion to 'sym' returned the MuPAD error: Error: Unexpected 'identifier'.
[line 1, col 31]
Error in sym>convertChar (line 2157)
s = convertExpression(x);
Error in sym>convertCharWithOption (line 2140)
s = convertChar(x);
Error in sym>tomupad (line 1871)
S = convertCharWithOption(x,a);
Error in sym (line 104)
S.s = tomupad(x,'');
Error in dsolve>mupadDsolve (line 324)
sys = [sys_sym sym(sys_str)];
Error in dsolve (line 186)
sol = mupadDsolve(args, options);
--------MATLAB
Also, I tried to add conditions, such as x(0) = 2, y(0)=8, x(1) = 7, y(1) = 18, and the errors are still similar. So what I think is that this cannot be solve by dsolve function.
So, again, the key problem is, given two known points, such as when t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 , how I get the value of x(t) and y(t)?
Update:
I tried ode45 functions. First, in order to turn the 2-order equations into 1-order, I set x1 = x, x2=y, x3=x', x4=y'. After some calculation, the equation becomes:
x(1)' = x(3) (1)
x(2)' = x(4) (2)
x(3)' = x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)) (3)
x(4)' = -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2) (4)
So the matlab code I wrote is:
myOdes.m
function xdot = myOdes(t,x)
xdot = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)]
end
main.m
t0 = 0;
tf = 1;
x0 = [2 3 5 7]';
[t,x] = ode45('myOdes',[t0,tf],x0);
plot(t,x)
It can work. However, actually this is not right. Because, what I know is that when t=0, the value of x and y, which is x(1) and x(2); and when t=1, the value of x and y. But the ode functions need the initial value: x0, I just wrote the condition x0 = [2 3 5 7]' randomly to help this code work. So how to solve this problem?
UPDATE:
I tried to use the function bvp4c after I realized that it is a boundary value problem and the following is my code (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)
It can work, but I don't know whether it is right. I will check it again to make sure it is the right code.
As mentioned, this isn't a math site, so try to give code or something showing some effort.
However, the first step you need to do is turn the DE into normal form (i.e., no 2nd derivatives). You do this by making a separate variable equal to the derivative. Then, you use
syms x y % or any variable instead of x or y
to define variables as symbolic. Use matlabfunction to create a symbolic function based on these variables. Finally, you can use the ode45 function to solve the symbolic function while passing variable values. I recommend you look up the full documentation in matlab in order to understand it better, but here is a very basic syntax:
MyFun= matlabFunction(eq,'vars',{x,y});
[xout,yout]=ode45(#(x,Y) MyFun(variables),[variable values],Options);
Hopefully this puts you in the right direction, so try messing around with it and provide code if you need more help.
EDIT:
This is how I would solve the problem. Note: I don't really like the matlabFunction creator but this is simply a personal preference for various reasons I won't go into.
% Seperate function of the first order state equations
function dz = firstOrderEqns(t,z)
dz(4,1) = 0;
dz(1) = -2.*z(3).*z(1).*z(4)./(1 + z(4).^2 + z(2).^2);
dz(2) = z(1);
dz(3) = -2.*z(2).*z(3).*z(1)./(1 + z(4).^2 + z(2).^2);
dz(4) = z(3);
end
% runfirstOrderEqns
%% Initial conditions i.e. # t=0
z1 = 5; % dy/dt = 5 (you didn't specify these initial conditions,
% these will depend on the system which you didn't really specify
z2 = 0; % y = 0
z3 = 5; % dx/dt = 5 (The same as for z1)
z4 = 0; % x = 0
IC = [z1, z2, z3, z4];
%% Run simulation
% Time vector: i.e closed interval [0,20]
t = [0,20]; % This is where you have to know about your system
% i.e what is it's time domain.
% Note: when a system has unstable poles at
% certain places the solver can crash you need
% to understand these.
% using default settings (See documentation ode45 for 'options')
[T,Y] = ode45(#firstOrderEqns,t,IC);
%% Plot function
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),':',T,Y(:,4),'.');
legend('dy/dt','y','dx/dt','x')
As in my comments I have made a lot of assumtions that you need to fix for example, you didn't specify what the initial conditions for the first derivatives of the states are i.e. (z1, z3) which is important for the response of the system. Also you didn't specify the time interval your interested for the simulation etc.
Note: The second m file can be used with any state function in the correct format
The following is the answer we finally get #Chriso: use matlab bvp4c function to solve this boundary value problem (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)