I am trying to implement the quantile regression process with a simple setup in Matlab. This page contains a description of the quantile regression as a linear program, and displays the appropriate matrices and vectors. I've tried to implement it in Matlab, but I do not get the correct last element of the bhat vector. It should be around 1 but I get a very low value (<1e-10). Using another algorithm I have, I get a value of 1.0675. Where did I go wrong? I'm guessing A, b or f are wrong.
I have tried playing with optimset, but I don't think that is the problem. I think I've made a conversion mistake when going from math to code, I just can't see where.
% set seed
rng(1);
% set parameters
n=30;
tau=0.5;
% create regressor and regressand
x=rand(n,1);
y=x+rand(n,1)/10;
% number of regressors (1)
m=size(x,2);
% vektors and matrices for linprog
f=[tau*ones(n,1);(1-tau)*ones(n,1);zeros(m,1)];
A=[eye(n),-eye(n),x;
-eye(n),eye(n),-x;
-eye(n),zeros(n),zeros(n,m);
zeros(n),-eye(n),zeros(n,m)];
b=[y;
y
zeros(n,1);
zeros(n,1)];
% get solution bhat=[u,v,beta] and exitflag (1=succes)
[bhat,~,exflag]=linprog(f',A,b);
I solved my problem by using the formulation (in the pdf) above the one I tried to implement in the question. I've put it in a Matlab-function if you're interested in the code.
function [ bhat ] = qregressMatlab( y, x, tau )
% bhat are the estimates
% y is a vector of outcomes
% x is a matrix with columns of explanatory variables
% tau is a scalar for choosing the conditional quantile to be estimated
n=size(x,1);
m=size(x,2);
% vectors and matrices for linprog
f=[tau*ones(n,1);(1-tau)*ones(n,1);zeros(m,1)];
Aeq=[eye(n),-eye(n),x];
beq=y;
lb=[zeros(n,1);zeros(n,1);-inf*ones(m,1)];
ub=inf*ones(m+2*n,1);
% Solve the linear programme
[bhat,~,~]=linprog(f,[],[],Aeq,beq,lb,ub);
% Pick out betas from (u,v,beta)-vector.
bhat=bhat(end-m+1:end);
end
Related
I am trying to tune a PID controller using Matlab(not Simulink because I am learning/uni coursework).
1. Summarize the problem:
So, I have a transfer function of a system for which there are phase margin requirement that needs to met
In order to find the phase advance part of the PID I need to solve a bunch of equations to plot a Bode plot using the variables calculated
2.Describe what I've tried
I tried to replace the tf([num],[den]) with real numbers but that is not feasible as it defeats the purpose of doing this, I want Matlab to calculate the GR and frequency and substitute that into the tf
Problem
Full_Code:
https://drive.google.com/file/d/1sWUnvvye_RBXGL8-nWq___3F5UDmDOoG/view?usp=sharing
Minimum reproducible code example:
clearvars;clc;clearAllMemoizedCaches;clear
syms s w
%--------------TF of the aircraft
G(s)= (160*(s+2.5)*(s+0.7))/((s^2+5*s+40)*(s^2+0.03*s+0.06));
k= 8; % selected k value range 4<k<8
Max_PA=asind((k-1)/(k+1)); % computes max phase advance
Centre_dB= 20*log10(sqrt(k)); % computing centre gain in dB
Poi= -120-Max_PA % looking for Point of interest(Poi)
tf_int= subs(G(s),1j*w); %intermediate transfer function
eqn= atan2d(imag(tf_int),real(tf_int))==Poi; % solve for w at Poi
% computing crossover freq(wc)
wc= vpasolve(eqn,w); % find exactly the wc at Poi
GR=20*log10(abs(subs(tf_int,w,wc))); % find the gain at at wc
Kpa= 10^((GR-Centre_dB)/20);
ti= 1/(sqrt(k)*wc); % computing Kpa and ti
num1= [Kpa*k*ti,Kpa];
den2= [ti,1];
PA= tf(num1,den2) %PA tf defined
Yo are trying to input non-numerical (symbolic numers) values into tf, which only accepts numerical arrays. You can convert them to that with double()
PA= tf(double(num1),double(den2)) %PA tf defined
I am quite new to Matlab so I apologize if I am making some obvious mistakes, but I have a second order ordinary differential equation that I am trying to plot the vector field of. I have looked at various resources on this site, the MATLAB documentation and MATLAB forums but I am still having trouble.
I have tried solving the ODE with the ode45 function, this gives my a single solution that I can plot. I am using the function odeToVectorField to transform my ODE into a system of first order ODE. I have a feeling this is what is preventing me from properly doing what I want because it give me a set of symbolic equations that I am difficulty to evaluate over the meshgrid.
Here is my code so far:
% Setup outside variables
clear
mu = 0.75; % resistance variable
l = 1; % length of pendulum
g = 9.81; % gravity
% Next we setup the domains of the vector space.
xdom = linspace(-pi,pi,51); % define the X axis space
ydom = linspace(-pi,pi,51); % define the Y axis space
[X,Y] = meshgrid(xdom,ydom); % create a meshgrid for the vector field
% Define the system of ODEs
syms y(t)
eqn = diff(y,t,2) == - mu.*diff(y,t,1) - (g/l).*sin(diff(y,t,0));
U = odeToVectorField(eqn) % this is the part where I think I am doing wrong
Uf = matlabFunction(U(1), 'vars',{'t','Y'}) % trying to set a function handle for the first ODE
Vf = matlabFunction(U(2), 'vars',{'t','Y'}) % trying to set a function handle for the second ODE
% Now we plot it
figure
quiver(X,Y,Uf(X,Y), Vf(X,Y))
Here is a screenshot of my output. I have purposefully left out some semi colons to help you visualize what I am trying to do.
Thank you very much for your help.
This code is to find the Euler's method on MATLAB
function [x,y]=euler_forward(f,xinit,yinit,xfinal,n)
h=(xfinal-xinit)/n;
% Initialization of x and y as column vectors
x=[xinit zeros(1,n)]; y=[yinit zeros(1,n)];
% Calculation of x and y
for i=1:n
x(i+1)=x(i)+h;
y(i+1)=y(i)+h*f(x(i),y(i));
end
end`
'f=#(x,y) (1+2*x)*sqrt(y);
% Calculate exact solution
g=#(x,y) (1+2*x)*sqrt(y);
xe=[0:0.01:1];
ye=g(xe);
[x1,y1]=euler_forward(f,0,1,1,4);
% Plot
plot(xe,ye,'k-',x1,y1,'k-.')
xlabel('x')
ylabel('y')
legend('Analytical','Forward')
% Estimate errors
error1=['Forward error: ' num2str(-100*(ye(end)-y1(end))/ye(end)) '%'];
error={error1}
So I have this so far for the problem and the it gives an error saying y is not defined. What do I do?
The problem is here:
% Calculate exact solution
g=#(x,y) (1+2*x)*sqrt(y);
Exact solution is a function of one variable, x. Presumably, you were supposed to find it with paper and pencil (or with Wolfram Alpha, etc): it is
g=#(x) .25*(x.^2+x+2).^2
Then the code works as expected, producing this neat chart: as is typical for Euler's method, the numerical solution lags behind the exact one.
I have a matrix z(x,y)
This is an NxN abitary pdf constructed from a unique Kernel density estimation (i.e. not a usual pdf and it doesn't have a function). It is multivariate and can't be separated and is discrete data.
I wan't to construct a NxN matrix (F(x,y)) that is the cumulative distribution function in 2 dimensions of this pdf so that I can then randomly sample the F(x,y) = P(x < X ,y < Y);
Analytically I think the CDF of a multivariate function is the surface integral of the pdf.
What I have tried is using the cumsum function in order to calculate the surface integral and tested this with a multivariate normal against the analytical solution and there seems to be some discrepancy between the two:
% multivariate parameters
delta = 100;
mu = [1 1];
Sigma = [0.25 .3; .3 1];
x1 = linspace(-2,4,delta); x2 = linspace(-2,4,delta);
[X1,X2] = meshgrid(x1,x2);
% Calculate Normal multivariate pdf
F = mvnpdf([X1(:) X2(:)],mu,Sigma);
F = reshape(F,length(x2),length(x1));
% My attempt at a numerical surface integral
FN = cumsum(cumsum(F,1),2);
% Normalise the CDF
FN = FN./max(max(FN));
X = [X1(:) X2(:)];
% Analytic solution to a multivariate normal pdf
p = mvncdf(X,mu,Sigma);
p = reshape(p,delta,delta);
% Highlight the difference
dif = p - FN;
error = max(max(sqrt(dif.^2)));
% %% Plot
figure(1)
surf(x1,x2,F);
caxis([min(F(:))-.5*range(F(:)),max(F(:))]);
xlabel('x1'); ylabel('x2'); zlabel('Probability Density');
figure(2)
surf(X1,X2,FN);
xlabel('x1'); ylabel('x2');
figure(3);
surf(X1,X2,p);
xlabel('x1'); ylabel('x2');
figure(5)
surf(X1,X2,dif)
xlabel('x1'); ylabel('x2');
Particularly the error seems to be in the transition region which is the most important.
Does anyone have any better solution to this problem or see what I'm doing wrong??
Any help would be much appreciated!
EDIT: This is the desired outcome of the cumulative integration, The reason this function is of value to me is that when you randomly generate samples from this function on the closed interval [0,1] the higher weighted (i.e. the more likely) values appear more often in this way the samples converge on the expected value(s) (in the case of multiple peaks) this is desired outcome for algorithms such as particle filters, neural networks etc.
Think of the 1-dimensional case first. You have a function represented by a vector F and want to numerically integrate. cumsum(F) will do that, but it uses a poor form of numerical integration. Namely, it treats F as a step function. You could instead do a more accurate numerical integration using the Trapezoidal rule or Simpson's rule.
The 2-dimensional case is no different. Your use of cumsum(cumsum(F,1),2) is again treating F as a step function, and the numerical errors resulting from that assumption only get worse as the number of dimensions of integration increases. There exist 2-dimensional analogues of the Trapezoidal rule and Simpson's rule. Since there's a bit too much math to repeat here, take a look here:
http://onestopgate.com/gate-study-material/mathematics/numerical-analysis/numerical-integration/2d-trapezoidal.asp.
You DO NOT need to compute the 2-dimensional integral of the probability density function in order to sample from the distribution. If you are computing the 2-d integral, you are going about the problem incorrectly.
Here are two ways to approach the sampling problem.
(1) You write that you have a kernel density estimate. A kernel density estimate is a special case of a mixture density. Any mixture density can be sampled by first selecting one kernel (perhaps differently or equally weighted, same procedure applies), and then sampling from that kernel. (That applies in any number of dimensions.) Typically the kernels are some relatively simple distribution such as a Gaussian distribution so that it is easy to sample from it.
(2) Any joint density P(X, Y) is equal to P(X | Y) P(Y) (and equivalently P(Y | X) P(X)). Therefore you can sample from P(Y) (or P(X)) and then from P(X | Y). In order to sample from P(X | Y), you will need to integrate P(X, Y) along a line Y = y (where y is the sampled value of Y), but (this is crucial) you only need to integrate along that line; you don't need to integrate over all values of X and Y.
If you tell us more about your problem, I can help with the details.
I'm a beginner to matlab coding so any help would be appreciated.
I'm trying to minimize difference of summation squared problem SUM((a-b)^2) for 2 variables. I've already coded it up in Excel's Solver like this:
Goal= Sum[{i, 9}, ( Y[i]- (X[i]*m+b) )^2 ]
using nonlinear methods.
where Y and X and arrays, and m and b are the variables we are trying to find by minimizing the sum. How would go do this same thing in Matlab?
thanks.
Here is an example. I've set the bounds by using fmincon.
x=0:10;
y=x*randi(10)-randi(10)+rand(size(x)); % Create data y
f=#(A) sum((y-(A(1)*x+A(2))).^2) % Test function that we wish to minimise
R=fmincon(f,[1 1],[],[],[],[],[0 0],[Inf Inf]) % Run the minimisation R(1)=m, R(2)=b
plot(x,y,x,R(1)*x+R(2)) % Plot the results