0

我在 MATLAB 中编写了一个小程序,使用 TU 游戏的多线性扩展来计算 Shapley 值。但是,我在使用 MATLAB 的符号数学工具箱时遇到了麻烦。在程序中,我必须集成一组函数来获得 Shapley 值。但是,在 MATLAB 程序中,我不能使用 int() 命令

Error using sym/subsindex (line 663) Ivalid indexing or function definition. When defining a function, ensure that the body of the function is a SYM object. When indexing, the input must be numeric, logical or ':'.

Error in ShapleyValueML (line 65)shv(jj)=int(dfy,0,1) 

因此,我必须改用integral()。在这种情况下,我需要使用 matlabFunction() 将表达式集转录为 MATLAB 函数句柄。但是,在我可以访问此命令的所有 Linux 机器(MATLAB R2014a)上都不起作用(请参阅下面的讨论)。作为一种解决方法,MATLAB 程序将函数集返回到当前工作区,在那里可以使用 int() 命令计算 Shapley 值。

为了使讨论更具体,让我们首先考虑这个小的 MATLAB 程序。

function [shv,F,dfm]=ShapleyValueML(v)

N=length(v);
[~, n]=log2(N);
S=1:N;
int=0:-1:1-n; 
mat=(rem(floor(S(:)*pow2(int)),2)==1);
cmat=(rem(floor(S(:)*pow2(int)),2)==0);
x=sym('x',[1 n]);
mx=1-x;
y = sym('y');
vy=ones(1,n)*y;
F=0;
shv=zeros(1,n);
dfm=cell(1,n);

for ss=1:N
    pd1=x(mat(ss,:));
    pd2=mx(cmat(ss,:));
    pd=prod(pd1)*prod(pd2)*v(ss);
    F=pd+F;
end
F=expand(F);

 for jj=1:n
     dF=diff(F,x(jj));
     dfy=subs(dF,x,vy);
%% Does not work!! MATLAB bug??? 
%  mf=matlabFunction(dfy);
%  shv(jj)=integral(mf,0,1);
%%
%% The best would be to use:
%%
%   shv(jj)=int(dfy,0,1)
%% but it cannot be used inside a program.
 dfm{jj}=dfy;
 end

end

注释部分是在程序内部不起作用的部分,但需要用该程序计算 Shapley 值,这就是它的目的。我测试了这个程序多达 12 名玩家,我能够通过两步程序成功计算 Shapley 值。因此,上述程序正确地指定了所考虑的问题。为了更好地理解这两个步骤的过程和上述程序的功能,让我们专注于一个三人游戏。联盟的值由以下数据数组给出

>> v = [0,0,90,0,100,120,220];

请注意,联盟根据其唯一的整数表示进行排序。定义了游戏,我们现在可以使用上述程序评估多线性扩展和偏导数集,但不能评估 Shapley 值。

>> [shv,F,dfm]=ShapleyValueML(v);

偏导数集的积分在单位立方体的对角线上运行,但是我们可以将变量从 [x1,x2,x3] 设置为 [y,y,y],并且积分从 0 运行到 1。

>> for k=1:3, shv(k)=int(dfm{k},0,1);end;

积分的解是由下式给出的 Shapley 值:

>> shv

shv =

    65    75    80

检查这确实是 Shapley 值可以通过实现的潜在函数方法来完成

>> sh_v=ShapleyValue(v)

sh_v =

     65    75    80

附带我的 MATLAB 博弈论工具箱 MatTuGames

http://www.mathworks.com/matlabcentral/fileexchange/35933-mattugames

除了与 int() 集成,还可以使用integral(),但内容如下

>> dfm{1}

ans =

    - 90*y^2 + 190*y

必须用 matlabFunction() 重写为函数句柄。正如我上面提到的,这在 Linux 下不起作用(MATLAB R2013a、R2013b、R2014a)。要看到这一点,让我们尝试重现该示例

>> syms x y
>> r = sqrt(x^2 + y^2);

来自 URL 上的文档:

http://www.mathworks.de/de/help/symbolic/generate-matlab-functions.html?searchHighlight=matlabFunction

这应该给

ht = 
@(x,y)tanh(sqrt(x.^2+y.^2))

但我明白了

>> ht = matlabFunction(tanh(r))
   Cell contents reference from a non-cell array object.

   Error in vectorize (line 15)
    c = cells{i};

   Error in sym/matlabFunction>mup2mat (line 319)
   res = vectorize(res(2:end-1)); % remove quotes

   Error in sym/matlabFunction>mup2matcell (line 304)
    r = mup2mat(c{1});

   Error in sym/matlabFunction (line 123)
   body = mup2matcell(funs);

现在我的问题来了:Exists there an alternative procedure to get from

>> dfm{1}

ans =

  - 90*y^2 + 190*y

函数句柄

>> df=@(y) (- 90.*y.^2 + 190.*y)

 df = 

    @(y)(-90.*y.^2+190.*y)

通过整合它

>> integral(df,0,1)

ans =

   65

或者换一种说法。是否有另一种方法可以将乘法 * 更改为逐元素乘法 .*,并将幂运算 ^ 更改为逐元素幂。^?

当然,对上述 MATLAB 程序的任何改进建议都非常感谢。


4

1 回答 1

2

我想我知道问题出在哪里;在函数的开头ShapleyValueML,您有一个名为的变量int,它隐藏了内置集成函数

...

int=0:-1:1-n;    %# <-- problem!

...

shv(jj)=int(dfy,0,1)

...

这解释了错误来自sym/subsindex,您使用符号对象作为数字数组的索引int

将变量名称更改为其他名称,注释代码运行良好(符号集成)!就那么简单 :)

于 2014-09-28T15:38:52.463 回答