我意识到使用feval动态调用函数效率很低,但在我的应用程序中它非常方便,而且运行良好,除了一个函数的情况。我只是不知道是什么原因导致了这个问题。这个函数在以通常的方式调用时运行良好,但在使用feval调用时会引发错误(下面的最后一行):
x = 200;
[y_mean, y_sigma, y_int] = lin_model_predict(model, x, vars, params); % works fine
assert(round(y_mean, 4) == 139.7200);
assert(isequaln(y_sigma, nan));
assert(isequal(round(y_int, 4), [137.5938 141.8462]));
% Test again using feval
f_name = "lin_model_predict"; % this will later be set programatically
[y_mean, y_sigma, y_int] = feval(f_name, model, x, vars, params); % raises error
我包括以下函数代码供参考:
function [y_mean, y_sigma, y_int] = lin_model_predict(model, x, vars, ...
params)
% [y_mean, y_sigma, x_int] = lin_model_predict(model, x, vars, params)
% Make predictions with a linear model of the form:
%
% power = a + b * load
%
% Make predictions using model
[y_mean, y_int] = predict(model, x, 'Alpha', vars.significance);
% TODO: Is there a need for sigma estimates?
y_sigma = nan(size(x));
end
完整错误消息:
Error using classreg.regr/CompactPredictor/feval
Too many output arguments.
Error in test_lin_models (line 46)
[y_mean, y_sigma, y_int] = feval(f_name, model, x, vars, params);
Matlab版本:小行星2021
更新
将最后一行替换为:
a = feval(f_name, model, x, vars, params);
我发现它需要一个输出参数。
通过调试这个调用,我发现它调用的是CompactPredictor.m中某个类的方法,位置如下:
/应用程序/MATLAB_R2021b.app/工具箱/统计信息/类规则/+类规则/+规则/紧凑型预测器.m
从该函数的文档字符串中:
function yPred = feval(model,varargin)
%FEVAL Evaluate model as a function
% YPRED = FEVAL(M,X1,X2,...Xp) computes an array YPRED of predicted
% values from the regression model M using predictor values X1, X2, ...,
% Xp, where P is the number of predictors in M. Each X argument must be
% the same size, and must have the same type as the corresponding
% predictor variable. The size of the YPRED output is the same as the
% common size of the X inputs.
在本例中,模型参数现在是字符串"lin_model_predict"
,这将引发新的错误Unrecognized method, property, or field 'NumPredictors' for class 'string'.
所以在我看来feval的标准用法已经被这个类方法劫持了。
不知道该怎么避免,有什么想法吗?
我决定在Mathworks论坛上发布这个问题,因为它可能需要Maven的投入:
请随意在此处或此处添加答案。
1条答案
按热度按时间gdrx4gfi1#
在你这行
其中一个参数是
CompactPredictor
类(可能是model
?),它触发了feval
的重载版本被调用。这就是MATLAB如何进行重载解析的。有几种方法可以解决这个问题,一种是不使用这个类的对象,可以写
lin_model_predict
来获取一个单元格数组作为输入,这样你就可以用lin_model_predict({model, x, vars, params})
来调用它;另一种是使用builtin
:第三种解决方案是不使用
feval
,而是编写一个函数来调用正确的函数:正如用户horchler在评论中所写的,函数句柄是一种比字符串更简洁的引用函数的方式,使用函数句柄可以:
但在某些情况下,只有字符串才有意义:可能被引用的函数是私有函数,您不希望调用者直接访问它们;或者字符串来自GUI或配置文件中的下拉菜单。在这些情况下,您可以使用表查找将字符串转换为函数句柄,请参见
containers.Map
或dictionary
(自R2022 b起)。