如何使用 Matlab 中先前调用的新输入参数和输出参数创建函数的函数句柄?
How to create a function handle of a function with both new input parameters and output parameters from previous call in Matlab?
我正在尝试创建一个函数和所述函数的函数句柄,其中该函数接收上一次调用的输出参数和新的输入参数,并计算函数中的梯度,如下面的玩具示例所示.我想将函数句柄传递给 hmcSampler
。但是,我在创建函数句柄时遇到问题,需要一些帮助。
澄清一下:我想用 theta
的新值调用 logPosterior
,而且还要用上次调用的 theta
和 logpdf
输出。我需要通过一个函数句柄来执行此操作,该函数句柄将被我无法控制的函数多次调用,因此我需要 logPosterior
或其句柄来管理旧值的存储。在第一次调用中,theta
和 old_theta
应该有不同的值,这样函数才能运行。
%% Toy implementation of hmcsampler class in Matlab
NumPredictors = 2;
trueIntercept = 2;
trueBeta = [3;0];
NumData = 100;
rng('default') %For reproducibility
X = rand(NumData,NumPredictors);
mu = X*trueBeta + trueIntercept;
y = mu;
% define the mean and variance of normal distribution of each parameter
means = [0; 0];
standevs = [1;1];
% create multivariate normal log probability distribution
[logpdf, grad_logpdf] = @(theta)logPosterior(theta, old_theta, X, y, means, standevs, old_logpdf); % <- How to write this?
% create the startpoint from which sampling starts
startpoint = randn(2, 1);
% create an HMC sampler object
smp = hmcSampler(logpdf, startpoint);
% estimate maximum of log probability density
[xhat, fitinfo] = estimateMAP(smp);
num_chains = 4;
chains = cell(num_chains, 1);
burnin = 50000;
num_samples = 2000000;
function [logpdf, grad_logpdf] = logPosterior(theta, old_theta, X, y, means, standevs, old_logpdf)
% values
intercept = theta(1);
beta = theta(2:end);
y_computed = X*beta + intercept;
log_likelihood = log(y_computed);
del_loglikelihood = log_likelihood - old_logpdf;
del_params = theta - old_theta;
grad_params1 = del_loglikelihood/del_params;
% compute log priors and gradients of parameters
log_prior_params = 0;
grad_params2 = [];
for i = 1:3
[lp, grad] = normalDistGrad(theta(i), means(i), standevs(i));
log_prior_params = log_prior_params + lp;
grad_params2 = [grad_params2; grad];
end
% return the log posterior and its gradient
logpdf = log_likelihood + log_prior_params;
grad_logpdf = grad_params1 + grad_params2;
end
function [lpdf,glpdf] = normalDistGrad(X, Mu, Sigma)
Z = (X - Mu)./Sigma;
lpdf = sum(-log(Sigma) - .5*log(2*pi) - .5*(Z.^2));
glpdf = -Z./Sigma;
end
首先在当前路径中的单独 m 文件中定义函数 :
function [o1,o2]=myfunc(in1,in2,in3)
o1=in1+in2+in3;
o2=in3-in2;
end
然后创建函数句柄:
f=@myfunc;
f(1,2,3)
ans= 6
仅使用其中一个输入:
f=@(x)myfunc(x,3,5);
f(1)
ans=9
获得两个输出:
[a,b]=f(1);
或者在你的函数中定义一个输出并在调用它们之后引用它们的索引:
function o=myfunc(in1,in2,in3)
o1=in1+in2+in3;
o2=in3-in2;
o=[o1,o2];
end
...
我将按如下方式实现 logPosterior
以跟踪上次函数调用中的值。 persistent
变量是函数的局部变量,但在调用之间持续存在,使其成为为函数提供内存的理想工具。
function [logpdf, grad_logpdf] = logPosterior(theta, X, y, means, standevs)
persistent old_theta old_logpdf
if isempty(old_theta)
% function hasn't been called before, initialize the old values:
old_theta = zeros(size(theta));
old_logpdf = 0; % adjust to be meaningful initial values
end
% ... (your original function code here)
% save new values as old values for next call
old_theta = theta;
old_logpdf = logpdf;
end
您现在将采用如下函数句柄:
func = @(theta)logPosterior(theta, X, y, means, standevs);
func
是您传递给调用它的任何函数的句柄。您可以通过 运行 您的函数初始化一次先前的变量(我不确定什么是合适的初始化!):
func(startpoint);
smp = hmcSampler(func, startpoint);
我正在尝试创建一个函数和所述函数的函数句柄,其中该函数接收上一次调用的输出参数和新的输入参数,并计算函数中的梯度,如下面的玩具示例所示.我想将函数句柄传递给 hmcSampler
。但是,我在创建函数句柄时遇到问题,需要一些帮助。
澄清一下:我想用 theta
的新值调用 logPosterior
,而且还要用上次调用的 theta
和 logpdf
输出。我需要通过一个函数句柄来执行此操作,该函数句柄将被我无法控制的函数多次调用,因此我需要 logPosterior
或其句柄来管理旧值的存储。在第一次调用中,theta
和 old_theta
应该有不同的值,这样函数才能运行。
%% Toy implementation of hmcsampler class in Matlab
NumPredictors = 2;
trueIntercept = 2;
trueBeta = [3;0];
NumData = 100;
rng('default') %For reproducibility
X = rand(NumData,NumPredictors);
mu = X*trueBeta + trueIntercept;
y = mu;
% define the mean and variance of normal distribution of each parameter
means = [0; 0];
standevs = [1;1];
% create multivariate normal log probability distribution
[logpdf, grad_logpdf] = @(theta)logPosterior(theta, old_theta, X, y, means, standevs, old_logpdf); % <- How to write this?
% create the startpoint from which sampling starts
startpoint = randn(2, 1);
% create an HMC sampler object
smp = hmcSampler(logpdf, startpoint);
% estimate maximum of log probability density
[xhat, fitinfo] = estimateMAP(smp);
num_chains = 4;
chains = cell(num_chains, 1);
burnin = 50000;
num_samples = 2000000;
function [logpdf, grad_logpdf] = logPosterior(theta, old_theta, X, y, means, standevs, old_logpdf)
% values
intercept = theta(1);
beta = theta(2:end);
y_computed = X*beta + intercept;
log_likelihood = log(y_computed);
del_loglikelihood = log_likelihood - old_logpdf;
del_params = theta - old_theta;
grad_params1 = del_loglikelihood/del_params;
% compute log priors and gradients of parameters
log_prior_params = 0;
grad_params2 = [];
for i = 1:3
[lp, grad] = normalDistGrad(theta(i), means(i), standevs(i));
log_prior_params = log_prior_params + lp;
grad_params2 = [grad_params2; grad];
end
% return the log posterior and its gradient
logpdf = log_likelihood + log_prior_params;
grad_logpdf = grad_params1 + grad_params2;
end
function [lpdf,glpdf] = normalDistGrad(X, Mu, Sigma)
Z = (X - Mu)./Sigma;
lpdf = sum(-log(Sigma) - .5*log(2*pi) - .5*(Z.^2));
glpdf = -Z./Sigma;
end
首先在当前路径中的单独 m 文件中定义函数 :
function [o1,o2]=myfunc(in1,in2,in3)
o1=in1+in2+in3;
o2=in3-in2;
end
然后创建函数句柄:
f=@myfunc;
f(1,2,3)
ans= 6
仅使用其中一个输入:
f=@(x)myfunc(x,3,5);
f(1)
ans=9
获得两个输出:
[a,b]=f(1);
或者在你的函数中定义一个输出并在调用它们之后引用它们的索引:
function o=myfunc(in1,in2,in3)
o1=in1+in2+in3;
o2=in3-in2;
o=[o1,o2];
end
...
我将按如下方式实现 logPosterior
以跟踪上次函数调用中的值。 persistent
变量是函数的局部变量,但在调用之间持续存在,使其成为为函数提供内存的理想工具。
function [logpdf, grad_logpdf] = logPosterior(theta, X, y, means, standevs)
persistent old_theta old_logpdf
if isempty(old_theta)
% function hasn't been called before, initialize the old values:
old_theta = zeros(size(theta));
old_logpdf = 0; % adjust to be meaningful initial values
end
% ... (your original function code here)
% save new values as old values for next call
old_theta = theta;
old_logpdf = logpdf;
end
您现在将采用如下函数句柄:
func = @(theta)logPosterior(theta, X, y, means, standevs);
func
是您传递给调用它的任何函数的句柄。您可以通过 运行 您的函数初始化一次先前的变量(我不确定什么是合适的初始化!):
func(startpoint);
smp = hmcSampler(func, startpoint);