我在 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 上的文档:
这应该给
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 程序的任何改进建议都非常感谢。