简体   繁体   中英

How to determine the size of an input argument for a function handle

I am creating a function that takes in data ( x,y,z ) and an anonymous function ( M ) as inputs. M 's inputs are data ( x,y,z ) and a parameter ( theta ).

I need to determine the dimension of the parameter theta inside FUNC

EDIT: (To add some context)

I have data that follows a known data generating process (DGP). For example, I can generate data using a linear instrumental variable DGP with 1 endogenous variable (hence theta will be dimension 1):

n = 100; q = 10;
theta0 = 1;                               % true param value
e = randn(n, 1);                          % 2nd stage error
u = randn(n, 1);                          % 1st stage error
z = randn(n, q);                          % instrument
x = z * ones(q, 1) + u;                   % endog variable
y = x * theta0 + e;                       % dependent variable

Then I want to estimate theta0 using my own variation of generalized linear methods ( FUNC )

M = @(x,y,z,theta) z' * (y - x * theta);  % moment condition
thetahat = FUNC(M, x, y, z);              % estimate theta0

and FUNC.m is

function out = FUNC(M, x, y, z)
k = ; % (!!!) <-- this is what I need to find out!
objFunc = @(theta) M(x, y, z, theta)' * M(x, y, z, theta);
out = fminunc(objFunc, ones(1, k)); % <-- this is where its used
end

In the above example, the DGP is a linear IV model. However, I should be able to use my function for any other DGP.

Other DGPs could, for example, define M as follows:

% E.g. 1) theta is dimension 1
M=@(x,y,z,theta) z' * (y - x * theta); 
% E.g. 2) theta is dimension 2
M=@(x,y,z,theta) z' * (y - (x * theta(1))^theta(2)); 
% E.g. 3) theta is dimension 3
M=@(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3)); 

The (super bad) hack that I am currently using for (!!!) is:

for ktest = [3,2,1] % the dimension of theta will never be higher than 3
    try 
        M(x, y, z, ones(1, ktest);
        k = ktest;     
    end
end

Since you know already what the form and requirements of your function M will be when you pass it to FUNC , it doesn't make much sense to then require FUNC to determine it based only on M . It would make much more sense to pass flag values or needed information to FUNC when you pass it M . I would write FUNC in one of two ways:

function out = FUNC(M, x, y, z, k)  % Accept k as an argument
  ...
end

function out = FUNC(M, x, y, z, theta0)  % Pass the initial guess, of the correct size
  ...
end

If you really want to let FUNC do the extra work, then the answer from excaza is how I would do it.



Old answer below. not really valid since the question was clarified, but I'm leaving it temporarily...

I think you have two better options here...

Make M a cell array of anonymous functions:

You could make your input M a cell array of possible anonymous functions and use the number of values in theta as the index. You would pass this M to FUNC :

M = {@(x,y,z,theta) z' * (y - x * theta), ...
     @(x,y,z,theta) z' * (y - (x * theta(1))^theta(2)), ...
     @(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3))};

Then somewhere inside FUNC :

out = M{numel(theta)}(x, y, z, theta);

Make M a normal function instead of an anonymous one:

An anonymous function is good for quick, simple formulas. Add in conditional logic and you should probably just make it a fully-fledged function . Here's an example with a switch statement (good for if you have a number of different formulas):

function out = M(x, y, x, theta)
  switch numel(theta)
    case 1
      out = z' * (y - x * theta);
    case 2
      out = z' * (y - (x * theta(1))^theta(2));
    case 3
      out = z' * (y - (theta(1) + x * theta(2))^theta(3));
  end
end

And here's an example that sets some defaults for parameters (good for if you have one formula with different ways to set its parameters, like you seem to have):

function out = M(x, y, x, theta)
  switch numel(theta)
    case 1
      p1 = 0;
      p2 = theta;
      p3 = 1;
    case 2
      p1 = 0;
      p2 = theta(1);
      p3 = theta(2);
    case 3
      p1 = theta(1);
      p2 = theta(2);
      p3 = theta(3);
  end
  out = z' * (y - (p1 + x * p2)^p3);
end

MATLAB doesn't store any information about the size of the inputs to an anonymous function. While a better idea would be to modify your code so you don't have to do these kinds of gymnastics, if your function definition is known to fit a narrow band of possibilities you could use a regular expression to parse the function definition itself. You can get this string from the return of functions .

For example:

function [nelements] = findsizetheta(fh)
defstr = func2str(fh);
test = regexp(defstr, 'theta\((\d+)\)', 'tokens');

if isempty(test)
    % Assume we have theta instead of theta(1)
    nelements = 1;
else
    nelements = max(str2double([test{:}]));
end
end

Which returns 1 , 2 , and 3 for your example definitions of M .

This assumes that theta is present in you anonymous function and that it is defined as a vector.

Also note that MATLAB cautions against utilizing functions in a programmatic manner, as its behavior may change in future releases. This was tested to function in R2017b.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM